refactor(find): use dynamic input buffer in find mode and improve some edge cases

This commit is contained in:
CJ van den Berg 2024-07-05 19:53:13 +02:00
parent 128182a448
commit 66df590541
2 changed files with 37 additions and 38 deletions

View file

@ -1280,7 +1280,7 @@ pub const Editor = struct {
self.match_done_token = self.match_token; self.match_done_token = self.match_token;
} }
fn init_matches_update(self: *Self) void { pub fn init_matches_update(self: *Self) void {
self.cancel_all_matches(); self.cancel_all_matches();
self.match_token += 1; self.match_token += 1;
} }
@ -3046,9 +3046,9 @@ pub const Editor = struct {
} }
}; };
const root = try self.buf_root(); const root = try self.buf_root();
defer tp.self_pid().send(.{ "A", "done", self.match_token }) catch {}; defer self.add_match_done();
var ctx: Ctx = .{ .self = self }; var ctx: Ctx = .{ .self = self };
self.init_matches_update() catch {}; self.init_matches_update();
try root.find_all_ranges(query, &ctx, Ctx.cb, self.a); try root.find_all_ranges(query, &ctx, Ctx.cb, self.a);
} }

View file

@ -14,14 +14,13 @@ const ed = @import("../../editor.zig");
const Allocator = @import("std").mem.Allocator; const Allocator = @import("std").mem.Allocator;
const json = @import("std").json; const json = @import("std").json;
const eql = @import("std").mem.eql; const eql = @import("std").mem.eql;
const ArrayList = @import("std").ArrayList;
const Self = @This(); const Self = @This();
a: Allocator, a: Allocator,
buf: [1024]u8 = undefined, input: ArrayList(u8),
input: []u8 = "", last_input: ArrayList(u8),
last_buf: [1024]u8 = undefined,
last_input: []u8 = "",
start_view: ed.View, start_view: ed.View,
start_cursor: ed.Cursor, start_cursor: ed.Cursor,
editor: *ed.Editor, editor: *ed.Editor,
@ -32,6 +31,8 @@ pub fn create(a: Allocator, _: command.Context) !*Self {
const self: *Self = try a.create(Self); const self: *Self = try a.create(Self);
self.* = .{ self.* = .{
.a = a, .a = a,
.input = ArrayList(u8).init(a),
.last_input = ArrayList(u8).init(a),
.start_view = editor.view, .start_view = editor.view,
.start_cursor = editor.get_primary().cursor, .start_cursor = editor.get_primary().cursor,
.editor = editor, .editor = editor,
@ -39,8 +40,7 @@ pub fn create(a: Allocator, _: command.Context) !*Self {
if (editor.get_primary().selection) |sel| ret: { if (editor.get_primary().selection) |sel| ret: {
const text = editor.get_selection(sel, self.a) catch break :ret; const text = editor.get_selection(sel, self.a) catch break :ret;
defer self.a.free(text); defer self.a.free(text);
@memcpy(self.buf[0..text.len], text); try self.input.appendSlice(text);
self.input = self.buf[0..text.len];
} }
return self; return self;
}; };
@ -48,6 +48,8 @@ pub fn create(a: Allocator, _: command.Context) !*Self {
} }
pub fn deinit(self: *Self) void { pub fn deinit(self: *Self) void {
self.input.deinit();
self.last_input.deinit();
self.a.destroy(self); self.a.destroy(self);
} }
@ -68,8 +70,8 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
defer { defer {
if (tui.current().mini_mode) |*mini_mode| { if (tui.current().mini_mode) |*mini_mode| {
mini_mode.text = self.input; mini_mode.text = self.input.items;
mini_mode.cursor = self.input.len; mini_mode.cursor = self.input.items.len;
} }
} }
@ -98,7 +100,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
mod.CTRL => switch (keynormal) { mod.CTRL => switch (keynormal) {
'Q' => self.cmd("quit", .{}), 'Q' => self.cmd("quit", .{}),
'V' => self.cmd("system_paste", .{}), 'V' => self.cmd("system_paste", .{}),
'U' => self.input = "", 'U' => self.input.clearRetainingCapacity(),
'G' => self.cancel(), 'G' => self.cancel(),
'C' => self.cancel(), 'C' => self.cancel(),
'L' => self.cmd("scroll_view_center", .{}), 'L' => self.cmd("scroll_view_center", .{}),
@ -108,7 +110,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'I' => self.insert_bytes("\t"), 'I' => self.insert_bytes("\t"),
key.SPACE => self.cancel(), key.SPACE => self.cancel(),
key.ENTER => self.insert_bytes("\n"), key.ENTER => self.insert_bytes("\n"),
key.BACKSPACE => self.input = "", key.BACKSPACE => self.input.clearRetainingCapacity(),
else => {}, else => {},
}, },
mod.ALT => switch (keynormal) { mod.ALT => switch (keynormal) {
@ -137,9 +139,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
key.F10 => self.cmd("theme_next", .{}), key.F10 => self.cmd("theme_next", .{}),
key.ESC => self.cancel(), key.ESC => self.cancel(),
key.ENTER => self.confirm(), key.ENTER => self.confirm(),
key.BACKSPACE => if (self.input.len > 0) { key.BACKSPACE => _ = self.input.popOrNull(),
self.input = self.input[0 .. self.input.len - 1];
},
key.LCTRL, key.RCTRL => self.cmd("enable_fast_scroll", .{}), key.LCTRL, key.RCTRL => self.cmd("enable_fast_scroll", .{}),
key.LALT, key.RALT => self.cmd("enable_fast_scroll", .{}), key.LALT, key.RALT => self.cmd("enable_fast_scroll", .{}),
else => if (!key.synthesized_p(keypress)) else => if (!key.synthesized_p(keypress))
@ -159,31 +159,31 @@ fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) !void {
} }
fn insert_code_point(self: *Self, c: u32) !void { fn insert_code_point(self: *Self, c: u32) !void {
if (self.input.len + 16 > self.buf.len) var buf: [16]u8 = undefined;
try self.flush_input(); const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e, @errorReturnTrace());
const bytes = ucs32_to_utf8(&[_]u32{c}, self.buf[self.input.len..]) catch |e| return tp.exit_error(e, @errorReturnTrace()); try self.input.appendSlice(buf[0 .. bytes]);
self.input = self.buf[0 .. self.input.len + bytes];
} }
fn insert_bytes(self: *Self, bytes: []const u8) !void { fn insert_bytes(self: *Self, bytes: []const u8) !void {
if (self.input.len + 16 > self.buf.len) try self.input.appendSlice(bytes);
try self.flush_input();
const newlen = self.input.len + bytes.len;
@memcpy(self.buf[self.input.len..newlen], bytes);
self.input = self.buf[0..newlen];
} }
var find_cmd_id: ?command.ID = null; var find_cmd_id: ?command.ID = null;
fn flush_input(self: *Self) !void { fn flush_input(self: *Self) !void {
if (self.input.len > 0) { if (self.input.items.len > 0) {
if (eql(u8, self.input, self.last_input)) if (eql(u8, self.input.items, self.last_input.items))
return; return;
@memcpy(self.last_buf[0..self.input.len], self.input); self.last_input.clearRetainingCapacity();
self.last_input = self.last_buf[0..self.input.len]; try self.last_input.appendSlice(self.input.items);
self.editor.find_operation = .goto_next_match; self.editor.find_operation = .goto_next_match;
self.editor.get_primary().cursor = self.start_cursor; const primary = self.editor.get_primary();
try self.editor.find_in_buffer(self.input); primary.selection = null;
primary.cursor = self.start_cursor;
try self.editor.find_in_buffer(self.input.items);
} else {
self.editor.get_primary().selection = null;
self.editor.init_matches_update();
} }
} }
@ -193,7 +193,7 @@ fn cmd(self: *Self, name_: []const u8, ctx: command.Context) tp.result {
} }
fn confirm(self: *Self) void { fn confirm(self: *Self) void {
self.editor.push_find_history(self.input); self.editor.push_find_history(self.input.items);
self.cmd("exit_mini_mode", .{}) catch {}; self.cmd("exit_mini_mode", .{}) catch {};
} }
@ -209,9 +209,9 @@ fn find_history_prev(self: *Self) void {
if (pos > 0) self.history_pos = pos - 1; if (pos > 0) self.history_pos = pos - 1;
} else { } else {
self.history_pos = history.items.len - 1; self.history_pos = history.items.len - 1;
if (self.input.len > 0) if (self.input.items.len > 0)
self.editor.push_find_history(self.editor.a.dupe(u8, self.input) catch return); self.editor.push_find_history(self.editor.a.dupe(u8, self.input.items) catch return);
if (eql(u8, history.items[self.history_pos.?], self.input) and self.history_pos.? > 0) if (eql(u8, history.items[self.history_pos.?], self.input.items) and self.history_pos.? > 0)
self.history_pos = self.history_pos.? - 1; self.history_pos = self.history_pos.? - 1;
} }
self.load_history(self.history_pos.?); self.load_history(self.history_pos.?);
@ -229,8 +229,7 @@ fn find_history_next(self: *Self) void {
fn load_history(self: *Self, pos: usize) void { fn load_history(self: *Self, pos: usize) void {
if (self.editor.find_history) |*history| { if (self.editor.find_history) |*history| {
const new = history.items[pos]; self.input.clearRetainingCapacity();
@memcpy(self.buf[0..new.len], new); self.input.appendSlice(history.items[pos]) catch {};
self.input = self.buf[0..new.len];
} }
} }