feat: more work on new find in files results table

This commit is contained in:
CJ van den Berg 2024-07-27 23:57:56 +02:00
parent a5f27f51a1
commit f535fc02bf
6 changed files with 105 additions and 43 deletions

View file

@ -155,7 +155,7 @@ pub fn need_reflow() void {
tp.self_pid().send(.{"reflow"}) catch {};
}
pub fn name(self: Self, buf: []u8) []u8 {
pub fn name(self: Self, buf: []u8) []const u8 {
return self.plane.name(buf);
}

View file

@ -3129,17 +3129,11 @@ pub const Editor = struct {
return self.find_in(query, ripgrep.find_in_stdin, true);
}
pub fn find_in_files(self: *Self, query: []const u8) !void {
return self.find_in(query, ripgrep.find_in_files, false);
}
pub fn add_match(self: *Self, m: tp.message) !void {
var path: []const u8 = undefined;
var begin_line: usize = undefined;
var begin_pos: usize = undefined;
var end_line: usize = undefined;
var end_pos: usize = undefined;
var lines: []const u8 = undefined;
var batch_cbor: []const u8 = undefined;
if (try m.match(.{ "A", "done", self.match_token })) {
self.add_match_done();
@ -3149,8 +3143,6 @@ pub const Editor = struct {
self.add_match_internal(begin_line, begin_pos, end_line, end_pos);
} else if (try m.match(.{ tp.any, tp.extract(&begin_line), tp.extract(&begin_pos), tp.extract(&end_line), tp.extract(&end_pos) })) {
self.add_match_internal(begin_line, begin_pos, end_line, end_pos);
} else if (try m.match(.{ tp.any, tp.extract(&path), tp.extract(&begin_line), tp.extract(&begin_pos), tp.extract(&end_line), tp.extract(&end_pos), tp.extract(&lines) })) {
self.logger.print("match: {s}:{d}:{d}:{d}:{d} {s}", .{ path, begin_line, begin_pos + 1, end_line, end_pos + 1, std.fmt.fmtSliceEscapeLower(lines) });
}
}

View file

@ -57,12 +57,6 @@ pub fn create(allocator: Allocator, parent: Plane) !Widget {
.on_scroll = EventHandler.bind(self, Self.handle_scroll),
}),
};
(try self.entries.addOne()).* = .{ .path = "file_path_1.zig", .begin_line = 1, .begin_pos = 1, .end_line = 1, .end_pos = 10, .lines = "matching text" };
(try self.entries.addOne()).* = .{ .path = "file_path_2.zig", .begin_line = 1, .begin_pos = 1, .end_line = 1, .end_pos = 10, .lines = "matching text" };
(try self.entries.addOne()).* = .{ .path = "file_path_3.zig", .begin_line = 1, .begin_pos = 1, .end_line = 1, .end_pos = 10, .lines = "matching text" };
try self.add_item(0);
try self.add_item(1);
try self.add_item(2);
return Widget.to(self);
}
@ -72,23 +66,47 @@ pub fn deinit(self: *Self, a: Allocator) void {
}
pub fn handle_resize(self: *Self, pos: Widget.Box) void {
self.plane.move_yx(@intCast(pos.y), @intCast(pos.x)) catch return;
self.plane.resize_simple(@intCast(pos.h), @intCast(pos.w)) catch return;
self.menu.resize(pos);
}
fn add_item(self: *Self, idx: usize) !void {
pub fn walk(self: *Self, walk_ctx: *anyopaque, f: Widget.WalkFn, w: *Widget) bool {
return self.menu.walk(walk_ctx, f) or f(walk_ctx, w);
}
pub fn add_item(self: *Self, entry_: Entry) !void {
const idx = self.entries.items.len;
const entry = (try self.entries.addOne());
entry.* = entry_;
entry.path = try self.allocator.dupe(u8, entry_.path);
entry.lines = try self.allocator.dupe(u8, entry_.lines);
var label = std.ArrayList(u8).init(self.allocator);
defer label.deinit();
const writer = label.writer();
try cbor.writeValue(writer, idx);
try self.menu.add_item_with_handler(label.items, handle_menu_action);
cbor.writeValue(writer, idx) catch return;
self.menu.add_item_with_handler(label.items, handle_menu_action) catch return;
self.menu.resize(Widget.Box.from(self.plane));
}
pub fn reset(self: *Self) void {
for (self.entries.items) |entry| {
self.allocator.free(entry.path);
self.allocator.free(entry.lines);
}
self.entries.clearRetainingCapacity();
self.menu.reset_items();
}
pub fn render(self: *Self, theme: *const Widget.Theme) bool {
self.plane.set_base_style(" ", theme.panel);
self.plane.erase();
self.plane.home();
return self.menu.render(theme);
}
fn handle_render_menu(self: *Self, button: *Button.State(*Menu.State(*Self)), theme: *const Widget.Theme, selected: bool) bool {
const style_base = if (button.active) theme.editor_cursor else if (button.hover or selected) theme.editor_selection else theme.editor_widget;
const style_base = if (button.active) theme.editor_cursor else if (button.hover or selected) theme.editor_selection else theme.panel;
// const style_keybind = if (tui.find_scope_style(theme, "entity.name")) |sty| sty.style else style_base;
button.plane.set_base_style(" ", style_base);
button.plane.erase();
@ -102,14 +120,13 @@ fn handle_render_menu(self: *Self, button: *Button.State(*Menu.State(*Self)), th
return false;
}
if (idx >= self.entries.items.len) {
self.logger.print_err(name, "table entry index out of range: {d}/{d}", .{ idx, self.entries.items.len });
return false;
}
const entry = &self.entries.items[idx];
const pointer = if (selected) "" else " ";
_ = button.plane.print("{s} ", .{pointer}) catch {};
button.plane.set_style(style_base);
_ = button.plane.print("{s} ", .{entry.path}) catch {};
_ = button.plane.print("{s}:{d} {s}", .{entry.path, entry.begin_line + 1, entry.lines}) catch {};
return false;
}
@ -143,12 +160,12 @@ fn handle_menu_action(menu: **Menu.State(*Self), button: *Button.State(*Menu.Sta
tp.self_pid().send(.{ "cmd", "navigate", .{
.file = entry.path,
.goto = .{
entry.end_line + 1,
entry.end_pos + 2,
entry.begin_line,
entry.begin_pos,
entry.begin_line,
entry.begin_pos,
entry.begin_pos + 1,
entry.end_line,
entry.end_pos,
entry.end_pos + 1,
},
} }) catch |e| self.logger.err("navigate", e);
}

View file

@ -2,6 +2,7 @@ const std = @import("std");
const tp = @import("thespian");
const cbor = @import("cbor");
const tracy = @import("tracy");
const ripgrep = @import("ripgrep");
const root = @import("root");
const location_history = @import("location_history");
const project_manager = @import("project_manager");
@ -33,6 +34,7 @@ panels: ?*WidgetList = null,
last_match_text: ?[]const u8 = null,
location_history: location_history,
file_stack: std.ArrayList([]const u8),
find_in_files_done: bool = false,
const NavState = struct {
time: i64 = 0,
@ -80,13 +82,45 @@ pub fn deinit(self: *Self, a: std.mem.Allocator) void {
}
pub fn receive(self: *Self, from_: tp.pid_ref, m: tp.message) error{Exit}!bool {
if (try m.match(.{"write_restore_info"})) {
var path: []const u8 = undefined;
var begin_line: usize = undefined;
var begin_pos: usize = undefined;
var end_line: usize = undefined;
var end_pos: usize = undefined;
var lines: []const u8 = undefined;
if (try m.match(.{ "FIF", tp.extract(&path), tp.extract(&begin_line), tp.extract(&begin_pos), tp.extract(&end_line), tp.extract(&end_pos), tp.extract(&lines) })) {
try self.add_find_in_files_result(path, begin_line, begin_pos, end_line, end_pos, lines);
return true;
} else if (try m.match(.{ "FIF", "done" })) {
self.find_in_files_done = true;
return true;
} else if (try m.match(.{"write_restore_info"})) {
self.write_restore_info();
return true;
}
return if (try self.floating_views.send(from_, m)) true else self.widgets.send(from_, m);
}
fn add_find_in_files_result(self: *Self, path: []const u8, begin_line: usize, begin_pos: usize, end_line: usize, end_pos: usize, lines: []const u8) tp.result {
const filelist_view = @import("filelist_view.zig");
if (!self.is_panel_view_showing(filelist_view))
_ = self.toggle_panel_view(filelist_view, false) catch |e| return tp.exit_error(e, @errorReturnTrace());
const fl = self.get_panel_view(filelist_view) orelse @panic("filelist_view missing");
if (self.find_in_files_done) {
self.find_in_files_done = false;
fl.reset();
}
@import("log").logger("mainview").print("match: {s}:{d}:{d}:{d}:{d} {s}", .{ path, begin_line, begin_pos + 1, end_line, end_pos + 1, std.fmt.fmtSliceEscapeLower(lines) });
fl.add_item(.{
.path = path,
.begin_line = begin_line - 1,
.begin_pos = begin_pos - 1,
.end_line = end_line - 1,
.end_pos = end_pos - 1,
.lines = lines
}) catch |e| return tp.exit_error(e, @errorReturnTrace());
}
pub fn update(self: *Self) void {
self.widgets.update();
self.floating_views.update();
@ -132,6 +166,14 @@ fn toggle_panel_view(self: *Self, view: anytype, enable_only: bool) !bool {
return enabled;
}
fn get_panel_view(self: *Self, comptime view: type) ?*view {
return if (self.panels) |panels| if (panels.get(@typeName(view))) |w| w.dynamic_cast(view) else null else null;
}
fn is_panel_view_showing(self: *Self, comptime view: type) bool {
return self.get_panel_view(view) != null;
}
fn close_all_panel_views(self: *Self) void {
if (self.panels) |panels| {
self.widgets.remove(panels.widget());
@ -265,6 +307,13 @@ const cmds = struct {
tui.need_render();
}
pub fn toggle_panel(self: *Self, _: Ctx) Result {
if (self.is_panel_view_showing(@import("filelist_view.zig")))
_ = try self.toggle_panel_view(@import("filelist_view.zig"), false)
else
_ = try self.toggle_panel_view(@import("logview.zig"), false);
}
pub fn toggle_logview(self: *Self, _: Ctx) Result {
_ = try self.toggle_panel_view(@import("logview.zig"), false);
}
@ -289,6 +338,10 @@ const cmds = struct {
_ = try self.toggle_panel_view(@import("filelist_view.zig"), false);
}
pub fn show_filelist_view(self: *Self, _: Ctx) Result {
_ = try self.toggle_panel_view(@import("filelist_view.zig"), true);
}
pub fn jump_back(self: *Self, _: Ctx) Result {
try self.location_history.back(location_jump);
}
@ -360,6 +413,13 @@ pub fn handle_editor_event(self: *Self, _: tp.pid_ref, m: tp.message) tp.result
}
}
pub fn find_in_files(self: *Self, query: []const u8) !void {
const find_f = ripgrep.find_in_files;
if (std.mem.indexOfScalar(u8, query, '\n')) |_| return;
var rg = try find_f(self.a, query, "FIF");
defer rg.deinit();
}
pub fn location_update(self: *Self, m: tp.message) tp.result {
var row: usize = 0;
var col: usize = 0;

View file

@ -81,7 +81,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
'E' => self.cmd("open_recent", .{}),
'J' => self.cmd("toggle_logview", .{}),
'J' => self.cmd("toggle_panel", .{}),
'Z' => self.cmd("undo", .{}),
'Y' => self.cmd("redo", .{}),
'Q' => self.cmd("quit", .{}),
@ -199,7 +199,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
key.F07 => self.cmd("dump_current_line", .{}),
key.F09 => self.cmd("theme_prev", .{}),
key.F10 => self.cmd("theme_next", .{}),
key.F11 => self.cmd("toggle_logview", .{}),
key.F11 => self.cmd("toggle_panel", .{}),
key.F12 => self.cmd("goto_definition", .{}),
key.F34 => self.cmd("toggle_whitespace", .{}), // C-F10
key.F58 => self.cmd("gutter_mode_next", .{}), // A-F10

View file

@ -22,27 +22,23 @@ buf: [1024]u8 = undefined,
input: []u8 = "",
last_buf: [1024]u8 = undefined,
last_input: []u8 = "",
start_view: ed.View,
start_cursor: ed.Cursor,
editor: *ed.Editor,
mainview: *mainview,
pub fn create(a: Allocator, _: command.Context) !*Self {
const self: *Self = try a.create(Self);
if (tui.current().mainview.dynamic_cast(mainview)) |mv_| if (mv_.get_editor()) |editor| {
if (tui.current().mainview.dynamic_cast(mainview)) |mv| {
self.* = .{
.a = a,
.start_view = editor.view,
.start_cursor = editor.get_primary().cursor,
.editor = editor,
.mainview = mv,
};
if (editor.get_primary().selection) |sel| ret: {
if (mv.get_editor()) |editor| if (editor.get_primary().selection) |sel| ret: {
const text = editor.get_selection(sel, self.a) catch break :ret;
defer self.a.free(text);
@memcpy(self.buf[0..text.len], text);
self.input = self.buf[0..text.len];
}
};
return self;
};
}
return error.NotFound;
}
@ -178,8 +174,7 @@ fn flush_input(self: *Self) !void {
return;
@memcpy(self.last_buf[0..self.input.len], self.input);
self.last_input = self.last_buf[0..self.input.len];
command.executeName("show_logview", .{}) catch {};
try self.editor.find_in_files(self.input);
try self.mainview.find_in_files(self.input);
}
}
@ -188,8 +183,6 @@ fn cmd(self: *Self, name_: []const u8, ctx: command.Context) tp.result {
return command.executeName(name_, ctx);
}
fn cancel(self: *Self) void {
self.editor.get_primary().cursor = self.start_cursor;
self.editor.scroll_to(self.start_view.row);
fn cancel(_: *Self) void {
command.executeName("exit_mini_mode", .{}) catch {};
}