From d0abaaee2a8fcd9cc0b14707ee543258db673402 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 21 Jan 2026 17:35:09 +0100 Subject: [PATCH 1/4] refactor: move completion replacement logic to editor --- src/tui/editor.zig | 4 ++++ src/tui/mode/overlay/completion_dropdown.zig | 2 +- src/tui/mode/overlay/completion_palette.zig | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/tui/editor.zig b/src/tui/editor.zig index 4b8d4de..670839f 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -6408,6 +6408,10 @@ pub const Editor = struct { self.completion_is_complete = is_incomplete; } + pub fn get_completion_replacement_selection(self: *Self, replace: Selection) ?Selection { + return replace.from_pos(self.buf_root() catch return null, self.metrics); + } + pub fn select(self: *Self, ctx: Context) Result { var sel: Selection = .{}; if (!try ctx.args.match(.{ tp.extract(&sel.begin.row), tp.extract(&sel.begin.col), tp.extract(&sel.end.row), tp.extract(&sel.end.col) })) diff --git a/src/tui/mode/overlay/completion_dropdown.zig b/src/tui/mode/overlay/completion_dropdown.zig index a85d745..480d9f4 100644 --- a/src/tui/mode/overlay/completion_dropdown.zig +++ b/src/tui/mode/overlay/completion_dropdown.zig @@ -276,7 +276,7 @@ fn get_replace_selection(replace: Buffer.Selection) ?Buffer.Selection { return if (replace.empty()) null else if (tui.get_active_editor()) |edt| - replace.from_pos(edt.buf_root() catch return null, edt.metrics) + edt.get_completion_replacement_selection(replace) else replace; } diff --git a/src/tui/mode/overlay/completion_palette.zig b/src/tui/mode/overlay/completion_palette.zig index 3e700ec..b913a19 100644 --- a/src/tui/mode/overlay/completion_palette.zig +++ b/src/tui/mode/overlay/completion_palette.zig @@ -205,7 +205,7 @@ fn get_replace_selection(replace: Buffer.Selection) ?Buffer.Selection { return if (replace.empty()) null else if (tui.get_active_editor()) |edt| - replace.from_pos(edt.buf_root() catch return null, edt.metrics) + edt.get_completion_replacement_selection(replace) else replace; } From 9729bae7be869628811efd9289a8d7b9d8e99942 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 21 Jan 2026 17:35:39 +0100 Subject: [PATCH 2/4] feat: add completion_insert_mode configuration option --- src/config.zig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/config.zig b/src/config.zig index 9816152..850738d 100644 --- a/src/config.zig +++ b/src/config.zig @@ -54,6 +54,7 @@ start_debugger_on_crash: bool = false, completion_trigger: CompletionTrigger = .automatic, completion_style: CompletionStyle = .dropdown, +completion_insert_mode: CompletionInsertMode = .insert, widget_style: WidgetStyle = .compact, palette_style: WidgetStyle = .bars_top_bottom, @@ -182,6 +183,11 @@ pub const CompletionStyle = enum { dropdown, }; +pub const CompletionInsertMode = enum { + insert, + replace, +}; + pub const Alignment = enum { left, right, From 3051cc3b86b9baca8ff36f97b585be6545b024e8 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 21 Jan 2026 17:40:37 +0100 Subject: [PATCH 3/4] refactor: implement completion_insert_mode .insert --- src/tui/editor.zig | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/tui/editor.zig b/src/tui/editor.zig index 670839f..679b687 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -6409,7 +6409,16 @@ pub const Editor = struct { } pub fn get_completion_replacement_selection(self: *Self, replace: Selection) ?Selection { - return replace.from_pos(self.buf_root() catch return null, self.metrics); + var sel = replace.from_pos(self.buf_root() catch return null, self.metrics); + sel.normalize(); + const cursor = self.get_primary().cursor; + return switch (tui.config().completion_insert_mode) { + .insert => if (self.get_primary().cursor.within(sel)) + .{ .begin = sel.begin, .end = cursor } + else + sel, + .replace => sel, + }; } pub fn select(self: *Self, ctx: Context) Result { From d8fa1b28aa613ff6fadb7f028b150b5eb1cd46cb Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 21 Jan 2026 17:43:32 +0100 Subject: [PATCH 4/4] feat: add toggle_completion_insert_mode command --- src/tui/tui.zig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/tui/tui.zig b/src/tui/tui.zig index a26e6e0..8755553 100644 --- a/src/tui/tui.zig +++ b/src/tui/tui.zig @@ -1150,6 +1150,17 @@ const cmds = struct { } pub const toggle_completion_trigger_meta: Meta = .{ .description = "Toggle auto completion" }; + pub fn toggle_completion_insert_mode(self: *Self, _: Ctx) Result { + self.config_.completion_insert_mode = switch (self.config_.completion_insert_mode) { + .insert => .replace, + .replace => .insert, + }; + defer self.logger.print("completion insert mode {t}", .{self.config_.completion_insert_mode}); + try save_config(); + resize(); + } + pub const toggle_completion_insert_mode_meta: Meta = .{ .description = "Toggle completion insert mode" }; + pub fn toggle_keybind_hints(self: *Self, _: Ctx) Result { self.hint_mode = switch (self.hint_mode) { .all => .prefix,