diff --git a/src/tui/editor.zig b/src/tui/editor.zig index 9c4ceba..ae73efb 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -4900,6 +4900,52 @@ pub const Editor = struct { _ = self.pop_tabstop(); } + fn replicate_selection(self: *Self, sel: Selection) void { + const dist = if (sel.begin.row != sel.end.row) + 0 + else if (sel.begin.col > sel.end.col) + sel.begin.col - sel.end.col + else + sel.end.col - sel.begin.col; + + for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| { + var s = Selection.from_cursor(&cursel.cursor); + s.begin.col -|= dist; + cursel.selection = s; + }; + } + + pub fn insert_completion(self: *Self, sel_: ?Selection, text: []const u8, insertTextFormat: usize) Result { + const primary = self.get_primary(); + const sel = if (sel_) |s| blk: { + primary.selection = s; + break :blk s; + } else primary.selection orelse Selection.from_cursor(&primary.cursor); + self.replicate_selection(sel); + + switch (insertTextFormat) { + 2 => try self.insert_snippet(text), + else => try self.insert_cursels(text), + } + } + + pub fn update_completion_cursels(self: *Self, sel: Selection, text: []const u8) Result { + const b = self.buf_for_update() catch return; + self.replicate_selection(sel); + var root = b.root; + for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| { + root = if (text.len > 0) + try self.insert(root, cursel, text, b.allocator) + else + try self.delete_selection(root, cursel, b.allocator); + }; + for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| { + cursel.selection = null; + }; + try self.update_buf(root); + self.clamp(); + } + pub fn insert_cursels(self: *Self, chars: []const u8) Result { const b = try self.buf_for_update(); var root = b.root; diff --git a/src/tui/mode/overlay/completion_dropdown.zig b/src/tui/mode/overlay/completion_dropdown.zig index c6a929c..41ff77b 100644 --- a/src/tui/mode/overlay/completion_dropdown.zig +++ b/src/tui/mode/overlay/completion_dropdown.zig @@ -117,19 +117,13 @@ pub fn initial_query(self: *Type, allocator: std.mem.Allocator) error{OutOfMemor pub fn update_query(self: *Type, query: []const u8) void { const editor = tui.get_active_editor() orelse return; + const sel = get_insert_selection(self, editor.get_primary().cursor); + editor.update_completion_cursels(sel, query) catch |e| self.logger.err(module_name, e); + const primary = editor.get_primary(); - primary.selection = get_insert_selection(self, editor.get_primary().cursor); - const b = editor.buf_for_update() catch return; - const root_ = if (query.len > 0) - editor.insert(b.root, primary, query, b.allocator) catch return - else - editor.delete_selection(b.root, primary, b.allocator) catch return; - self.value.cursor = editor.get_primary().cursor; - if (self.value.replace) |*sel| sel.* = .{ .begin = sel.begin, .end = self.value.cursor }; - primary.selection = null; - editor.update_buf(root_) catch {}; - editor.clamp(); - editor.need_render(); + self.value.cursor = primary.cursor; + self.value.view = editor.view; + if (self.value.replace) |*s| s.* = .{ .begin = s.begin, .end = self.value.cursor }; if (query.len > 0) { const last_char = query[query.len - 1]; editor.run_triggers(primary, last_char, .insert); @@ -296,18 +290,14 @@ fn select(menu: **Type.MenuType, button: *Type.ButtonType, _: Type.Pos) void { const self = menu.*.opts.ctx; const values = get_values(button.opts.label); const editor = tui.get_active_editor() orelse return; - const primary = editor.get_primary(); - primary.selection = get_insert_selection(self, editor.get_primary().cursor); + const sel = get_insert_selection(self, editor.get_primary().cursor); const text = if (values.insertText.len > 0) values.insertText else if (values.textEdit_newText.len > 0) values.textEdit_newText else values.label; - switch (values.insertTextFormat) { - 2 => editor.insert_snippet(text) catch |e| self.logger.err(module_name, e), - else => editor.insert_cursels(text) catch |e| self.logger.err(module_name, e), - } + editor.insert_completion(sel, text, values.insertTextFormat) catch |e| menu.*.opts.ctx.logger.err(module_name, e); self.value.cursor = editor.get_primary().cursor; self.value.view = editor.view; const mv = tui.mainview() orelse return; diff --git a/src/tui/mode/overlay/completion_palette.zig b/src/tui/mode/overlay/completion_palette.zig index 7045136..bf23235 100644 --- a/src/tui/mode/overlay/completion_palette.zig +++ b/src/tui/mode/overlay/completion_palette.zig @@ -230,10 +230,7 @@ fn select(menu: **Type.MenuType, button: *Type.ButtonType, _: Type.Pos) void { values.textEdit_newText else values.label; - switch (values.insertTextFormat) { - 2 => editor.insert_snippet(text) catch |e| menu.*.opts.ctx.logger.err(module_name, e), - else => editor.insert_cursels(text) catch |e| menu.*.opts.ctx.logger.err(module_name, e), - } + editor.insert_completion(null, text, values.insertTextFormat) catch |e| menu.*.opts.ctx.logger.err(module_name, e); const mv = tui.mainview() orelse return; mv.cancel_info_content() catch {}; tp.self_pid().send(.{ "cmd", "exit_overlay_mode" }) catch |e| menu.*.opts.ctx.logger.err(module_name, e);