fix: prevent different match types from cancelling each other out

This commit is contained in:
CJ van den Berg 2025-11-10 13:55:47 +01:00
parent 7b9a4071c8
commit 36c975dc20
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
3 changed files with 46 additions and 21 deletions

View file

@ -64,6 +64,12 @@ pub const Match = struct {
has_selection: bool = false, has_selection: bool = false,
style: ?Widget.Theme.Style = null, style: ?Widget.Theme.Style = null,
const Type = enum {
none,
auto_find,
find,
highlight_references,
};
const List = std.ArrayListUnmanaged(?Self); const List = std.ArrayListUnmanaged(?Self);
const Self = @This(); const Self = @This();
@ -325,7 +331,9 @@ pub const Editor = struct {
matches: Match.List = .empty, matches: Match.List = .empty,
match_token: usize = 0, match_token: usize = 0,
match_done_token: usize = 0, match_done_token: usize = 0,
match_type: Match.Type = .none,
last_find_query: ?[]const u8 = null, last_find_query: ?[]const u8 = null,
last_find_query_match_type: Match.Type = .none,
find_history: ?std.ArrayListUnmanaged([]const u8) = null, find_history: ?std.ArrayListUnmanaged([]const u8) = null,
find_operation: ?enum { goto_next_match, goto_prev_match } = null, find_operation: ?enum { goto_next_match, goto_prev_match } = null,
highlight_references_state: enum { adding, done } = .done, highlight_references_state: enum { adding, done } = .done,
@ -1910,10 +1918,17 @@ pub const Editor = struct {
fn cancel_all_matches(self: *Self) void { fn cancel_all_matches(self: *Self) void {
self.matches.clearAndFree(self.allocator); self.matches.clearAndFree(self.allocator);
self.match_type = .none;
} }
pub fn have_matches(self: *Self) bool { pub fn init_matches_update(self: *Self) void {
return self.matches.items.len > 0; self.matches.clearAndFree(self.allocator);
self.match_token += 1;
}
pub fn have_matches_not_of_type(self: *Self, match_type: Match.Type) bool {
if (self.matches.items.len == 0) return false;
return self.match_type != match_type;
} }
pub fn clear_matches(self: *Self) void { pub fn clear_matches(self: *Self) void {
@ -1922,6 +1937,14 @@ pub const Editor = struct {
self.match_done_token = self.match_token; self.match_done_token = self.match_token;
} }
pub fn clear_matches_if_type(self: *Self, match_type: Match.Type) bool {
if (self.match_type == match_type) {
self.clear_matches();
return true;
}
return false;
}
pub fn sort_matches(self: *Self) void { pub fn sort_matches(self: *Self) void {
const less_fn = struct { const less_fn = struct {
fn less_fn(_: void, lhs_: ?Match, rhs_: ?Match) bool { fn less_fn(_: void, lhs_: ?Match, rhs_: ?Match) bool {
@ -1936,11 +1959,6 @@ pub const Editor = struct {
std.mem.sort(?Match, self.matches.items, {}, less_fn); std.mem.sort(?Match, self.matches.items, {}, less_fn);
} }
pub fn init_matches_update(self: *Self) void {
self.cancel_all_matches();
self.match_token += 1;
}
fn with_cursor_const(root: Buffer.Root, move: cursor_operator_const, cursel: *CurSel, metrics: Buffer.Metrics) error{Stop}!void { fn with_cursor_const(root: Buffer.Root, move: cursor_operator_const, cursel: *CurSel, metrics: Buffer.Metrics) error{Stop}!void {
try move(root, &cursel.cursor, metrics); try move(root, &cursel.cursor, metrics);
} }
@ -5139,8 +5157,13 @@ pub const Editor = struct {
pub fn find_query(self: *Self, ctx: Context) Result { pub fn find_query(self: *Self, ctx: Context) Result {
var query: []const u8 = undefined; var query: []const u8 = undefined;
var match_type: Match.Type = undefined;
if (ctx.args.match(.{tp.extract(&query)}) catch false) { if (ctx.args.match(.{tp.extract(&query)}) catch false) {
try self.find_in_buffer(query); self.match_type = .find;
try self.find_in_buffer(query, .none);
self.clamp();
} else if (ctx.args.match(.{ tp.extract(&query), tp.extract(&match_type) }) catch false) {
try self.find_in_buffer(query, match_type);
self.clamp(); self.clamp();
} else return error.InvalidFindQueryArgument; } else return error.InvalidFindQueryArgument;
} }
@ -5150,7 +5173,7 @@ pub const Editor = struct {
_ = ctx; _ = ctx;
const query: []const u8 = try self.copy_word_at_cursor(self.allocator); const query: []const u8 = try self.copy_word_at_cursor(self.allocator);
defer self.allocator.free(query); defer self.allocator.free(query);
try self.find_in_buffer(query); try self.find_in_buffer(query, .find);
} }
pub const find_word_at_cursor_meta: Meta = .{ .description = "Search for the word under the cursor" }; pub const find_word_at_cursor_meta: Meta = .{ .description = "Search for the word under the cursor" };
@ -5181,7 +5204,8 @@ pub const Editor = struct {
(history.addOne(self.allocator) catch return).* = new; (history.addOne(self.allocator) catch return).* = new;
} }
fn set_last_find_query(self: *Self, query: []const u8) void { fn set_last_find_query(self: *Self, query: []const u8, match_type: Match.Type) void {
self.last_find_query_match_type = match_type;
if (self.last_find_query) |last| { if (self.last_find_query) |last| {
if (query.ptr != last.ptr) { if (query.ptr != last.ptr) {
self.allocator.free(last); self.allocator.free(last);
@ -5190,8 +5214,9 @@ pub const Editor = struct {
} else self.last_find_query = self.allocator.dupe(u8, query) catch return; } else self.last_find_query = self.allocator.dupe(u8, query) catch return;
} }
pub fn find_in_buffer(self: *Self, query: []const u8) !void { pub fn find_in_buffer(self: *Self, query: []const u8, match_type: Match.Type) !void {
self.set_last_find_query(query); self.set_last_find_query(query, match_type);
self.match_type = match_type;
return self.find_in_buffer_sync(query); return self.find_in_buffer_sync(query);
} }
@ -5424,7 +5449,7 @@ pub const Editor = struct {
if (self.matches.items.len == 0) { if (self.matches.items.len == 0) {
if (self.last_find_query) |last| { if (self.last_find_query) |last| {
self.find_operation = .goto_next_match; self.find_operation = .goto_next_match;
try self.find_in_buffer(last); try self.find_in_buffer(last, self.last_find_query_match_type);
} }
} }
try self.move_cursor_next_match(ctx); try self.move_cursor_next_match(ctx);
@ -5453,7 +5478,7 @@ pub const Editor = struct {
if (self.matches.items.len == 0) { if (self.matches.items.len == 0) {
if (self.last_find_query) |last| { if (self.last_find_query) |last| {
self.find_operation = .goto_prev_match; self.find_operation = .goto_prev_match;
try self.find_in_buffer(last); try self.find_in_buffer(last, self.last_find_query_match_type);
} }
} }
try self.move_cursor_prev_match(ctx); try self.move_cursor_prev_match(ctx);
@ -5832,6 +5857,7 @@ pub const Editor = struct {
pub const highlight_references_meta: Meta = .{ .description = "Language: Highlight references" }; pub const highlight_references_meta: Meta = .{ .description = "Language: Highlight references" };
pub fn add_highlight_reference(self: *Self, match_: Match) void { pub fn add_highlight_reference(self: *Self, match_: Match) void {
self.match_type = .highlight_references;
if (self.highlight_references_state == .done) { if (self.highlight_references_state == .done) {
self.highlight_references_state = .adding; self.highlight_references_state = .adding;
self.cancel_all_matches(); self.cancel_all_matches();

View file

@ -1269,16 +1269,15 @@ pub fn handle_editor_event(self: *Self, _: tp.pid_ref, m: tp.message) tp.result
if (try m.match(.{ tp.any, tp.any, "none" })) if (try m.match(.{ tp.any, tp.any, "none" }))
return self.clear_auto_find(editor); return self.clear_auto_find(editor);
if (try m.match(.{ tp.any, tp.any, tp.extract(&sel.begin.row), tp.extract(&sel.begin.col), tp.extract(&sel.end.row), tp.extract(&sel.end.col) })) { if (try m.match(.{ tp.any, tp.any, tp.extract(&sel.begin.row), tp.extract(&sel.begin.col), tp.extract(&sel.end.row), tp.extract(&sel.end.col) })) {
if (editor.have_matches()) return; if (editor.have_matches_not_of_type(.auto_find)) return;
sel.normalize(); sel.normalize();
if (sel.end.row - sel.begin.row > ed.max_match_lines) if (sel.end.row - sel.begin.row > ed.max_match_lines)
return self.clear_auto_find(editor); return self.clear_auto_find(editor);
const text = editor.get_selection(sel, self.allocator) catch return self.clear_auto_find(editor); const text = editor.get_selection(sel, self.allocator) catch return self.clear_auto_find(editor);
if (text.len == 0) if (text.len == 0)
return self.clear_auto_find(editor); return self.clear_auto_find(editor);
if (!self.is_last_match_text(text)) { if (!self.is_last_match_text(text))
tp.self_pid().send(.{ "cmd", "find_query", .{text} }) catch return; tp.self_pid().send(.{ "cmd", "find_query", .{ text, "auto_find" } }) catch return;
}
} }
return; return;
} }
@ -1327,8 +1326,8 @@ fn location_jump(from: tp.pid_ref, file_path: []const u8, cursor: location_histo
} }
fn clear_auto_find(self: *Self, editor: *ed.Editor) void { fn clear_auto_find(self: *Self, editor: *ed.Editor) void {
editor.clear_matches(); if (editor.clear_matches_if_type(.auto_find))
self.store_last_match_text(null); self.store_last_match_text(null);
} }
fn is_last_match_text(self: *Self, text: []const u8) bool { fn is_last_match_text(self: *Self, text: []const u8) bool {

View file

@ -91,7 +91,7 @@ fn flush_input(self: *Self) !void {
const primary = self.editor.get_primary(); const primary = self.editor.get_primary();
primary.selection = null; primary.selection = null;
primary.cursor = self.start_cursor; primary.cursor = self.start_cursor;
try self.editor.find_in_buffer(self.input_.items); try self.editor.find_in_buffer(self.input_.items, .find);
} else { } else {
self.editor.get_primary().selection = null; self.editor.get_primary().selection = null;
self.editor.init_matches_update(); self.editor.init_matches_update();