feat: more work on new find in files results table
This commit is contained in:
parent
a5f27f51a1
commit
f535fc02bf
6 changed files with 105 additions and 43 deletions
|
@ -155,7 +155,7 @@ pub fn need_reflow() void {
|
||||||
tp.self_pid().send(.{"reflow"}) catch {};
|
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);
|
return self.plane.name(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3129,17 +3129,11 @@ pub const Editor = struct {
|
||||||
return self.find_in(query, ripgrep.find_in_stdin, true);
|
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 {
|
pub fn add_match(self: *Self, m: tp.message) !void {
|
||||||
var path: []const u8 = undefined;
|
|
||||||
var begin_line: usize = undefined;
|
var begin_line: usize = undefined;
|
||||||
var begin_pos: usize = undefined;
|
var begin_pos: usize = undefined;
|
||||||
var end_line: usize = undefined;
|
var end_line: usize = undefined;
|
||||||
var end_pos: usize = undefined;
|
var end_pos: usize = undefined;
|
||||||
var lines: []const u8 = undefined;
|
|
||||||
var batch_cbor: []const u8 = undefined;
|
var batch_cbor: []const u8 = undefined;
|
||||||
if (try m.match(.{ "A", "done", self.match_token })) {
|
if (try m.match(.{ "A", "done", self.match_token })) {
|
||||||
self.add_match_done();
|
self.add_match_done();
|
||||||
|
@ -3149,8 +3143,6 @@ pub const Editor = struct {
|
||||||
self.add_match_internal(begin_line, begin_pos, end_line, end_pos);
|
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) })) {
|
} 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);
|
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) });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,12 +57,6 @@ pub fn create(allocator: Allocator, parent: Plane) !Widget {
|
||||||
.on_scroll = EventHandler.bind(self, Self.handle_scroll),
|
.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);
|
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 {
|
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);
|
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);
|
var label = std.ArrayList(u8).init(self.allocator);
|
||||||
defer label.deinit();
|
defer label.deinit();
|
||||||
const writer = label.writer();
|
const writer = label.writer();
|
||||||
try cbor.writeValue(writer, idx);
|
cbor.writeValue(writer, idx) catch return;
|
||||||
try self.menu.add_item_with_handler(label.items, handle_menu_action);
|
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 {
|
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);
|
return self.menu.render(theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_render_menu(self: *Self, button: *Button.State(*Menu.State(*Self)), theme: *const Widget.Theme, selected: bool) bool {
|
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;
|
// 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.set_base_style(" ", style_base);
|
||||||
button.plane.erase();
|
button.plane.erase();
|
||||||
|
@ -102,14 +120,13 @@ fn handle_render_menu(self: *Self, button: *Button.State(*Menu.State(*Self)), th
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (idx >= self.entries.items.len) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
const entry = &self.entries.items[idx];
|
const entry = &self.entries.items[idx];
|
||||||
const pointer = if (selected) "⏵" else " ";
|
const pointer = if (selected) "⏵" else " ";
|
||||||
_ = button.plane.print("{s} ", .{pointer}) catch {};
|
_ = button.plane.print("{s} ", .{pointer}) catch {};
|
||||||
button.plane.set_style(style_base);
|
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;
|
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", .{
|
tp.self_pid().send(.{ "cmd", "navigate", .{
|
||||||
.file = entry.path,
|
.file = entry.path,
|
||||||
.goto = .{
|
.goto = .{
|
||||||
|
entry.end_line + 1,
|
||||||
|
entry.end_pos + 2,
|
||||||
entry.begin_line,
|
entry.begin_line,
|
||||||
entry.begin_pos,
|
entry.begin_pos + 1,
|
||||||
entry.begin_line,
|
|
||||||
entry.begin_pos,
|
|
||||||
entry.end_line,
|
entry.end_line,
|
||||||
entry.end_pos,
|
entry.end_pos + 1,
|
||||||
},
|
},
|
||||||
} }) catch |e| self.logger.err("navigate", e);
|
} }) catch |e| self.logger.err("navigate", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ const std = @import("std");
|
||||||
const tp = @import("thespian");
|
const tp = @import("thespian");
|
||||||
const cbor = @import("cbor");
|
const cbor = @import("cbor");
|
||||||
const tracy = @import("tracy");
|
const tracy = @import("tracy");
|
||||||
|
const ripgrep = @import("ripgrep");
|
||||||
const root = @import("root");
|
const root = @import("root");
|
||||||
const location_history = @import("location_history");
|
const location_history = @import("location_history");
|
||||||
const project_manager = @import("project_manager");
|
const project_manager = @import("project_manager");
|
||||||
|
@ -33,6 +34,7 @@ panels: ?*WidgetList = null,
|
||||||
last_match_text: ?[]const u8 = null,
|
last_match_text: ?[]const u8 = null,
|
||||||
location_history: location_history,
|
location_history: location_history,
|
||||||
file_stack: std.ArrayList([]const u8),
|
file_stack: std.ArrayList([]const u8),
|
||||||
|
find_in_files_done: bool = false,
|
||||||
|
|
||||||
const NavState = struct {
|
const NavState = struct {
|
||||||
time: i64 = 0,
|
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 {
|
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();
|
self.write_restore_info();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return if (try self.floating_views.send(from_, m)) true else self.widgets.send(from_, m);
|
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 {
|
pub fn update(self: *Self) void {
|
||||||
self.widgets.update();
|
self.widgets.update();
|
||||||
self.floating_views.update();
|
self.floating_views.update();
|
||||||
|
@ -132,6 +166,14 @@ fn toggle_panel_view(self: *Self, view: anytype, enable_only: bool) !bool {
|
||||||
return enabled;
|
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 {
|
fn close_all_panel_views(self: *Self) void {
|
||||||
if (self.panels) |panels| {
|
if (self.panels) |panels| {
|
||||||
self.widgets.remove(panels.widget());
|
self.widgets.remove(panels.widget());
|
||||||
|
@ -265,6 +307,13 @@ const cmds = struct {
|
||||||
tui.need_render();
|
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 {
|
pub fn toggle_logview(self: *Self, _: Ctx) Result {
|
||||||
_ = try self.toggle_panel_view(@import("logview.zig"), false);
|
_ = 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);
|
_ = 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 {
|
pub fn jump_back(self: *Self, _: Ctx) Result {
|
||||||
try self.location_history.back(location_jump);
|
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 {
|
pub fn location_update(self: *Self, m: tp.message) tp.result {
|
||||||
var row: usize = 0;
|
var row: usize = 0;
|
||||||
var col: usize = 0;
|
var col: usize = 0;
|
||||||
|
|
|
@ -81,7 +81,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
|
||||||
return switch (modifiers) {
|
return switch (modifiers) {
|
||||||
mod.CTRL => switch (keynormal) {
|
mod.CTRL => switch (keynormal) {
|
||||||
'E' => self.cmd("open_recent", .{}),
|
'E' => self.cmd("open_recent", .{}),
|
||||||
'J' => self.cmd("toggle_logview", .{}),
|
'J' => self.cmd("toggle_panel", .{}),
|
||||||
'Z' => self.cmd("undo", .{}),
|
'Z' => self.cmd("undo", .{}),
|
||||||
'Y' => self.cmd("redo", .{}),
|
'Y' => self.cmd("redo", .{}),
|
||||||
'Q' => self.cmd("quit", .{}),
|
'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.F07 => self.cmd("dump_current_line", .{}),
|
||||||
key.F09 => self.cmd("theme_prev", .{}),
|
key.F09 => self.cmd("theme_prev", .{}),
|
||||||
key.F10 => self.cmd("theme_next", .{}),
|
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.F12 => self.cmd("goto_definition", .{}),
|
||||||
key.F34 => self.cmd("toggle_whitespace", .{}), // C-F10
|
key.F34 => self.cmd("toggle_whitespace", .{}), // C-F10
|
||||||
key.F58 => self.cmd("gutter_mode_next", .{}), // A-F10
|
key.F58 => self.cmd("gutter_mode_next", .{}), // A-F10
|
||||||
|
|
|
@ -22,27 +22,23 @@ buf: [1024]u8 = undefined,
|
||||||
input: []u8 = "",
|
input: []u8 = "",
|
||||||
last_buf: [1024]u8 = undefined,
|
last_buf: [1024]u8 = undefined,
|
||||||
last_input: []u8 = "",
|
last_input: []u8 = "",
|
||||||
start_view: ed.View,
|
mainview: *mainview,
|
||||||
start_cursor: ed.Cursor,
|
|
||||||
editor: *ed.Editor,
|
|
||||||
|
|
||||||
pub fn create(a: Allocator, _: command.Context) !*Self {
|
pub fn create(a: Allocator, _: command.Context) !*Self {
|
||||||
const self: *Self = try a.create(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.* = .{
|
self.* = .{
|
||||||
.a = a,
|
.a = a,
|
||||||
.start_view = editor.view,
|
.mainview = mv,
|
||||||
.start_cursor = editor.get_primary().cursor,
|
|
||||||
.editor = editor,
|
|
||||||
};
|
};
|
||||||
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;
|
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);
|
@memcpy(self.buf[0..text.len], text);
|
||||||
self.input = self.buf[0..text.len];
|
self.input = self.buf[0..text.len];
|
||||||
}
|
|
||||||
return self;
|
|
||||||
};
|
};
|
||||||
|
return self;
|
||||||
|
}
|
||||||
return error.NotFound;
|
return error.NotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,8 +174,7 @@ fn flush_input(self: *Self) !void {
|
||||||
return;
|
return;
|
||||||
@memcpy(self.last_buf[0..self.input.len], self.input);
|
@memcpy(self.last_buf[0..self.input.len], self.input);
|
||||||
self.last_input = self.last_buf[0..self.input.len];
|
self.last_input = self.last_buf[0..self.input.len];
|
||||||
command.executeName("show_logview", .{}) catch {};
|
try self.mainview.find_in_files(self.input);
|
||||||
try self.editor.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);
|
return command.executeName(name_, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cancel(self: *Self) void {
|
fn cancel(_: *Self) void {
|
||||||
self.editor.get_primary().cursor = self.start_cursor;
|
|
||||||
self.editor.scroll_to(self.start_view.row);
|
|
||||||
command.executeName("exit_mini_mode", .{}) catch {};
|
command.executeName("exit_mini_mode", .{}) catch {};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue