From 65eb6bc7ad0cf5eaf6d568a8248aba76c65191fc Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Thu, 2 Oct 2025 16:22:55 +0200 Subject: [PATCH 1/6] feat: add Selection.from_pos function --- src/buffer/Selection.zig | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/buffer/Selection.zig b/src/buffer/Selection.zig index b87064b..5ea9df5 100644 --- a/src/buffer/Selection.zig +++ b/src/buffer/Selection.zig @@ -19,6 +19,19 @@ pub fn from_cursor(cursor: *const Cursor) Self { return .{ .begin = cursor.*, .end = cursor.* }; } +pub fn from_pos(sel: Self, root: Buffer.Root, metrics: Buffer.Metrics) error{NotFound}!Self { + return .{ + .begin = .{ + .row = sel.begin.row, + .col = try root.pos_to_width(sel.begin.row, sel.begin.col, metrics), + }, + .end = .{ + .row = sel.end.row, + .col = try root.pos_to_width(sel.end.row, sel.end.col, metrics), + }, + }; +} + pub fn line_from_cursor(cursor: Cursor, root: Buffer.Root, mtrx: Buffer.Metrics) Self { var begin = cursor; var end = cursor; From 10bd270d8915cbbdb57cb42e2ed23081132f83c6 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Thu, 2 Oct 2025 16:23:21 +0200 Subject: [PATCH 2/6] feat: add Match.from_pos function --- src/tui/editor.zig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tui/editor.zig b/src/tui/editor.zig index 8802baf..dc3f12b 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -74,6 +74,10 @@ pub const Match = struct { return .{ .begin = self.begin, .end = self.end }; } + pub fn from_pos(self: Self, root: Buffer.Root, metrics: Buffer.Metrics) error{NotFound}!Self { + return from_selection(try self.to_selection().from_pos(root, metrics)); + } + fn nudge_insert(self: *Self, nudge: Selection) void { self.begin.nudge_insert(nudge); self.end.nudge_insert(nudge); From 390fbd51ffb5ca08d9a4f1fc3d0c9c0e43036848 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Thu, 2 Oct 2025 16:25:48 +0200 Subject: [PATCH 3/6] refactor: simplify code by using Selection.from_pos --- src/tui/editor.zig | 53 +++++++++++----------------------------------- 1 file changed, 12 insertions(+), 41 deletions(-) diff --git a/src/tui/editor.zig b/src/tui/editor.zig index dc3f12b..61cbba0 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -179,16 +179,10 @@ pub const CurSel = struct { } fn selection_from_range(range: syntax.Range, root: Buffer.Root, metrics: Buffer.Metrics) error{NotFound}!Selection { - return .{ - .begin = .{ - .row = range.start_point.row, - .col = try root.pos_to_width(range.start_point.row, range.start_point.column, metrics), - }, - .end = .{ - .row = range.end_point.row, - .col = try root.pos_to_width(range.end_point.row, range.end_point.column, metrics), - }, - }; + return Selection.from_pos(.{ + .begin = .{ .row = range.start_point.row, .col = range.start_point.column }, + .end = .{ .row = range.end_point.row, .col = range.end_point.column }, + }, root, metrics); } pub fn selection_from_node(node: syntax.Node, root: Buffer.Root, metrics: Buffer.Metrics) error{NotFound}!Selection { @@ -5446,10 +5440,8 @@ pub const Editor = struct { if (pos_type == .byte) { column = root.pos_to_width(line - 1, column - 1, self.metrics) catch return; column += 1; - if (have_sel) { - sel.begin.col = root.pos_to_width(sel.begin.row, sel.begin.col, self.metrics) catch return; - sel.end.col = root.pos_to_width(sel.end.row, sel.end.col, self.metrics) catch return; - } + if (have_sel) + sel = sel.from_pos(root, self.metrics) catch return; // self.logger.print("goto_byte_pos: l:{d} c:{d} {any} {}", .{ line, column, sel, pos_type }); } const primary = self.get_primary(); @@ -5549,16 +5541,7 @@ pub const Editor = struct { .push => try self.push_cursor(), } const root = self.buf_root() catch return; - const sel: Selection = .{ - .begin = .{ - .row = sel_.begin.row, - .col = try root.pos_to_width(sel_.begin.row, sel_.begin.col, self.metrics), - }, - .end = .{ - .row = sel_.end.row, - .col = try root.pos_to_width(sel_.end.row, sel_.end.col, self.metrics), - }, - }; + const sel = try sel_.from_pos(root, self.metrics); const primary = self.get_primary(); primary.selection = sel; primary.cursor = sel.end; @@ -5599,18 +5582,16 @@ pub const Editor = struct { } first = false; } - const begin_col = try root.pos_to_width(begin_row, begin_col_pos, self.metrics); - const end_col = try root.pos_to_width(end_row, end_col_pos, self.metrics); last_begin_row = begin_row; last_begin_col_pos = begin_col_pos; last_end_row = end_row; last_end_col_pos = end_col_pos; - const sel: Selection = .{ - .begin = .{ .row = begin_row, .col = begin_col }, - .end = .{ .row = end_row, .col = end_col }, - }; + const sel = try Selection.from_pos(.{ + .begin = .{ .row = begin_row, .col = begin_col_pos }, + .end = .{ .row = end_row, .col = end_col_pos }, + }, root, self.metrics); const primary = self.get_primary(); primary.selection = sel; primary.cursor = sel.end; @@ -5687,23 +5668,13 @@ pub const Editor = struct { if (!std.mem.eql(u8, file_path, self.file_path orelse return)) return; const root = self.buf_root() catch return; - const sel: Selection = .{ - .begin = .{ - .row = sel_.begin.row, - .col = root.pos_to_width(sel_.begin.row, sel_.begin.col, self.metrics) catch return, - }, - .end = .{ - .row = sel_.end.row, - .col = root.pos_to_width(sel_.end.row, sel_.end.col, self.metrics) catch return, - }, - }; (try self.diagnostics.addOne(self.allocator)).* = .{ .source = try self.allocator.dupe(u8, source), .code = try self.allocator.dupe(u8, code), .message = try self.allocator.dupe(u8, message), .severity = severity, - .sel = sel, + .sel = sel_.from_pos(root, self.metrics) catch return, }; switch (Diagnostic.to_severity(severity)) { From 6ae176a8acaee1ab0bbe4371861afda13a5fb33a Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Thu, 2 Oct 2025 16:27:16 +0200 Subject: [PATCH 4/6] refactor: add selection_pos_to_width and get_replace_selection functions --- src/tui/editor.zig | 5 +++++ src/tui/mode/overlay/completion_palette.zig | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/src/tui/editor.zig b/src/tui/editor.zig index 61cbba0..e13d0d4 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -5602,6 +5602,11 @@ pub const Editor = struct { } } + pub fn selection_pos_to_width(self: *Self, sel_: Selection) ?Selection { + const root = self.buf_root() catch return null; + return sel_.from_pos(root, self.metrics) catch null; + } + fn count_lines(content: []const u8) struct { usize, usize } { var pos = content; var offset = content.len; diff --git a/src/tui/mode/overlay/completion_palette.zig b/src/tui/mode/overlay/completion_palette.zig index c36b4a3..5d9789e 100644 --- a/src/tui/mode/overlay/completion_palette.zig +++ b/src/tui/mode/overlay/completion_palette.zig @@ -130,6 +130,15 @@ fn get_values(item_cbor: []const u8) struct { []const u8, []const u8, u8, Buffer return .{ label_, sort_text, kind, replace }; } +fn get_replace_selection(replace: Buffer.Selection) ?Buffer.Selection { + return if (tui.get_active_editor()) |edt| + edt.selection_pos_to_width(replace) + else if (replace.empty()) + null + else + replace; +} + fn select(menu: **Type.MenuState, button: *Type.ButtonState) void { const label_, _, _, _ = get_values(button.opts.label); tp.self_pid().send(.{ "cmd", "exit_overlay_mode" }) catch |e| menu.*.opts.ctx.logger.err(module_name, e); From 6ec8aae94ab9811b57114eee9b48cd0d420eb7bb Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Thu, 2 Oct 2025 16:27:47 +0200 Subject: [PATCH 5/6] fix: translate byte offsets to columns when applying completions --- src/tui/mode/overlay/completion_palette.zig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tui/mode/overlay/completion_palette.zig b/src/tui/mode/overlay/completion_palette.zig index 5d9789e..1145c6e 100644 --- a/src/tui/mode/overlay/completion_palette.zig +++ b/src/tui/mode/overlay/completion_palette.zig @@ -40,9 +40,10 @@ pub fn load_entries(palette: *Type) !usize { var max_label_len: usize = 0; for (palette.entries.items) |*item| { - const label_, const sort_text, _, const replace = get_values(item.cbor); - if (palette.value.replace == null and !(replace.begin.row == 0 and replace.begin.col == 0 and replace.end.row == 0 and replace.end.col == 0)) - palette.value.replace = replace; + const label_, const sort_text, _, const maybe_replace = get_values(item.cbor); + if (get_replace_selection(maybe_replace)) |replace| { + if (palette.value.replace == null) palette.value.replace = replace; + } item.label = label_; item.sort_text = sort_text; max_label_len = @max(max_label_len, item.label.len); @@ -149,7 +150,7 @@ pub fn updated(palette: *Type, button_: ?*Type.ButtonState) !void { const button = button_ orelse return cancel(palette); _, _, _, const replace = get_values(button.opts.label); const editor = tui.get_active_editor() orelse return error.NotFound; - editor.get_primary().selection = if (replace.empty()) null else replace; + editor.get_primary().selection = get_replace_selection(replace); } pub fn cancel(palette: *Type) !void { From 5362706b26f54b441d27f50ef209ea85c3fb7d5e Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Thu, 2 Oct 2025 16:28:23 +0200 Subject: [PATCH 6/6] fix: translate columns to byte offsets when requesting completions --- src/tui/editor.zig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tui/editor.zig b/src/tui/editor.zig index e13d0d4..6d15a20 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -5520,9 +5520,11 @@ pub const Editor = struct { pub fn completion(self: *Self, _: Context) Result { const file_path = self.file_path orelse return; + const root = self.buf_root() catch return; const primary = self.get_primary(); + const col = try root.get_line_width_to_pos(primary.cursor.row, primary.cursor.col, self.metrics); self.completions.clearRetainingCapacity(); - return project_manager.completion(file_path, primary.cursor.row, primary.cursor.col); + return project_manager.completion(file_path, primary.cursor.row, col); } pub const completion_meta: Meta = .{ .description = "Language: Show completions at cursor" };