refactor: add save/restore functionality to open_recent
This commit is contained in:
parent
4c98cf33e3
commit
2f77dbb845
1 changed files with 85 additions and 4 deletions
|
|
@ -40,12 +40,18 @@ buffer_manager: ?*BufferManager,
|
|||
split: enum { none, vertical } = .none,
|
||||
total_items: usize = 0,
|
||||
total_files_in_project: usize = 0,
|
||||
quick_activate_enabled: bool = true,
|
||||
restore_info: std.ArrayList([]const u8) = .empty,
|
||||
|
||||
const inputbox_label = "Search files by name";
|
||||
const MenuType = Menu.Options(*Self).MenuType;
|
||||
const ButtonType = MenuType.ButtonType;
|
||||
|
||||
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);
|
||||
|
|
@ -70,8 +76,15 @@ pub fn create(allocator: std.mem.Allocator) !tui.Mode {
|
|||
};
|
||||
try self.commands.init(self);
|
||||
try tui.message_filters().add(MessageFilter.bind(self, receive_project_manager));
|
||||
self.query_pending = true;
|
||||
try project_manager.request_recent_files(max_recent_files);
|
||||
|
||||
if (ctx.args.buf.len != 0) {
|
||||
try self.restore(ctx);
|
||||
self.quick_activate_enabled = false;
|
||||
} else {
|
||||
self.query_pending = true;
|
||||
try project_manager.request_recent_files(max_recent_files);
|
||||
}
|
||||
|
||||
self.do_resize();
|
||||
try mv.floating_views.add(self.modal.widget());
|
||||
try mv.floating_views.add(self.menu.container_widget);
|
||||
|
|
@ -84,6 +97,8 @@ pub fn create(allocator: std.mem.Allocator) !tui.Mode {
|
|||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
self.save();
|
||||
self.clear_restore_info();
|
||||
self.commands.deinit();
|
||||
tui.message_filters().remove_ptr(self);
|
||||
if (tui.mainview()) |mv| {
|
||||
|
|
@ -94,6 +109,57 @@ pub fn deinit(self: *Self) void {
|
|||
self.allocator.destroy(self);
|
||||
}
|
||||
|
||||
fn clear_restore_info(self: *Self) void {
|
||||
for (self.restore_info.items) |item| self.allocator.free(item);
|
||||
self.restore_info.clearRetainingCapacity();
|
||||
}
|
||||
|
||||
fn save(self: *Self) void {
|
||||
var data: std.Io.Writer.Allocating = .init(self.allocator);
|
||||
defer data.deinit();
|
||||
const writer = &data.writer;
|
||||
|
||||
cbor.writeArrayHeader(writer, 4) catch return;
|
||||
cbor.writeValue(writer, self.inputbox.text.items) catch return;
|
||||
cbor.writeValue(writer, self.longest) catch return;
|
||||
cbor.writeValue(writer, self.menu.selected) catch return;
|
||||
cbor.writeArrayHeader(writer, self.restore_info.items.len) catch return;
|
||||
for (self.restore_info.items) |item| cbor.writeValue(writer, item) catch return;
|
||||
|
||||
tui.set_last_palette(.open_recent, .{ .args = .{ .buf = data.written() } });
|
||||
}
|
||||
|
||||
fn restore(self: *Self, ctx: command.Context) !void {
|
||||
var iter = ctx.args.buf;
|
||||
|
||||
if ((cbor.decodeArrayHeader(&iter) catch 0) != 4) return;
|
||||
|
||||
var input_: []const u8 = undefined;
|
||||
if (!(cbor.matchString(&iter, &input_) catch return)) return;
|
||||
|
||||
self.inputbox.text.shrinkRetainingCapacity(0);
|
||||
try self.inputbox.text.appendSlice(self.inputbox.allocator, input_);
|
||||
self.inputbox.cursor = tui.egc_chunk_width(self.inputbox.text.items, 0, 8);
|
||||
|
||||
if (!(cbor.matchValue(&iter, cbor.extract(&self.longest)) catch return)) return;
|
||||
|
||||
var selected: ?usize = null;
|
||||
if (!(cbor.matchValue(&iter, cbor.extract(&selected)) catch return)) return;
|
||||
|
||||
var len = cbor.decodeArrayHeader(&iter) catch 0;
|
||||
while (len > 0) : (len -= 0) {
|
||||
var item: []const u8 = undefined;
|
||||
if (!(cbor.matchString(&iter, &item) catch break)) break;
|
||||
const data = try self.allocator.dupe(u8, item);
|
||||
errdefer self.allocator.free(data);
|
||||
try self.restore_item(data);
|
||||
}
|
||||
|
||||
self.do_resize();
|
||||
|
||||
if (selected) |*idx| while (idx.* > 0) : (idx.* -= 1) self.menu.select_down();
|
||||
}
|
||||
|
||||
inline fn menu_width(self: *Self) usize {
|
||||
return @max(@min(self.longest + 3, max_menu_width()) + 5, inputbox_label.len + 2);
|
||||
}
|
||||
|
|
@ -129,6 +195,7 @@ fn do_resize(self: *Self) void {
|
|||
}
|
||||
|
||||
fn menu_action_open_file(menu: **MenuType, button: *ButtonType, _: Widget.Pos) void {
|
||||
menu.*.opts.ctx.save();
|
||||
var file_path: []const u8 = undefined;
|
||||
var iter = button.opts.label;
|
||||
if (!(cbor.matchString(&iter, &file_path) catch false)) return;
|
||||
|
|
@ -148,7 +215,6 @@ fn add_item(
|
|||
indicator: []const u8,
|
||||
matches: ?[]const u8,
|
||||
) !void {
|
||||
self.total_items += 1;
|
||||
var label: std.Io.Writer.Allocating = .init(self.allocator);
|
||||
defer label.deinit();
|
||||
const writer = &label.writer;
|
||||
|
|
@ -157,7 +223,18 @@ fn add_item(
|
|||
try cbor.writeValue(writer, file_color);
|
||||
try cbor.writeValue(writer, indicator);
|
||||
if (matches) |cb| _ = try writer.write(cb) else try cbor.writeValue(writer, &[_]usize{});
|
||||
try self.menu.add_item_with_handler(label.written(), menu_action_open_file);
|
||||
const data = try label.toOwnedSlice();
|
||||
errdefer self.allocator.free(data);
|
||||
try self.restore_item(data);
|
||||
}
|
||||
|
||||
fn restore_item(
|
||||
self: *Self,
|
||||
label: []const u8,
|
||||
) error{OutOfMemory}!void {
|
||||
self.total_items += 1;
|
||||
try self.menu.add_item_with_handler(label, menu_action_open_file);
|
||||
(try self.restore_info.addOne(self.allocator)).* = label;
|
||||
}
|
||||
|
||||
fn receive_project_manager(self: *Self, _: tp.pid_ref, m: tp.message) MessageFilter.Error!bool {
|
||||
|
|
@ -253,6 +330,7 @@ fn start_query(self: *Self) MessageFilter.Error!void {
|
|||
self.total_items = 0;
|
||||
if (self.query_pending) return;
|
||||
self.query_pending = true;
|
||||
self.clear_restore_info();
|
||||
try project_manager.query_recent_files(max_recent_files, self.inputbox.text.items);
|
||||
}
|
||||
|
||||
|
|
@ -370,11 +448,14 @@ const cmds = struct {
|
|||
pub const palette_menu_activate_alternate_meta: Meta = .{};
|
||||
|
||||
pub fn palette_menu_activate_quick(self: *Self, _: Ctx) Result {
|
||||
if (!self.quick_activate_enabled) return;
|
||||
if (self.menu.selected orelse 0 > 0) self.menu.activate_selected();
|
||||
self.quick_activate_enabled = false;
|
||||
}
|
||||
pub const palette_menu_activate_quick_meta: Meta = .{};
|
||||
|
||||
pub fn palette_menu_cancel(self: *Self, _: Ctx) Result {
|
||||
self.save();
|
||||
try self.cmd("exit_overlay_mode", .{});
|
||||
}
|
||||
pub const palette_menu_cancel_meta: Meta = .{};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue