From cdd1e09069ef7ebfe14a71eeae40ec39d2468008 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Mon, 18 Aug 2025 14:42:34 +0200 Subject: [PATCH 1/3] feat: add support for loading palettes with arguments --- src/tui/mode/overlay/palette.zig | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/tui/mode/overlay/palette.zig b/src/tui/mode/overlay/palette.zig index cfadc52..927e3a0 100644 --- a/src/tui/mode/overlay/palette.zig +++ b/src/tui/mode/overlay/palette.zig @@ -47,6 +47,10 @@ pub fn Create(options: type) type { pub const ButtonState = Button.State(*Menu.State(*Self)); pub fn create(allocator: std.mem.Allocator) !tui.Mode { + return create_with_args(allocator, .{}); + } + + pub fn create_with_args(allocator: std.mem.Allocator, ctx: command.Context) !tui.Mode { const mv = tui.mainview() orelse return error.NotFound; const self = try allocator.create(Self); errdefer allocator.destroy(self); @@ -77,7 +81,10 @@ pub fn Create(options: type) type { .entries = std.ArrayList(Entry).init(allocator), }; if (self.menu.scrollbar) |scrollbar| scrollbar.style_factory = scrollbar_style; - self.longest_hint = try options.load_entries(self); + self.longest_hint = if (@hasDecl(options, "load_entries_with_args")) + try options.load_entries_with_args(self, ctx) + else + try options.load_entries(self); if (@hasDecl(options, "restore_state")) options.restore_state(self) catch {}; try self.commands.init(self); @@ -467,11 +474,15 @@ pub fn Create(options: type) type { const button = self.menu.get_selected() orelse return; const refresh = options.delete_item(self.menu, button); if (refresh) { - options.clear_entries(self); - self.longest_hint = try options.load_entries(self); - if (self.entries.items.len > 0) - self.initial_selected = self.menu.selected; - try self.start_query(0); + if (@hasDecl(options, "load_entries")) { + options.clear_entries(self); + self.longest_hint = try options.load_entries(self); + if (self.entries.items.len > 0) + self.initial_selected = self.menu.selected; + try self.start_query(0); + } else { + return palette_menu_cancel(self, .{}); + } } } } From 7d7a45f539ace91254bf84dd0a37b1bb3b07c5f9 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Mon, 18 Aug 2025 14:46:13 +0200 Subject: [PATCH 2/3] refactor: make project_manager.request_recent_projects fully async --- src/project_manager.zig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/project_manager.zig b/src/project_manager.zig index 925294a..fc73c9e 100644 --- a/src/project_manager.zig +++ b/src/project_manager.zig @@ -98,9 +98,9 @@ pub fn request_recent_files(max: usize) (ProjectManagerError || ProjectError)!vo return send(.{ "request_recent_files", project, max }); } -pub fn request_recent_projects(allocator: std.mem.Allocator) (ProjectError || CallError)!tp.message { +pub fn request_recent_projects() (ProjectManagerError || ProjectError)!void { const project = tp.env.get().str("project"); - return (try get()).pid.call(allocator, request_timeout, .{ "request_recent_projects", project }); + return send(.{ "request_recent_projects", project }); } pub fn query_recent_files(max: usize, query: []const u8) (ProjectManagerError || ProjectError)!void { @@ -462,6 +462,9 @@ const Process = struct { self.sort_projects_by_last_used(&recent_projects); var message = std.ArrayList(u8).init(self.allocator); const writer = message.writer(); + try cbor.writeArrayHeader(writer, 3); + try cbor.writeValue(writer, "PRJ"); + try cbor.writeValue(writer, "recent_projects"); try cbor.writeArrayHeader(writer, recent_projects.items.len); for (recent_projects.items) |project| { try cbor.writeArrayHeader(writer, 2); @@ -469,6 +472,7 @@ const Process = struct { try cbor.writeValue(writer, if (self.projects.get(project.name)) |_| true else false); } from.send_raw(.{ .buf = message.items }) catch return error.ClientFailed; + self.logger.print("{d} projects found", .{recent_projects.items.len}); } fn query_recent_files(self: *Process, from: tp.pid_ref, project_directory: []const u8, max: usize, query: []const u8) (ProjectError || Project.ClientError)!void { From d53a24a1d2338d12914202438312a0be011a74d5 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Mon, 18 Aug 2025 14:47:01 +0200 Subject: [PATCH 3/3] fix: make open_recent_projects run async --- src/tui/mode/overlay/open_recent_project.zig | 10 ++++++---- src/tui/tui.zig | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/tui/mode/overlay/open_recent_project.zig b/src/tui/mode/overlay/open_recent_project.zig index d9fd219..aef1729 100644 --- a/src/tui/mode/overlay/open_recent_project.zig +++ b/src/tui/mode/overlay/open_recent_project.zig @@ -27,10 +27,12 @@ pub fn deinit(palette: *Type) void { palette.allocator.free(entry.label); } -pub fn load_entries(palette: *Type) !usize { - const rsp = try project_manager.request_recent_projects(palette.allocator); - defer palette.allocator.free(rsp.buf); - var iter: []const u8 = rsp.buf; +pub fn load_entries_with_args(palette: *Type, ctx: command.Context) !usize { + var items_cbor: []const u8 = undefined; + if (!(cbor.match(ctx.args.buf, .{ "PRJ", "recent_projects", tp.extract_cbor(&items_cbor) }) catch false)) + return error.InvalidRecentProjects; + + var iter: []const u8 = items_cbor; var len = try cbor.decodeArrayHeader(&iter); while (len > 0) : (len -= 1) { var name_: []const u8 = undefined; diff --git a/src/tui/tui.zig b/src/tui/tui.zig index 7ccdfe4..3bc7c39 100644 --- a/src/tui/tui.zig +++ b/src/tui/tui.zig @@ -413,6 +413,9 @@ fn receive_safe(self: *Self, from: tp.pid_ref, m: tp.message) !void { return; } + if (try m.match(.{ "PRJ", "recent_projects", tp.more })) // async recent projects request + return self.enter_overlay_mode_with_args(@import("mode/overlay/open_recent_project.zig").Type, .{ .args = m }); + if (try m.match(.{ "PRJ", tp.more })) // drop late project manager query responses return; @@ -684,6 +687,17 @@ fn enter_overlay_mode(self: *Self, mode: type) command.Result { refresh_hover(); } +fn enter_overlay_mode_with_args(self: *Self, mode: type, ctx: command.Context) command.Result { + command.executeName("disable_fast_scroll", .{}) catch {}; + command.executeName("disable_jump_mode", .{}) catch {}; + if (self.mini_mode_) |_| try cmds.exit_mini_mode(self, .{}); + if (self.input_mode_outer_) |_| try cmds.exit_overlay_mode(self, .{}); + self.input_mode_outer_ = self.input_mode_; + self.input_mode_ = try mode.create_with_args(self.allocator, ctx); + if (self.input_mode_) |*m| m.run_init(); + refresh_hover(); +} + fn get_input_mode(self: *Self, mode_name: []const u8) !Mode { return keybind.mode(mode_name, self.allocator, .{}); } @@ -914,8 +928,8 @@ const cmds = struct { } pub const open_recent_meta: Meta = .{ .description = "Open recent" }; - pub fn open_recent_project(self: *Self, _: Ctx) Result { - return self.enter_overlay_mode(@import("mode/overlay/open_recent_project.zig").Type); + pub fn open_recent_project(_: *Self, _: Ctx) Result { + try project_manager.request_recent_projects(); } pub const open_recent_project_meta: Meta = .{ .description = "Open project" };