From 911fc3160a8f35db405b155b8cf207c45338cd4d Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Tue, 23 Dec 2025 23:53:14 +0100 Subject: [PATCH 1/3] refactor: add support for backspace during completion --- src/keybind/builtin/flow.json | 6 ++++-- src/tui/mode/overlay/completion_dropdown.zig | 5 ++++- src/tui/mode/overlay/dropdown.zig | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/keybind/builtin/flow.json b/src/keybind/builtin/flow.json index 081c8df..41af849 100644 --- a/src/keybind/builtin/flow.json +++ b/src/keybind/builtin/flow.json @@ -385,7 +385,8 @@ ["ctrl+up", "palette_menu_up"], ["ctrl+down", "palette_menu_down"], ["ctrl+enter", "palette_menu_activate"], - ["tab", "palette_menu_complete"] + ["tab", "palette_menu_complete"], + ["backspace", "overlay_delete_backwards"] ] }, "overlay/dropdown": { @@ -398,7 +399,8 @@ ["up", "palette_menu_up"], ["down", "palette_menu_down"], ["enter", "palette_menu_activate"], - ["tab", "palette_menu_complete"] + ["tab", "palette_menu_complete"], + ["backspace", "overlay_delete_backwards"] ] }, "mini/numeric": { diff --git a/src/tui/mode/overlay/completion_dropdown.zig b/src/tui/mode/overlay/completion_dropdown.zig index c09f92d..779559b 100644 --- a/src/tui/mode/overlay/completion_dropdown.zig +++ b/src/tui/mode/overlay/completion_dropdown.zig @@ -110,7 +110,10 @@ pub fn update_query(self: *Type, query: []const u8) void { 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_ = editor.insert(b.root, primary, query, b.allocator) 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; diff --git a/src/tui/mode/overlay/dropdown.zig b/src/tui/mode/overlay/dropdown.zig index a825e08..a629c84 100644 --- a/src/tui/mode/overlay/dropdown.zig +++ b/src/tui/mode/overlay/dropdown.zig @@ -353,6 +353,15 @@ pub fn Create(options: type) type { return matches.items.len; } + fn delete_code_point(self: *Self) !void { + if (self.query.items.len > 0) { + self.query.shrinkRetainingCapacity(self.query.items.len - tui.egc_last(self.query.items).len); + if (@hasDecl(options, "update_query")) + options.update_query(self, self.query.items); + } + try self.start_query(0); + } + fn insert_code_point(self: *Self, c: u32) !void { var buf: [6]u8 = undefined; const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf); @@ -523,6 +532,11 @@ pub fn Create(options: type) type { } pub const palette_menu_cancel_meta: Meta = .{}; + pub fn overlay_delete_backwards(self: *Self, _: Ctx) Result { + self.delete_code_point() catch |e| return tp.exit_error(e, @errorReturnTrace()); + } + pub const overlay_delete_backwards_meta: Meta = .{ .description = "Delete backwards" }; + pub fn overlay_insert_code_point(self: *Self, ctx: Ctx) Result { var egc: u32 = 0; if (!try ctx.args.match(.{tp.extract(&egc)})) From 4f39bbbd41355b25bc8bfef36186c97d818f9ee4 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 24 Dec 2025 00:02:41 +0100 Subject: [PATCH 2/3] refactor: add support for delete word during completion --- src/keybind/builtin/flow.json | 2 ++ src/tui/mode/overlay/dropdown.zig | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/keybind/builtin/flow.json b/src/keybind/builtin/flow.json index 41af849..ed65972 100644 --- a/src/keybind/builtin/flow.json +++ b/src/keybind/builtin/flow.json @@ -386,6 +386,7 @@ ["ctrl+down", "palette_menu_down"], ["ctrl+enter", "palette_menu_activate"], ["tab", "palette_menu_complete"], + ["ctrl+backspace", "overlay_delete_word_left"], ["backspace", "overlay_delete_backwards"] ] }, @@ -400,6 +401,7 @@ ["down", "palette_menu_down"], ["enter", "palette_menu_activate"], ["tab", "palette_menu_complete"], + ["ctrl+backspace", "overlay_delete_word_left"], ["backspace", "overlay_delete_backwards"] ] }, diff --git a/src/tui/mode/overlay/dropdown.zig b/src/tui/mode/overlay/dropdown.zig index a629c84..1a54f85 100644 --- a/src/tui/mode/overlay/dropdown.zig +++ b/src/tui/mode/overlay/dropdown.zig @@ -353,6 +353,17 @@ pub fn Create(options: type) type { return matches.items.len; } + fn delete_word(self: *Self) !void { + if (std.mem.lastIndexOfAny(u8, self.query.items, "/\\. -_")) |pos| { + self.query.shrinkRetainingCapacity(pos); + } else { + self.query.shrinkRetainingCapacity(0); + } + if (@hasDecl(options, "update_query")) + options.update_query(self, self.query.items); + return self.start_query(0); + } + fn delete_code_point(self: *Self) !void { if (self.query.items.len > 0) { self.query.shrinkRetainingCapacity(self.query.items.len - tui.egc_last(self.query.items).len); @@ -532,6 +543,11 @@ pub fn Create(options: type) type { } pub const palette_menu_cancel_meta: Meta = .{}; + pub fn overlay_delete_word_left(self: *Self, _: Ctx) Result { + self.delete_word() catch |e| return tp.exit_error(e, @errorReturnTrace()); + } + pub const overlay_delete_word_left_meta: Meta = .{ .description = "Delete word to the left" }; + pub fn overlay_delete_backwards(self: *Self, _: Ctx) Result { self.delete_code_point() catch |e| return tp.exit_error(e, @errorReturnTrace()); } From b5d137666fc791de946b4e3058316a678904c9b3 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 24 Dec 2025 00:10:56 +0100 Subject: [PATCH 3/3] refactor: run triggers only on primary cursel --- src/tui/editor.zig | 7 ++++--- src/tui/mode/overlay/completion_dropdown.zig | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tui/editor.zig b/src/tui/editor.zig index 5cfefd8..945ec19 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -2286,7 +2286,7 @@ pub const Editor = struct { var size: usize = 0; const root_, const trigger_char = try root.delete_range_char(sel, allocator, &size, self.metrics); self.nudge_delete(sel, cursel, size); - if (trigger_char) |char| self.run_triggers(char, .delete); + if (trigger_char) |char| self.run_triggers(cursel, char, .delete); return root_; } @@ -2865,7 +2865,7 @@ pub const Editor = struct { cursor.row, cursor.col, root_ = try root_.insert_chars(cursor.row, cursor.col, s, allocator, self.metrics); cursor.target = cursor.col; self.nudge_insert(.{ .begin = begin, .end = cursor.* }, cursel, s.len); - if (s.len == 1) self.run_triggers(s[0], .insert); + if (s.len == 1) self.run_triggers(cursel, s[0], .insert); return root_; } @@ -6253,11 +6253,12 @@ pub const Editor = struct { return false; } - pub fn run_triggers(self: *Self, char: u8, event: TriggerEvent) void { + pub fn run_triggers(self: *Self, cursel: *const CurSel, char: u8, event: TriggerEvent) void { switch (char) { '\n', '\t', ' ' => return, else => {}, } + if (!cursel.cursor.eql(self.get_primary().cursor)) return; for (self.get_event_triggers(event).items) |item| if (item.char == char) { if (command.log_execute) self.logger.print("trigger: {t} '{c}' {?s}({d})", .{ event, char, command.get_name(item.command), item.command }); diff --git a/src/tui/mode/overlay/completion_dropdown.zig b/src/tui/mode/overlay/completion_dropdown.zig index 779559b..ab6e8c8 100644 --- a/src/tui/mode/overlay/completion_dropdown.zig +++ b/src/tui/mode/overlay/completion_dropdown.zig @@ -122,7 +122,7 @@ pub fn update_query(self: *Type, query: []const u8) void { editor.need_render(); if (query.len > 0) { const last_char = query[query.len - 1]; - editor.run_triggers(last_char, .insert); + editor.run_triggers(primary, last_char, .insert); } return; }