From e86afc3ef69be38c58b18fc20f75e9568ddae056 Mon Sep 17 00:00:00 2001 From: Alexander Mykolaichuk Date: Sat, 23 Sep 2023 12:52:32 +0200 Subject: [PATCH] add completions_with_replace flag --- README.md | 1 + schema.json | 5 ++++ src/Config.zig | 3 +++ src/config_gen/config.json | 8 +++++- src/features/completions.zig | 52 +++++++++++++++++++----------------- 5 files changed, 43 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 19f13f553..f16e60dda 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ The following options are currently available. | `build_runner_path` | `?[]const u8` | `null` | Path to the `build_runner.zig` file provided by zls. null is equivalent to `${executable_directory}/build_runner.zig` | | `global_cache_path` | `?[]const u8` | `null` | Path to a directory that will be used as zig's cache. null is equivalent to `${KnownFolders.Cache}/zls` | | `build_runner_global_cache_path` | `?[]const u8` | `null` | Path to a directory that will be used as the global cache path when executing a projects build.zig. null is equivalent to the path shown by `zig env` | +| `completions_with_replace` | `bool` | `true` | Completions confirm behavior. If 'true', replace the text after the cursor | ### Per-build Configuration Options diff --git a/schema.json b/schema.json index 6bb367485..427f18560 100644 --- a/schema.json +++ b/schema.json @@ -163,6 +163,11 @@ "description": "Path to a directory that will be used as the global cache path when executing a projects build.zig. null is equivalent to the path shown by `zig env`", "type": "string", "default": "null" + }, + "completions_with_replace": { + "description": "Completions confirm behavior. If 'true', replace the text after the cursor", + "type": "boolean", + "default": "true" } } } diff --git a/src/Config.zig b/src/Config.zig index c948c839f..9cbce674c 100644 --- a/src/Config.zig +++ b/src/Config.zig @@ -101,4 +101,7 @@ global_cache_path: ?[]const u8 = null, /// Path to a directory that will be used as the global cache path when executing a projects build.zig. null is equivalent to the path shown by `zig env` build_runner_global_cache_path: ?[]const u8 = null, +/// Completions confirm behavior. If 'true', replace the text after the cursor +completions_with_replace: bool = true, + // DO NOT EDIT diff --git a/src/config_gen/config.json b/src/config_gen/config.json index 334df82a4..3aa508b74 100644 --- a/src/config_gen/config.json +++ b/src/config_gen/config.json @@ -190,6 +190,12 @@ "description": "Path to a directory that will be used as the global cache path when executing a projects build.zig. null is equivalent to the path shown by `zig env`", "type": "?[]const u8", "default": "null" + }, + { + "name": "completions_with_replace", + "description": "Completions confirm behavior. If 'true', replace the text after the cursor", + "type": "bool", + "default": "true" } ] -} \ No newline at end of file +} diff --git a/src/features/completions.zig b/src/features/completions.zig index 4cba16791..597598052 100644 --- a/src/features/completions.zig +++ b/src/features/completions.zig @@ -1455,33 +1455,35 @@ pub fn completionAtIndex(server: *Server, analyser: *Analyser, arena: std.mem.Al const completions = maybe_completions orelse return null; - // The cursor is in the middle of a word or before a @, so we can replace - // the remaining identifier with the completion instead of just inserting. - // TODO Identify function call/struct init and replace the whole thing. - const lookahead_context = try Analyser.getPositionContext(arena, handle.text, source_index, true); - if (server.client_capabilities.supports_apply_edits and - pos_context != .import_string_literal and - pos_context != .cinclude_string_literal and - pos_context != .embedfile_string_literal and - pos_context.loc() != null and - lookahead_context.loc() != null and - pos_context.loc().?.end != lookahead_context.loc().?.end) - { - var end = lookahead_context.loc().?.end; - while (end < handle.text.len and (std.ascii.isAlphanumeric(handle.text[end]) or handle.text[end] == '"')) { - end += 1; - } + if (server.config.completions_with_replace) { + // The cursor is in the middle of a word or before a @, so we can replace + // the remaining identifier with the completion instead of just inserting. + // TODO Identify function call/struct init and replace the whole thing. + const lookahead_context = try Analyser.getPositionContext(arena, handle.text, source_index, true); + if (server.client_capabilities.supports_apply_edits and + pos_context != .import_string_literal and + pos_context != .cinclude_string_literal and + pos_context != .embedfile_string_literal and + pos_context.loc() != null and + lookahead_context.loc() != null and + pos_context.loc().?.end != lookahead_context.loc().?.end) + { + var end = lookahead_context.loc().?.end; + while (end < handle.text.len and (std.ascii.isAlphanumeric(handle.text[end]) or handle.text[end] == '"')) { + end += 1; + } - const replaceLoc = offsets.Loc{ .start = lookahead_context.loc().?.start, .end = end }; - const replaceRange = offsets.locToRange(handle.text, replaceLoc, server.offset_encoding); + const replaceLoc = offsets.Loc{ .start = lookahead_context.loc().?.start, .end = end }; + const replaceRange = offsets.locToRange(handle.text, replaceLoc, server.offset_encoding); - for (completions) |*item| { - item.textEdit = .{ - .TextEdit = .{ - .newText = item.insertText orelse item.label, - .range = replaceRange, - }, - }; + for (completions) |*item| { + item.textEdit = .{ + .TextEdit = .{ + .newText = item.insertText orelse item.label, + .range = replaceRange, + }, + }; + } } }