Merge pull request #274 from InterplanetaryEngineer/master
Refactor config wizard
This commit is contained in:
commit
3c609ff47d
@ -67,7 +67,7 @@ zig build config # Configure ZLS
|
|||||||
|
|
||||||
### Configuration Options
|
### Configuration Options
|
||||||
|
|
||||||
You can configure zls by providing a zls.json file.
|
You can configure zls by running `zls config`.
|
||||||
zls will look for a zls.json configuration file in multiple locations with the following priority:
|
zls will look for a zls.json configuration file in multiple locations with the following priority:
|
||||||
- In the local configuration folder of your OS (as provided by [known-folders](https://github.com/ziglibs/known-folders#folder-list))
|
- In the local configuration folder of your OS (as provided by [known-folders](https://github.com/ziglibs/known-folders#folder-list))
|
||||||
- In the same directory as the executable
|
- In the same directory as the executable
|
||||||
@ -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. |
|
| `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. |
|
| `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.
|
| `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
|
## Features
|
||||||
|
|
||||||
|
209
build.zig
209
build.zig
@ -2,210 +2,10 @@ const std = @import("std");
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
// const build_options = @import("build_options")
|
// const build_options = @import("build_options")
|
||||||
|
|
||||||
const zinput = @import("src/zinput/src/main.zig");
|
|
||||||
|
|
||||||
var builder: *std.build.Builder = undefined;
|
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", .{});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build(b: *std.build.Builder) !void {
|
pub fn build(b: *std.build.Builder) !void {
|
||||||
builder = b;
|
builder = b;
|
||||||
// Standard target options allows the person running `zig build` to choose
|
|
||||||
// what target to build for. Here we do not override the defaults, which
|
|
||||||
// means any target is allowed, and the default is native. Other options
|
|
||||||
// for restricting supported target set are available.
|
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
|
|
||||||
const mode = b.standardReleaseOptions();
|
const mode = b.standardReleaseOptions();
|
||||||
@ -225,15 +25,6 @@ pub fn build(b: *std.build.Builder) !void {
|
|||||||
|
|
||||||
b.installFile("src/special/build_runner.zig", "bin/build_runner.zig");
|
b.installFile("src/special/build_runner.zig", "bin/build_runner.zig");
|
||||||
|
|
||||||
const run_cmd = exe.run();
|
|
||||||
run_cmd.step.dependOn(b.getInstallStep());
|
|
||||||
|
|
||||||
const run_step = b.step("run", "Run the app");
|
|
||||||
run_step.dependOn(&run_cmd.step);
|
|
||||||
|
|
||||||
const configure_step = b.step("config", "Configure zls");
|
|
||||||
configure_step.makeFn = config;
|
|
||||||
|
|
||||||
const test_step = b.step("test", "Run all the tests");
|
const test_step = b.step("test", "Run all the tests");
|
||||||
test_step.dependOn(builder.getInstallStep());
|
test_step.dependOn(builder.getInstallStep());
|
||||||
|
|
||||||
|
50
src/main.zig
50
src/main.zig
@ -12,6 +12,7 @@ const URI = @import("uri.zig");
|
|||||||
const references = @import("references.zig");
|
const references = @import("references.zig");
|
||||||
const rename = @import("rename.zig");
|
const rename = @import("rename.zig");
|
||||||
const offsets = @import("offsets.zig");
|
const offsets = @import("offsets.zig");
|
||||||
|
const setup = @import("setup.zig");
|
||||||
const semantic_tokens = @import("semantic_tokens.zig");
|
const semantic_tokens = @import("semantic_tokens.zig");
|
||||||
const known_folders = @import("known-folders");
|
const known_folders = @import("known-folders");
|
||||||
|
|
||||||
@ -356,6 +357,8 @@ fn nodeToCompletion(
|
|||||||
const node_tags = tree.nodes.items(.tag);
|
const node_tags = tree.nodes.items(.tag);
|
||||||
const datas = tree.nodes.items(.data);
|
const datas = tree.nodes.items(.data);
|
||||||
const token_tags = tree.tokens.items(.tag);
|
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)
|
const doc_kind: types.MarkupContent.Kind = if (client_capabilities.completion_doc_supports_md)
|
||||||
.Markdown
|
.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});
|
logger.debug("Method without return value not implemented: {s}", .{method});
|
||||||
}
|
}
|
||||||
|
|
||||||
const stack_frames = switch (std.builtin.mode) {
|
|
||||||
.Debug => 10,
|
fn launchWizard() !void {
|
||||||
else => 0,
|
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 }){};
|
var gpa_state = std.heap.GeneralPurposeAllocator(.{ .stack_trace_frames = stack_frames }){};
|
||||||
|
|
||||||
pub fn main() anyerror!void {
|
pub fn main() anyerror!void {
|
||||||
@ -1699,6 +1709,10 @@ pub fn main() anyerror!void {
|
|||||||
if (std.mem.eql(u8, arg, "--debug-log")) {
|
if (std.mem.eql(u8, arg, "--debug-log")) {
|
||||||
actual_log_level = .debug;
|
actual_log_level = .debug;
|
||||||
std.debug.print("Enabled debug logging\n", .{});
|
std.debug.print("Enabled debug logging\n", .{});
|
||||||
|
} else if (std.mem.eql(u8, arg, "config")) {
|
||||||
|
try launchWizard();
|
||||||
|
args_it.deinit();
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
std.debug.print("Unrecognized argument {s}\n", .{arg});
|
std.debug.print("Unrecognized argument {s}\n", .{arg});
|
||||||
std.os.exit(1);
|
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});
|
logger.debug("zig path `{s}` is not absolute, will look in path", .{exe_path});
|
||||||
allocator.free(exe_path);
|
allocator.free(exe_path);
|
||||||
}
|
}
|
||||||
|
config.zig_exe_path = try setup.findZig(allocator);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.zig_exe_path) |exe_path| {
|
if (config.zig_exe_path) |exe_path| {
|
||||||
|
214
src/setup.zig
Normal file
214
src/setup.zig
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
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("\n\nThank you for choosing ZLS!\n", .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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