From 552417091d97d4e8141dee2c056c16916d1a2954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20T=C3=A1mara?= Date: Fri, 3 Oct 2025 00:24:33 -0500 Subject: [PATCH] feat: add helix mode close other buffers and reload all * x and x! have expected behaviour in Helix mode --- src/buffer/Manager.zig | 37 +++++++++++++++++++++++++++++++++++++ src/tui/mode/helix.zig | 35 ++++++++++++++++++++++++++--------- 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/src/buffer/Manager.zig b/src/buffer/Manager.zig index 93b883b..4c4f1e9 100644 --- a/src/buffer/Manager.zig +++ b/src/buffer/Manager.zig @@ -149,6 +149,17 @@ pub fn save_all(self: *const Self) Buffer.StoreToFileError!void { } } +pub fn reload_all(self: *const Self) Buffer.LoadFromFileError!void { + var i = self.buffers.iterator(); + while (i.next()) |kv| { + const buffer = kv.value_ptr.*; + if (buffer.is_ephemeral()) + buffer.mark_clean() + else + try buffer.refresh_from_file(); + } +} + pub fn delete_all(self: *Self) void { var i = self.buffers.iterator(); while (i.next()) |p| { @@ -158,6 +169,32 @@ pub fn delete_all(self: *Self) void { self.buffers.clearRetainingCapacity(); } +pub fn delete_others(self: *Self, protected: *Buffer) void { + var i = self.buffers.iterator(); + while (i.next()) |p| { + const buffer = p.value_ptr.*; + if (buffer != protected) { + buffer.reset_to_last_saved(); + self.close_buffer(buffer); + } + } +} + +pub fn close_others(self: *Self, protected: *Buffer) usize { + var removed: usize = 0; + var i = self.buffers.iterator(); + if (self.is_dirty()) return 0; + while (i.next()) |p| { + const buffer = p.value_ptr.*; + if (buffer != protected) { + if (self.buffers.remove(buffer.get_file_path())) + removed += 1; + buffer.deinit(); + } + } + return removed; +} + pub fn buffer_from_ref(self: *Self, buffer_ref: usize) ?*Buffer { var i = self.buffers.iterator(); while (i.next()) |p| diff --git a/src/tui/mode/helix.zig b/src/tui/mode/helix.zig index d186cf3..810ce15 100644 --- a/src/tui/mode/helix.zig +++ b/src/tui/mode/helix.zig @@ -60,20 +60,16 @@ const cmds_ = struct { } pub const wq_meta: Meta = .{ .description = "wq (write/save file and quit)" }; + pub fn @"x!"(_: *void, _: Ctx) Result { + try cmd("save_file", command.fmt(.{ "then", .{ "quit_without_saving", .{} } })); + } + pub const @"x!_meta": Meta = .{ .description = "x! (write/save file and close forcefully, ignoring other unsaved changes)" }; + pub fn x(_: *void, _: Ctx) Result { try cmd("save_file", command.fmt(.{ "then", .{ "quit", .{} } })); } pub const x_meta: Meta = .{ .description = "x (write/save file and quit)" }; - // This one needs some help, the intention is to close only the current buffer - // , if is the only buffer, exit... - // TODO - // pub fn @"x!"(_: *void, _: Ctx) Result { - // try cmd("save_file", .{}); - // try cmd("close_file_without_saving", .{}); - // } - // pub const @"x!_meta": Meta = .{ .description = "x! (write/save file and close forcefully, ignoring unsaved changes)" }; - pub fn wa(_: *void, _: Ctx) Result { if (tui.get_buffer_manager()) |bm| bm.save_all() catch |e| return tp.exit_error(e, @errorReturnTrace()); @@ -116,6 +112,12 @@ const cmds_ = struct { } pub const rl_meta: Meta = .{ .description = "rl (force reload current file)" }; + pub fn rla(_: *void, _: Ctx) Result { + if (tui.get_buffer_manager()) |bm| + bm.reload_all() catch |e| return tp.exit_error(e, @errorReturnTrace()); + } + pub const rla_meta: Meta = .{ .description = "rla (reload all files discarding the current contents)" }; + pub fn o(_: *void, _: Ctx) Result { try cmd("open_file", .{}); } @@ -152,6 +154,21 @@ const cmds_ = struct { } pub const @"bc!_meta": Meta = .{ .description = "bc! (Close buffer/tab forcefully, ignoring changes)" }; + pub fn @"bco!"(_: *void, _: Ctx) Result { + const mv = tui.mainview() orelse return; + if (tui.get_buffer_manager()) |bm| { + if (mv.get_active_buffer()) |buffer| bm.delete_others(buffer); + } + } + pub const @"bco!_meta": Meta = .{ .description = "bco! (Close other buffers/tabs forcefully, ignoring changes)" }; + + pub fn bco(_: *void, _: Ctx) Result { + const mv = tui.mainview() orelse return; + const bm = tui.get_buffer_manager() orelse return; + if (mv.get_active_buffer()) |buffer| _ = bm.close_others(buffer); + } + pub const bco_meta: Meta = .{ .description = "bco (Close other buffers/tabs, except this one)" }; + pub fn save_selection(_: *void, _: Ctx) Result { const logger = log.logger("helix-mode"); defer logger.deinit();