feat: add open_previous_file command

closes #56
This commit is contained in:
CJ van den Berg 2024-10-24 18:27:30 +02:00
parent d33d5dcac2
commit 3b4c81c706
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
8 changed files with 30 additions and 8 deletions

View file

@ -167,8 +167,9 @@ pub fn sort_files_by_mtime(self: *Self) void {
std.mem.sort(File, self.files.items, {}, less_fn); std.mem.sort(File, self.files.items, {}, less_fn);
} }
pub fn request_most_recent_file(self: *Self, from: tp.pid_ref) ClientError!void { pub fn request_n_most_recent_file(self: *Self, from: tp.pid_ref, n: usize) ClientError!void {
const file_path = if (self.files.items.len > 0) self.files.items[0].path else null; 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; from.send(.{file_path}) catch return error.ClientFailed;
} }

View file

@ -64,16 +64,20 @@ pub fn open(rel_project_directory: []const u8) (ProjectManagerError || FileSyste
return send(.{ "open", project_directory }); 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"); const project = tp.env.get().str("project");
if (project.len == 0) if (project.len == 0)
return error.NoProject; 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); defer allocator.free(rsp.buf);
var file_path: []const u8 = undefined; 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; 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 { pub fn request_recent_files(max: usize) (ProjectManagerError || ProjectError)!void {
const project = tp.env.get().str("project"); const project = tp.env.get().str("project");
if (project.len == 0) if (project.len == 0)
@ -274,6 +278,7 @@ const Process = struct {
var version: usize = 0; var version: usize = 0;
var text_ptr: usize = 0; var text_ptr: usize = 0;
var text_len: usize = 0; var text_len: usize = 0;
var n: usize = 0;
var root_dst: usize = 0; var root_dst: usize = 0;
var root_src: usize = 0; var root_src: usize = 0;
@ -300,8 +305,8 @@ const Process = struct {
self.logger.print_err("lsp-handling", "child '{s}' terminated", .{path}); self.logger.print_err("lsp-handling", "child '{s}' terminated", .{path});
} else if (try cbor.match(m.buf, .{ "open", tp.extract(&project_directory) })) { } 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; 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) })) { } else if (try cbor.match(m.buf, .{ "request_n_most_recent_file", tp.extract(&project_directory), tp.extract(&n) })) {
self.request_most_recent_file(from, project_directory) catch |e| return from.forward_error(e, @errorReturnTrace()) catch error.ClientFailed; 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) })) { } 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; 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) })) { } 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; const project = self.projects.get(project_directory) orelse return error.NoProject;
project.sort_files_by_mtime(); 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 { fn request_recent_files(self: *Process, from: tp.pid_ref, project_directory: []const u8, max: usize) (ProjectError || Project.ClientError)!void {

View file

@ -535,6 +535,12 @@ const cmds = struct {
} }
} }
pub const show_diagnostics_meta = .{ .description = "Show diagnostics panel" }; 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 { pub fn handle_editor_event(self: *Self, _: tp.pid_ref, m: tp.message) tp.result {

View file

@ -143,6 +143,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
else => {}, else => {},
}, },
mod.ALT => switch (keynormal) { mod.ALT => switch (keynormal) {
'O' => self.cmd("open_previous_file", .{}),
'J' => self.cmd("join_next_line", .{}), 'J' => self.cmd("join_next_line", .{}),
'N' => self.cmd("goto_next_file_or_diagnostic", .{}), 'N' => self.cmd("goto_next_file_or_diagnostic", .{}),
'P' => self.cmd("goto_prev_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" }, .{ "move_word_right", "C-right, A-f" },
.{ "open_command_palette", "C-S-p, S-A-p, A-x" }, .{ "open_command_palette", "C-S-p, S-A-p, A-x" },
.{ "open_file", "C-o" }, .{ "open_file", "C-o" },
.{ "open_previous_file", "A-o" },
.{ "open_recent", "C-e" }, .{ "open_recent", "C-e" },
.{ "open_recent_project", "C-r" }, .{ "open_recent_project", "C-r" },
.{ "paste", "A-v" }, .{ "paste", "A-v" },

View file

@ -105,6 +105,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
}, },
mod.CTRL | mod.SHIFT => switch (keynormal) { mod.CTRL | mod.SHIFT => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}), 'P' => self.cmd("open_command_palette", .{}),
'6' => self.cmd("open_previous_file", .{}),
else => {}, else => {},
}, },
mod.ALT => switch (keynormal) { mod.ALT => switch (keynormal) {
@ -604,6 +605,7 @@ const hints = tui.KeybindHints.initComptime(.{
.{ "move_word_right", "C-right, A-f, e" }, .{ "move_word_right", "C-right, A-f, e" },
.{ "move_word_right_vim", "w" }, .{ "move_word_right_vim", "w" },
.{ "open_command_palette", "Space ?, C-S-p, :, S-;, S-A-p" }, .{ "open_command_palette", "Space ?, C-S-p, :, S-;, S-A-p" },
.{ "open_previous_file", "C-^" },
.{ "open_recent", "C-e" }, .{ "open_recent", "C-e" },
.{ "paste", "A-v, p" }, .{ "paste", "A-v, p" },
.{ "pop_cursor", "C-u" }, .{ "pop_cursor", "C-u" },

View file

@ -105,6 +105,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
}, },
mod.CTRL | mod.SHIFT => switch (keynormal) { mod.CTRL | mod.SHIFT => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}), 'P' => self.cmd("open_command_palette", .{}),
'6' => self.cmd("open_previous_file", .{}),
else => {}, else => {},
}, },
mod.ALT => switch (keynormal) { mod.ALT => switch (keynormal) {
@ -604,6 +605,7 @@ const hints = tui.KeybindHints.initComptime(.{
.{ "move_word_right", "C-right, A-f, e" }, .{ "move_word_right", "C-right, A-f, e" },
.{ "move_word_right_vim", "w" }, .{ "move_word_right_vim", "w" },
.{ "open_command_palette", "Space ?, C-S-p, :, S-;, S-A-p" }, .{ "open_command_palette", "Space ?, C-S-p, :, S-;, S-A-p" },
.{ "open_previous_file", "C-^" },
.{ "open_recent", "C-e" }, .{ "open_recent", "C-e" },
.{ "paste", "A-v, p" }, .{ "paste", "A-v, p" },
.{ "pop_cursor", "C-u" }, .{ "pop_cursor", "C-u" },

View file

@ -138,6 +138,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'F' => self.cmd("find_in_files", .{}), 'F' => self.cmd("find_in_files", .{}),
'L' => self.cmd_async("add_cursor_all_matches"), 'L' => self.cmd_async("add_cursor_all_matches"),
'I' => self.cmd_async("toggle_inspector_view"), 'I' => self.cmd_async("toggle_inspector_view"),
'6' => self.cmd("open_previous_file", .{}),
key.ENTER => self.cmd("smart_insert_line_before", .{}), key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.END => self.cmd("select_buffer_end", .{}), key.END => self.cmd("select_buffer_end", .{}),
key.HOME => self.cmd("select_buffer_begin", .{}), 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", "C-right, A-f, e" },
.{ "move_word_right_vim", "w" }, .{ "move_word_right_vim", "w" },
.{ "open_command_palette", "C-S-p, :, S-;, S-A-p" }, .{ "open_command_palette", "C-S-p, :, S-;, S-A-p" },
.{ "open_previous_file", "C-^" },
.{ "open_recent", "C-e" }, .{ "open_recent", "C-e" },
.{ "paste", "A-v, p" }, .{ "paste", "A-v, p" },
.{ "pop_cursor", "C-u" }, .{ "pop_cursor", "C-u" },

View file

@ -138,6 +138,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'F' => self.cmd("find_in_files", .{}), 'F' => self.cmd("find_in_files", .{}),
'L' => self.cmd_async("add_cursor_all_matches"), 'L' => self.cmd_async("add_cursor_all_matches"),
'I' => self.cmd_async("toggle_inspector_view"), 'I' => self.cmd_async("toggle_inspector_view"),
'6' => self.cmd("open_previous_file", .{}),
key.ENTER => self.cmd("smart_insert_line_before", .{}), key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.END => self.cmd("select_buffer_end", .{}), key.END => self.cmd("select_buffer_end", .{}),
key.HOME => self.cmd("select_buffer_begin", .{}), key.HOME => self.cmd("select_buffer_begin", .{}),
@ -481,6 +482,7 @@ const hints = tui.KeybindHints.initComptime(.{
.{ "find", "C-f, /" }, .{ "find", "C-f, /" },
.{ "goto", "C-g" }, .{ "goto", "C-g" },
.{ "move_to_char", "C-b, C-t" }, // true/false .{ "move_to_char", "C-b, C-t" }, // true/false
.{ "open_previous_file", "C-^" },
.{ "open_file", "C-o" }, .{ "open_file", "C-o" },
.{ "filter", "A-s" }, // self.cmd("filter", command.fmt(.{"sort"})), .{ "filter", "A-s" }, // self.cmd("filter", command.fmt(.{"sort"})),
// .{ "filter", "S-A-s" }, // self.cmd("filter", command.fmt(.{ "sort", "-u" })), // .{ "filter", "S-A-s" }, // self.cmd("filter", command.fmt(.{ "sort", "-u" })),