Refactor config wizard
Deduplicated zig finder and added `zls config` subcommand
This commit is contained in:
		
							parent
							
								
									ba668094ad
								
							
						
					
					
						commit
						2fc9506fdc
					
				| @ -85,6 +85,8 @@ The following options are currently available. | ||||
| | `enable_semantic_tokens` | `bool` | `true` | Enables semantic token support when the client also supports it. | | ||||
| | `operator_completions` | `bool` | `true` | Enables `*` and `?` operators in completion lists. | | ||||
| | `skip_std_references` | `bool` | `false` | When true, skips searching for references in std. Improves lookup speed for functions in user's code. Renaming and go-to-definition will continue to work as is. | ||||
| | `include_at_in_builtins` | `bool` | `false` | Most editors (except Sublime Text, it seems) generate a duplicate @ if a completion starts with it. | ||||
| | `max_detail_length` | `usize` | `1048576` | Completion detail fields are truncated to this length. Decrease if previews lag your editor. | ||||
| 
 | ||||
| ## Features | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										194
									
								
								build.zig
									
									
									
									
									
								
							
							
						
						
									
										194
									
								
								build.zig
									
									
									
									
									
								
							| @ -2,202 +2,12 @@ const std = @import("std"); | ||||
| const builtin = @import("builtin"); | ||||
| // const build_options = @import("build_options") | ||||
| 
 | ||||
| const zinput = @import("src/zinput/src/main.zig"); | ||||
| const setup = @import("src/setup.zig"); | ||||
| 
 | ||||
| var builder: *std.build.Builder = undefined; | ||||
| 
 | ||||
| pub fn config(step: *std.build.Step) anyerror!void { | ||||
|     @setEvalBranchQuota(2500); | ||||
|     std.debug.warn("Welcome to the ZLS configuration wizard! (insert mage emoji here)\n", .{}); | ||||
| 
 | ||||
|     var zig_exe_path: ?[]const u8 = null; | ||||
|     std.debug.print("Looking for 'zig' in PATH...\n", .{}); | ||||
|     find_zig: { | ||||
|         const allocator = builder.allocator; | ||||
|         const env_path = std.process.getEnvVarOwned(allocator, "PATH") catch |err| switch (err) { | ||||
|             error.EnvironmentVariableNotFound => { | ||||
|                 break :find_zig; | ||||
|             }, | ||||
|             else => return err, | ||||
|         }; | ||||
|         defer allocator.free(env_path); | ||||
| 
 | ||||
|         const exe_extension = @as(std.zig.CrossTarget, .{}).exeFileExt(); | ||||
|         const zig_exe = try std.fmt.allocPrint(allocator, "zig{s}", .{exe_extension}); | ||||
|         defer allocator.free(zig_exe); | ||||
| 
 | ||||
|         var it = std.mem.tokenize(env_path, &[_]u8{std.fs.path.delimiter}); | ||||
|         while (it.next()) |path| { | ||||
|             const resolved_path = try std.fs.path.resolve(allocator, &[_][]const u8{path}); | ||||
|             defer allocator.free(resolved_path); | ||||
|             const full_path = try std.fs.path.join(allocator, &[_][]const u8{ | ||||
|                 resolved_path, | ||||
|                 zig_exe, | ||||
|             }); | ||||
|             defer allocator.free(full_path); | ||||
| 
 | ||||
|             if (!std.fs.path.isAbsolute(full_path)) continue; | ||||
|             // Skip folders named zig | ||||
|             const file = std.fs.openFileAbsolute(full_path, .{}) catch continue; | ||||
|             const stat = file.stat() catch continue; | ||||
|             const is_dir = stat.kind == .Directory; | ||||
|             if (is_dir) continue; | ||||
| 
 | ||||
|             var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; | ||||
|             zig_exe_path = try std.mem.dupe(allocator, u8, std.os.realpath(full_path, &buf) catch continue); | ||||
|             break :find_zig; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (zig_exe_path == null) { | ||||
|         std.debug.print("Could not find 'zig' in PATH\n", .{}); | ||||
|         zig_exe_path = try zinput.askString(builder.allocator, "What is the path to the 'zig' executable you would like to use?", 512); | ||||
|     } else { | ||||
|         std.debug.print("Found zig executable '{s}'\n", .{zig_exe_path.?}); | ||||
|     } | ||||
| 
 | ||||
|     const editor = try zinput.askSelectOne("Which code editor do you use?", enum { VSCode, Sublime, Kate, Neovim, Vim8, Emacs, Doom, Other }); | ||||
|     const snippets = try zinput.askBool("Do you want to enable snippets?"); | ||||
|     const style = try zinput.askBool("Do you want to enable style warnings?"); | ||||
|     const semantic_tokens = try zinput.askBool("Do you want to enable semantic highlighting?"); | ||||
|     const operator_completions = try zinput.askBool("Do you want to enable .* and .? completions?"); | ||||
|     const include_at_in_builtins = switch (editor) { | ||||
|         .Sublime => | ||||
|             true, | ||||
|         .VSCode, | ||||
|         .Kate, | ||||
|         .Neovim, | ||||
|         .Vim8, | ||||
|         .Emacs, | ||||
|         .Doom => | ||||
|             false, | ||||
|         else => | ||||
|             try zinput.askBool("Should the @ sign be included in completions of builtin functions?\nChange this later if `@inc` completes to `include` or `@@include`") | ||||
|     }; | ||||
|     const max_detail_length: usize = switch (editor) { | ||||
|         .Sublime => | ||||
|             256, | ||||
|         else => | ||||
|             1024 * 1024 | ||||
|     }; | ||||
|      | ||||
|     var dir = try std.fs.cwd().openDir(builder.exe_dir, .{}); | ||||
|     defer dir.close(); | ||||
| 
 | ||||
|     var file = try dir.createFile("zls.json", .{}); | ||||
|     defer file.close(); | ||||
| 
 | ||||
|     const out = file.writer(); | ||||
| 
 | ||||
|     std.debug.warn("Writing to config...\n", .{}); | ||||
| 
 | ||||
|     const content = std.json.stringify(.{ | ||||
|         .zig_exe_path = zig_exe_path, | ||||
|         .enable_snippets = snippets, | ||||
|         .warn_style = style, | ||||
|         .enable_semantic_tokens = semantic_tokens, | ||||
|         .operator_completions = operator_completions, | ||||
|         .include_at_in_builtins = include_at_in_builtins, | ||||
|         .max_detail_length = max_detail_length, | ||||
|     }, std.json.StringifyOptions{}, out); | ||||
| 
 | ||||
|     std.debug.warn("Successfully saved configuration options!\n", .{}); | ||||
|     std.debug.warn("\n", .{}); | ||||
| 
 | ||||
|     switch (editor) { | ||||
|         .VSCode => { | ||||
|             std.debug.warn( | ||||
|                 \\To use ZLS in Visual Studio Code, install the 'ZLS for VSCode' extension. | ||||
|                 \\Then, open VSCode's 'settings.json' file, and add `"zigLanguageClient.path": "[command_or_path_to_zls]"`. | ||||
|             , .{}); | ||||
|         }, | ||||
|         .Sublime => { | ||||
|             std.debug.warn( | ||||
|                 \\To use ZLS in Sublime, install the `LSP` package from `https://github.com/sublimelsp/LSP/releases` or via Package Control. | ||||
|                 \\Then, add the following snippet to `LSP`'s user settings: | ||||
|                 \\ | ||||
|                 \\{{ | ||||
|                 \\  "clients": {{ | ||||
|                 \\    "zig": {{ | ||||
|                 \\      "command": ["zls"], | ||||
|                 \\      "enabled": true, | ||||
|                 \\      "languageId": "zig", | ||||
|                 \\      "scopes": ["source.zig"], | ||||
|                 \\      "syntaxes": ["Packages/Zig/Syntaxes/Zig.tmLanguage"] | ||||
|                 \\    }} | ||||
|                 \\  }} | ||||
|                 \\}} | ||||
|             , .{}); | ||||
|         }, | ||||
|         .Kate => { | ||||
|             std.debug.warn( | ||||
|                 \\To use ZLS in Kate, enable `LSP client` plugin in Kate settings. | ||||
|                 \\Then, add the following snippet to `LSP client's` user settings: | ||||
|                 \\(or paste it in `LSP client's` GUI settings) | ||||
|                 \\ | ||||
|                 \\{{ | ||||
|                 \\    "servers": {{ | ||||
|                 \\        "zig": {{ | ||||
|                 \\            "command": ["zls"], | ||||
|                 \\            "url": "https://github.com/zigtools/zls", | ||||
|                 \\            "highlightingModeRegex": "^Zig$" | ||||
|                 \\        }} | ||||
|                 \\    }} | ||||
|                 \\}} | ||||
|             , .{}); | ||||
|         }, | ||||
|         .Neovim, .Vim8 => { | ||||
|             std.debug.warn( | ||||
|                 \\To use ZLS in Neovim/Vim8, we recommend using CoC engine. You can get it from 'https://github.com/neoclide/coc.nvim'. | ||||
|                 \\Then, simply issue cmd from Neovim/Vim8 `:CocConfig`, and add this to your CoC config: | ||||
|                 \\ | ||||
|                 \\{{ | ||||
|                 \\  "languageserver": {{ | ||||
|                 \\    "zls" : {{ | ||||
|                 \\      "command": "command_or_path_to_zls", | ||||
|                 \\      "filetypes": ["zig"] | ||||
|                 \\    }} | ||||
|                 \\  }} | ||||
|                 \\}} | ||||
|             , .{}); | ||||
|         }, | ||||
|         .Emacs => { | ||||
|             std.debug.warn( | ||||
|                 \\To use ZLS in Emacs, install lsp-mode (https://github.com/emacs-lsp/lsp-mode) from melpa. | ||||
|                 \\Zig mode (https://github.com/ziglang/zig-mode) is also useful! | ||||
|                 \\Then, add the following to your emacs config: | ||||
|                 \\ | ||||
|                 \\(require 'lsp-mode) | ||||
|                 \\(setq lsp-zig-zls-executable "<path to zls>") | ||||
|             , .{}); | ||||
|         }, | ||||
|         .Doom => { | ||||
|             std.debug.warn( | ||||
|                 \\To use ZLS in Doom Emacs, enable the lsp module | ||||
|                 \\And install the `zig-mode` (https://github.com/ziglang/zig-mode) package by adding `(package! zig-mode)` to your packages.el file. | ||||
|                 \\ | ||||
|                 \\(use-package! zig-mode | ||||
|                 \\  :hook ((zig-mode . lsp-deferred)) | ||||
|                 \\  :custom (zig-format-on-save nil) | ||||
|                 \\  :config | ||||
|                 \\  (after! lsp-mode | ||||
|                 \\    (add-to-list 'lsp-language-id-configuration '(zig-mode . "zig")) | ||||
|                 \\    (lsp-register-client | ||||
|                 \\      (make-lsp-client | ||||
|                 \\        :new-connection (lsp-stdio-connection "<path to zls>") | ||||
|                 \\        :major-modes '(zig-mode) | ||||
|                 \\        :server-id 'zls)))) | ||||
|             , .{}); | ||||
|         }, | ||||
|         .Other => { | ||||
|             std.debug.warn( | ||||
|                 \\We might not *officially* support your editor, but you can definitely still use ZLS! | ||||
|                 \\Simply configure your editor for use with language servers and point it to the ZLS executable! | ||||
|             , .{}); | ||||
|         }, | ||||
|     } | ||||
| 
 | ||||
|     std.debug.warn("\nYou can find the ZLS executable in the \"zig-cache/bin\" by default.\nNOTE: Make sure that if you move the ZLS executable, you move the `zls.json` config file with it as well!\n\nAnd finally: Thanks for choosing ZLS!\n\n", .{}); | ||||
|     try setup.wizard(builder.allocator, builder.exe_dir); | ||||
| } | ||||
| 
 | ||||
| pub fn build(b: *std.build.Builder) !void { | ||||
|  | ||||
							
								
								
									
										50
									
								
								src/main.zig
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								src/main.zig
									
									
									
									
									
								
							| @ -12,6 +12,7 @@ const URI = @import("uri.zig"); | ||||
| const references = @import("references.zig"); | ||||
| const rename = @import("rename.zig"); | ||||
| const offsets = @import("offsets.zig"); | ||||
| const setup = @import("setup.zig"); | ||||
| const semantic_tokens = @import("semantic_tokens.zig"); | ||||
| const known_folders = @import("known-folders"); | ||||
| 
 | ||||
| @ -356,6 +357,8 @@ fn nodeToCompletion( | ||||
|     const node_tags = tree.nodes.items(.tag); | ||||
|     const datas = tree.nodes.items(.data); | ||||
|     const token_tags = tree.tokens.items(.tag); | ||||
|     if (tree.errors.len > 0) | ||||
|         return; | ||||
| 
 | ||||
|     const doc_kind: types.MarkupContent.Kind = if (client_capabilities.completion_doc_supports_md) | ||||
|         .Markdown | ||||
| @ -1678,10 +1681,17 @@ fn processJsonRpc(arena: *std.heap.ArenaAllocator, parser: *std.json.Parser, jso | ||||
|     logger.debug("Method without return value not implemented: {s}", .{method}); | ||||
| } | ||||
| 
 | ||||
| const stack_frames = switch (std.builtin.mode) { | ||||
|     .Debug => 10, | ||||
|     else => 0, | ||||
| }; | ||||
| 
 | ||||
| fn launchWizard() !void { | ||||
|     const dest = | ||||
|         (try known_folders.getPath(allocator, .local_configuration)) | ||||
|             orelse (try known_folders.getPath(allocator, .executable_dir)) | ||||
|                 orelse return error.NoConfigPathFound; | ||||
|     defer allocator.free(dest); | ||||
|     try setup.wizard(allocator, dest); | ||||
| } | ||||
| 
 | ||||
| const stack_frames = switch (std.builtin.mode) { .Debug => 10, else => 0 }; | ||||
| var gpa_state = std.heap.GeneralPurposeAllocator(.{ .stack_trace_frames = stack_frames }){}; | ||||
| 
 | ||||
| pub fn main() anyerror!void { | ||||
| @ -1699,6 +1709,10 @@ pub fn main() anyerror!void { | ||||
|         if (std.mem.eql(u8, arg, "--debug-log")) { | ||||
|             actual_log_level = .debug; | ||||
|             std.debug.print("Enabled debug logging\n", .{}); | ||||
|         } else if (std.mem.eql(u8, arg, "config")) { | ||||
|             try launchWizard(); | ||||
|             args_it.deinit();             | ||||
|             return; | ||||
|         } else { | ||||
|             std.debug.print("Unrecognized argument {s}\n", .{arg}); | ||||
|             std.os.exit(1); | ||||
| @ -1746,33 +1760,7 @@ pub fn main() anyerror!void { | ||||
|             logger.debug("zig path `{s}` is not absolute, will look in path", .{exe_path}); | ||||
|             allocator.free(exe_path); | ||||
|         } | ||||
| 
 | ||||
|         const env_path = std.process.getEnvVarOwned(allocator, "PATH") catch |err| switch (err) { | ||||
|             error.EnvironmentVariableNotFound => { | ||||
|                 logger.warn("Could not get PATH environmental variable", .{}); | ||||
|                 break :find_zig; | ||||
|             }, | ||||
|             else => return err, | ||||
|         }; | ||||
|         defer allocator.free(env_path); | ||||
| 
 | ||||
|         const exe_extension = std.Target.current.exeFileExt(); | ||||
|         const zig_exe = try std.fmt.allocPrint(allocator, "zig{s}", .{exe_extension}); | ||||
|         defer allocator.free(zig_exe); | ||||
| 
 | ||||
|         var it = std.mem.tokenize(env_path, &[_]u8{std.fs.path.delimiter}); | ||||
|         while (it.next()) |path| { | ||||
|             const full_path = try std.fs.path.join(allocator, &[_][]const u8{ | ||||
|                 path, | ||||
|                 zig_exe, | ||||
|             }); | ||||
|             defer allocator.free(full_path); | ||||
| 
 | ||||
|             var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; | ||||
|             config.zig_exe_path = try std.mem.dupe(allocator, u8, std.os.realpath(full_path, &buf) catch continue); | ||||
|             logger.info("Found zig in PATH: {s}", .{config.zig_exe_path}); | ||||
|             break :find_zig; | ||||
|         } | ||||
|         config.zig_exe_path = try setup.findZig(allocator); | ||||
|     } | ||||
| 
 | ||||
|     if (config.zig_exe_path) |exe_path| { | ||||
|  | ||||
							
								
								
									
										221
									
								
								src/setup.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								src/setup.zig
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,221 @@ | ||||
| const std = @import("std"); | ||||
| const zinput = @import("zinput/src/main.zig"); | ||||
| 
 | ||||
| pub fn wizard(allocator: *std.mem.Allocator, exe_dir: []const u8) !void { | ||||
|     @setEvalBranchQuota(2500); | ||||
|     std.debug.warn( | ||||
|         \\Welcome to the ZLS configuration wizard! | ||||
|         \\      * | ||||
|         \\       |\ | ||||
|         \\      /* \ | ||||
|         \\      |  *\ | ||||
|         \\    _/_*___|_    x | ||||
|         \\      | @ @     / | ||||
|         \\     @     \   / | ||||
|         \\      \__-/   / | ||||
|         \\ | ||||
|         \\ | ||||
|         , .{}); | ||||
| 
 | ||||
|     var zig_exe_path = try findZig(allocator); | ||||
|     defer if(zig_exe_path) |p| allocator.free(p); | ||||
| 
 | ||||
|     if (zig_exe_path) |path| { | ||||
|         std.debug.print("Found zig executable '{s}' in PATH.\n", .{path}); | ||||
|     } else { | ||||
|         std.debug.print("Could not find 'zig' in PATH\n", .{}); | ||||
|         zig_exe_path = try zinput.askString(allocator, "What is the path to the 'zig' executable you would like to use?", std.fs.MAX_PATH_BYTES); | ||||
|     } | ||||
| 
 | ||||
|     const editor = try zinput.askSelectOne("Which code editor do you use?", enum { VSCode, Sublime, Kate, Neovim, Vim8, Emacs, Doom, Other }); | ||||
|     const snippets = try zinput.askBool("Do you want to enable snippets?"); | ||||
|     const style = try zinput.askBool("Do you want to enable style warnings?"); | ||||
|     const semantic_tokens = try zinput.askBool("Do you want to enable semantic highlighting?"); | ||||
|     const operator_completions = try zinput.askBool("Do you want to enable .* and .? completions?"); | ||||
|     const include_at_in_builtins = switch (editor) { | ||||
|         .Sublime => | ||||
|             true, | ||||
|         .VSCode, | ||||
|         .Kate, | ||||
|         .Neovim, | ||||
|         .Vim8, | ||||
|         .Emacs, | ||||
|         .Doom => | ||||
|             false, | ||||
|         else => | ||||
|             try zinput.askBool("Should the @ sign be included in completions of builtin functions?\nChange this later if `@inc` completes to `include` or `@@include`") | ||||
|     }; | ||||
|     const max_detail_length: usize = switch (editor) { | ||||
|         .Sublime => | ||||
|             256, | ||||
|         else => | ||||
|             1024 * 1024 | ||||
|     }; | ||||
|      | ||||
|     var dir = try std.fs.cwd().openDir(exe_dir, .{}); | ||||
|     defer dir.close(); | ||||
| 
 | ||||
|     var file = try dir.createFile("zls.json", .{}); | ||||
|     defer file.close(); | ||||
| 
 | ||||
|     const out = file.writer(); | ||||
| 
 | ||||
|     std.debug.warn("Writing config to {s}/zls.json ... ", .{exe_dir}); | ||||
| 
 | ||||
|     const content = std.json.stringify(.{ | ||||
|         .zig_exe_path = zig_exe_path, | ||||
|         .enable_snippets = snippets, | ||||
|         .warn_style = style, | ||||
|         .enable_semantic_tokens = semantic_tokens, | ||||
|         .operator_completions = operator_completions, | ||||
|         .include_at_in_builtins = include_at_in_builtins, | ||||
|         .max_detail_length = max_detail_length, | ||||
|     }, std.json.StringifyOptions{}, out); | ||||
| 
 | ||||
|     std.debug.warn("successful.\n\n\n\n", .{}); | ||||
| 
 | ||||
| 
 | ||||
|     // Keep synced with README.md | ||||
|     switch (editor) { | ||||
|         .VSCode => { | ||||
|             std.debug.warn( | ||||
|                 \\To use ZLS in Visual Studio Code, install the 'ZLS for VSCode' extension from  | ||||
|                 \\'https://github.com/zigtools/zls-vscode/releases' or via the extensions menu. | ||||
|                 \\Then, open VSCode's 'settings.json' file, and add: | ||||
|                 \\ | ||||
|                 \\"zigLanguageClient.path": "[command_or_path_to_zls]" | ||||
|             , .{}); | ||||
|         }, | ||||
|         .Sublime => { | ||||
|             std.debug.warn( | ||||
|                 \\To use ZLS in Sublime, install the `LSP` package from  | ||||
|                 \\https://github.com/sublimelsp/LSP/releases or via Package Control. | ||||
|                 \\Then, add the following snippet to LSP's user settings: | ||||
|                 \\ | ||||
|                 \\{{ | ||||
|                 \\  "clients": {{ | ||||
|                 \\    "zig": {{ | ||||
|                 \\      "command": ["zls"], | ||||
|                 \\      "enabled": true, | ||||
|                 \\      "languageId": "zig", | ||||
|                 \\      "scopes": ["source.zig"], | ||||
|                 \\      "syntaxes": ["Packages/Zig/Syntaxes/Zig.tmLanguage"] | ||||
|                 \\    }} | ||||
|                 \\  }} | ||||
|                 \\}} | ||||
|             , .{}); | ||||
|         }, | ||||
|         .Kate => { | ||||
|             std.debug.warn( | ||||
|                 \\To use ZLS in Kate, enable `LSP client` plugin in Kate settings. | ||||
|                 \\Then, add the following snippet to `LSP client's` user settings: | ||||
|                 \\(or paste it in `LSP client's` GUI settings) | ||||
|                 \\ | ||||
|                 \\{{ | ||||
|                 \\    "servers": {{ | ||||
|                 \\        "zig": {{ | ||||
|                 \\            "command": ["zls"], | ||||
|                 \\            "url": "https://github.com/zigtools/zls", | ||||
|                 \\            "highlightingModeRegex": "^Zig$" | ||||
|                 \\        }} | ||||
|                 \\    }} | ||||
|                 \\}} | ||||
|             , .{}); | ||||
|         }, | ||||
|         .Neovim, .Vim8 => { | ||||
|             std.debug.warn( | ||||
|                 \\To use ZLS in Neovim/Vim8, we recommend using CoC engine. | ||||
|                 \\You can get it from https://github.com/neoclide/coc.nvim. | ||||
|                 \\Then, simply issue cmd from Neovim/Vim8 `:CocConfig`, and add this to your CoC config: | ||||
|                 \\ | ||||
|                 \\{{ | ||||
|                 \\  "languageserver": {{ | ||||
|                 \\    "zls" : {{ | ||||
|                 \\      "command": "command_or_path_to_zls", | ||||
|                 \\      "filetypes": ["zig"] | ||||
|                 \\    }} | ||||
|                 \\  }} | ||||
|                 \\}} | ||||
|             , .{}); | ||||
|         }, | ||||
|         .Emacs => { | ||||
|             std.debug.warn( | ||||
|                 \\To use ZLS in Emacs, install lsp-mode (https://github.com/emacs-lsp/lsp-mode) from melpa. | ||||
|                 \\Zig mode (https://github.com/ziglang/zig-mode) is also useful! | ||||
|                 \\Then, add the following to your emacs config: | ||||
|                 \\ | ||||
|                 \\(require 'lsp-mode) | ||||
|                 \\(setq lsp-zig-zls-executable "<path to zls>") | ||||
|             , .{}); | ||||
|         }, | ||||
|         .Doom => { | ||||
|             std.debug.warn( | ||||
|                 \\To use ZLS in Doom Emacs, enable the lsp module | ||||
|                 \\And install the `zig-mode` (https://github.com/ziglang/zig-mode) | ||||
|                 \\package by adding `(package! zig-mode)` to your packages.el file. | ||||
|                 \\ | ||||
|                 \\(use-package! zig-mode | ||||
|                 \\  :hook ((zig-mode . lsp-deferred)) | ||||
|                 \\  :custom (zig-format-on-save nil) | ||||
|                 \\  :config | ||||
|                 \\  (after! lsp-mode | ||||
|                 \\    (add-to-list 'lsp-language-id-configuration '(zig-mode . "zig")) | ||||
|                 \\    (lsp-register-client | ||||
|                 \\      (make-lsp-client | ||||
|                 \\        :new-connection (lsp-stdio-connection "<path to zls>") | ||||
|                 \\        :major-modes '(zig-mode) | ||||
|                 \\        :server-id 'zls)))) | ||||
|             , .{}); | ||||
|         }, | ||||
|         .Other => { | ||||
|             std.debug.warn( | ||||
|                 \\We might not *officially* support your editor, but you can definitely still use ZLS! | ||||
|                 \\Simply configure your editor for use with language servers and point it to the ZLS executable! | ||||
|             , .{}); | ||||
|         }, | ||||
|     } | ||||
| 
 | ||||
|     std.debug.warn( | ||||
|         \\ | ||||
|         \\You can find the ZLS executable in the "zig-cache/bin" by default. | ||||
|         \\NOTE: Make sure that if you move the ZLS executable, you move the `zls.json` config file with it as well! | ||||
|         \\And finally: Thanks for choosing ZLS! | ||||
|         \\ | ||||
|         \\ | ||||
|         , .{}); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| pub fn findZig(allocator: *std.mem.Allocator) !?[]const u8 { | ||||
|     const env_path = std.process.getEnvVarOwned(allocator, "PATH") catch |err| switch (err) { | ||||
|         error.EnvironmentVariableNotFound => { | ||||
|             return null; | ||||
|         }, | ||||
|         else => return err, | ||||
|     }; | ||||
|     defer allocator.free(env_path); | ||||
| 
 | ||||
|     const exe_extension = std.Target.current.exeFileExt(); | ||||
|     const zig_exe = try std.fmt.allocPrint(allocator, "zig{s}", .{exe_extension}); | ||||
|     defer allocator.free(zig_exe); | ||||
| 
 | ||||
|     var it = std.mem.tokenize(env_path, &[_]u8{std.fs.path.delimiter}); | ||||
|     while (it.next()) |path| { | ||||
|         const full_path = try std.fs.path.join(allocator, &[_][]const u8{ | ||||
|             path, | ||||
|             zig_exe, | ||||
|         }); | ||||
|         defer allocator.free(full_path); | ||||
| 
 | ||||
|         if (!std.fs.path.isAbsolute(full_path)) continue; | ||||
| 
 | ||||
|         // Skip folders named zig | ||||
|         const file = std.fs.openFileAbsolute(full_path, .{}) catch continue; | ||||
|         defer file.close(); | ||||
|         const stat = file.stat() catch continue; | ||||
|         if (stat.kind == .Directory) continue; | ||||
|          | ||||
|         return try allocator.dupe(u8, full_path); | ||||
|     } | ||||
|     return null; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user