From 3b4c81c7065b4534171fa829869beb0f9b4370ba Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Thu, 24 Oct 2024 18:27:30 +0200 Subject: [PATCH] feat: add open_previous_file command closes #56 --- src/Project.zig | 5 +++-- src/project_manager.zig | 17 +++++++++++------ src/tui/mainview.zig | 6 ++++++ src/tui/mode/input/flow.zig | 2 ++ src/tui/mode/input/helix/normal.zig | 2 ++ src/tui/mode/input/helix/select.zig | 2 ++ src/tui/mode/input/vim/normal.zig | 2 ++ src/tui/mode/input/vim/visual.zig | 2 ++ 8 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/Project.zig b/src/Project.zig index b704af5..1669a4e 100644 --- a/src/Project.zig +++ b/src/Project.zig @@ -167,8 +167,9 @@ pub fn sort_files_by_mtime(self: *Self) void { std.mem.sort(File, self.files.items, {}, less_fn); } -pub fn request_most_recent_file(self: *Self, from: tp.pid_ref) ClientError!void { - const file_path = if (self.files.items.len > 0) self.files.items[0].path else null; +pub fn request_n_most_recent_file(self: *Self, from: tp.pid_ref, n: usize) ClientError!void { + if (n >= self.files.items.len) return error.ClientFailed; + const file_path = if (self.files.items.len > 0) self.files.items[n].path else null; from.send(.{file_path}) catch return error.ClientFailed; } diff --git a/src/project_manager.zig b/src/project_manager.zig index b29774f..2de2e3a 100644 --- a/src/project_manager.zig +++ b/src/project_manager.zig @@ -64,16 +64,20 @@ pub fn open(rel_project_directory: []const u8) (ProjectManagerError || FileSyste return send(.{ "open", project_directory }); } -pub fn request_most_recent_file(allocator: std.mem.Allocator) (CallError || ProjectError || cbor.Error)!?[]const u8 { +pub fn request_n_most_recent_file(allocator: std.mem.Allocator, n: usize) (CallError || ProjectError || cbor.Error)!?[]const u8 { const project = tp.env.get().str("project"); if (project.len == 0) return error.NoProject; - const rsp = try (try get()).pid.call(allocator, request_timeout, .{ "request_most_recent_file", project }); + const rsp = try (try get()).pid.call(allocator, request_timeout, .{ "request_n_most_recent_file", project, n }); defer allocator.free(rsp.buf); var file_path: []const u8 = undefined; return if (try cbor.match(rsp.buf, .{tp.extract(&file_path)})) try allocator.dupe(u8, file_path) else null; } +pub fn request_most_recent_file(allocator: std.mem.Allocator) (CallError || ProjectError || cbor.Error)!?[]const u8 { + return request_n_most_recent_file(allocator, 0); +} + pub fn request_recent_files(max: usize) (ProjectManagerError || ProjectError)!void { const project = tp.env.get().str("project"); if (project.len == 0) @@ -274,6 +278,7 @@ const Process = struct { var version: usize = 0; var text_ptr: usize = 0; var text_len: usize = 0; + var n: usize = 0; var root_dst: usize = 0; var root_src: usize = 0; @@ -300,8 +305,8 @@ const Process = struct { self.logger.print_err("lsp-handling", "child '{s}' terminated", .{path}); } else if (try cbor.match(m.buf, .{ "open", tp.extract(&project_directory) })) { self.open(project_directory) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed; - } else if (try cbor.match(m.buf, .{ "request_most_recent_file", tp.extract(&project_directory) })) { - self.request_most_recent_file(from, project_directory) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed; + } else if (try cbor.match(m.buf, .{ "request_n_most_recent_file", tp.extract(&project_directory), tp.extract(&n) })) { + self.request_n_most_recent_file(from, project_directory, n) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed; } else if (try cbor.match(m.buf, .{ "request_recent_files", tp.extract(&project_directory), tp.extract(&max) })) { self.request_recent_files(from, project_directory, max) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed; } else if (try cbor.match(m.buf, .{ "request_recent_projects", tp.extract(&project_directory) })) { @@ -375,10 +380,10 @@ const Process = struct { }); } - fn request_most_recent_file(self: *Process, from: tp.pid_ref, project_directory: []const u8) (ProjectError || Project.ClientError)!void { + fn request_n_most_recent_file(self: *Process, from: tp.pid_ref, project_directory: []const u8, n: usize) (ProjectError || Project.ClientError)!void { const project = self.projects.get(project_directory) orelse return error.NoProject; project.sort_files_by_mtime(); - return project.request_most_recent_file(from); + return project.request_n_most_recent_file(from, n); } fn request_recent_files(self: *Process, from: tp.pid_ref, project_directory: []const u8, max: usize) (ProjectError || Project.ClientError)!void { diff --git a/src/tui/mainview.zig b/src/tui/mainview.zig index 1af43ec..41b58dd 100644 --- a/src/tui/mainview.zig +++ b/src/tui/mainview.zig @@ -535,6 +535,12 @@ const cmds = struct { } } pub const show_diagnostics_meta = .{ .description = "Show diagnostics panel" }; + + pub fn open_previous_file(self: *Self, _: Ctx) Result { + const file_path = try project_manager.request_n_most_recent_file(self.allocator, 1); + self.show_file_async_and_free(file_path orelse return error.Stop); + } + pub const open_previous_file_meta = .{ .description = "Open the previous file" }; }; pub fn handle_editor_event(self: *Self, _: tp.pid_ref, m: tp.message) tp.result { diff --git a/src/tui/mode/input/flow.zig b/src/tui/mode/input/flow.zig index 86892e3..a1c0e0d 100644 --- a/src/tui/mode/input/flow.zig +++ b/src/tui/mode/input/flow.zig @@ -143,6 +143,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void { else => {}, }, mod.ALT => switch (keynormal) { + 'O' => self.cmd("open_previous_file", .{}), 'J' => self.cmd("join_next_line", .{}), 'N' => self.cmd("goto_next_file_or_diagnostic", .{}), 'P' => self.cmd("goto_prev_file_or_diagnostic", .{}), @@ -383,6 +384,7 @@ const hints = tui.KeybindHints.initComptime(.{ .{ "move_word_right", "C-right, A-f" }, .{ "open_command_palette", "C-S-p, S-A-p, A-x" }, .{ "open_file", "C-o" }, + .{ "open_previous_file", "A-o" }, .{ "open_recent", "C-e" }, .{ "open_recent_project", "C-r" }, .{ "paste", "A-v" }, diff --git a/src/tui/mode/input/helix/normal.zig b/src/tui/mode/input/helix/normal.zig index 7388c4c..7ca179a 100644 --- a/src/tui/mode/input/helix/normal.zig +++ b/src/tui/mode/input/helix/normal.zig @@ -105,6 +105,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void { }, mod.CTRL | mod.SHIFT => switch (keynormal) { 'P' => self.cmd("open_command_palette", .{}), + '6' => self.cmd("open_previous_file", .{}), else => {}, }, mod.ALT => switch (keynormal) { @@ -604,6 +605,7 @@ const hints = tui.KeybindHints.initComptime(.{ .{ "move_word_right", "C-right, A-f, e" }, .{ "move_word_right_vim", "w" }, .{ "open_command_palette", "Space ?, C-S-p, :, S-;, S-A-p" }, + .{ "open_previous_file", "C-^" }, .{ "open_recent", "C-e" }, .{ "paste", "A-v, p" }, .{ "pop_cursor", "C-u" }, diff --git a/src/tui/mode/input/helix/select.zig b/src/tui/mode/input/helix/select.zig index d84cdc1..1cb30aa 100644 --- a/src/tui/mode/input/helix/select.zig +++ b/src/tui/mode/input/helix/select.zig @@ -105,6 +105,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void { }, mod.CTRL | mod.SHIFT => switch (keynormal) { 'P' => self.cmd("open_command_palette", .{}), + '6' => self.cmd("open_previous_file", .{}), else => {}, }, mod.ALT => switch (keynormal) { @@ -604,6 +605,7 @@ const hints = tui.KeybindHints.initComptime(.{ .{ "move_word_right", "C-right, A-f, e" }, .{ "move_word_right_vim", "w" }, .{ "open_command_palette", "Space ?, C-S-p, :, S-;, S-A-p" }, + .{ "open_previous_file", "C-^" }, .{ "open_recent", "C-e" }, .{ "paste", "A-v, p" }, .{ "pop_cursor", "C-u" }, diff --git a/src/tui/mode/input/vim/normal.zig b/src/tui/mode/input/vim/normal.zig index a12c7ef..ad86c28 100644 --- a/src/tui/mode/input/vim/normal.zig +++ b/src/tui/mode/input/vim/normal.zig @@ -138,6 +138,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void { 'F' => self.cmd("find_in_files", .{}), 'L' => self.cmd_async("add_cursor_all_matches"), 'I' => self.cmd_async("toggle_inspector_view"), + '6' => self.cmd("open_previous_file", .{}), key.ENTER => self.cmd("smart_insert_line_before", .{}), key.END => self.cmd("select_buffer_end", .{}), key.HOME => self.cmd("select_buffer_begin", .{}), @@ -571,6 +572,7 @@ const hints = tui.KeybindHints.initComptime(.{ .{ "move_word_right", "C-right, A-f, e" }, .{ "move_word_right_vim", "w" }, .{ "open_command_palette", "C-S-p, :, S-;, S-A-p" }, + .{ "open_previous_file", "C-^" }, .{ "open_recent", "C-e" }, .{ "paste", "A-v, p" }, .{ "pop_cursor", "C-u" }, diff --git a/src/tui/mode/input/vim/visual.zig b/src/tui/mode/input/vim/visual.zig index 4f51543..878c82a 100644 --- a/src/tui/mode/input/vim/visual.zig +++ b/src/tui/mode/input/vim/visual.zig @@ -138,6 +138,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void { 'F' => self.cmd("find_in_files", .{}), 'L' => self.cmd_async("add_cursor_all_matches"), 'I' => self.cmd_async("toggle_inspector_view"), + '6' => self.cmd("open_previous_file", .{}), key.ENTER => self.cmd("smart_insert_line_before", .{}), key.END => self.cmd("select_buffer_end", .{}), key.HOME => self.cmd("select_buffer_begin", .{}), @@ -481,6 +482,7 @@ const hints = tui.KeybindHints.initComptime(.{ .{ "find", "C-f, /" }, .{ "goto", "C-g" }, .{ "move_to_char", "C-b, C-t" }, // true/false + .{ "open_previous_file", "C-^" }, .{ "open_file", "C-o" }, .{ "filter", "A-s" }, // self.cmd("filter", command.fmt(.{"sort"})), // .{ "filter", "S-A-s" }, // self.cmd("filter", command.fmt(.{ "sort", "-u" })),