Compare commits
5 commits
e053a0dcf4
...
752a356d38
| Author | SHA1 | Date | |
|---|---|---|---|
| 752a356d38 | |||
| 6678e0c1e3 | |||
| 2704c7be07 | |||
| 91b54d6842 | |||
| 89e9fd7b83 |
3 changed files with 134 additions and 9 deletions
|
|
@ -36,6 +36,8 @@
|
|||
["ctrl+shift+tab", "previous_tab"],
|
||||
["ctrl+page_down", "next_tab"],
|
||||
["ctrl+page_up", "previous_tab"],
|
||||
["ctrl+shift+page_down", "move_tab_next"],
|
||||
["ctrl+shift+page_up", "move_tab_previous"],
|
||||
["ctrl+shift+e", "switch_buffers"],
|
||||
["alt+shift+v", "clipboard_history"],
|
||||
["ctrl+0", "reset_fontsize"],
|
||||
|
|
|
|||
|
|
@ -638,8 +638,12 @@ const cmds = struct {
|
|||
tui.need_render();
|
||||
}
|
||||
try command.executeName("save_file", .{});
|
||||
if (buffer.is_ephemeral() and !buffer.is_dirty())
|
||||
_ = self.buffer_manager.close_buffer(buffer);
|
||||
try command.executeName("place_next_tab", command.fmt(.{
|
||||
if (buffer.is_ephemeral()) "before" else "after",
|
||||
self.buffer_manager.buffer_to_ref(buffer),
|
||||
}));
|
||||
if (buffer.is_ephemeral())
|
||||
self.buffer_manager.close_buffer(buffer);
|
||||
}
|
||||
}
|
||||
pub const save_file_as_meta: Meta = .{ .arguments = &.{.string} };
|
||||
|
|
@ -1182,6 +1186,38 @@ const cmds = struct {
|
|||
_ = try self.widgets_widget.msg(.{"previous_tab"});
|
||||
}
|
||||
pub const previous_tab_meta: Meta = .{ .description = "Switch to previous tab" };
|
||||
|
||||
pub fn move_tab_next(self: *Self, _: Ctx) Result {
|
||||
_ = try self.widgets_widget.msg(.{"move_tab_next"});
|
||||
}
|
||||
pub const move_tab_next_meta: Meta = .{ .description = "Move tab to next position" };
|
||||
|
||||
pub fn move_tab_previous(self: *Self, _: Ctx) Result {
|
||||
_ = try self.widgets_widget.msg(.{"move_tab_previous"});
|
||||
}
|
||||
pub const move_tab_previous_meta: Meta = .{ .description = "Move tab to previous position" };
|
||||
|
||||
pub fn swap_tabs(self: *Self, ctx: Ctx) Result {
|
||||
var buffer_ref_a: usize = undefined;
|
||||
var buffer_ref_b: usize = undefined;
|
||||
if (!try ctx.args.match(.{
|
||||
tp.extract(&buffer_ref_a),
|
||||
tp.extract(&buffer_ref_b),
|
||||
})) return error.InvalidSwapTabsArgument;
|
||||
_ = try self.widgets_widget.msg(.{ "swap_tabs", buffer_ref_a, buffer_ref_b });
|
||||
}
|
||||
pub const swap_tabs_meta: Meta = .{ .arguments = &.{ .integer, .integer } };
|
||||
|
||||
pub fn place_next_tab(self: *Self, ctx: Ctx) Result {
|
||||
var pos: enum { before, after } = undefined;
|
||||
var buffer_ref: usize = undefined;
|
||||
if (try ctx.args.match(.{ tp.extract(&pos), tp.extract(&buffer_ref) })) {
|
||||
_ = try self.widgets_widget.msg(.{ "place_next_tab", pos, buffer_ref });
|
||||
} else if (try ctx.args.match(.{"atend"})) {
|
||||
_ = try self.widgets_widget.msg(.{ "place_next_tab", "atend" });
|
||||
} else return error.InvalidSwapTabsArgument;
|
||||
}
|
||||
pub const place_next_tab_meta: Meta = .{ .arguments = &.{ .string, .integer } };
|
||||
};
|
||||
|
||||
pub fn handle_editor_event(self: *Self, _: tp.pid_ref, m: tp.message) tp.result {
|
||||
|
|
|
|||
|
|
@ -87,12 +87,19 @@ pub const TabBar = struct {
|
|||
tabs: []TabBarTab = &[_]TabBarTab{},
|
||||
active_buffer_ref: ?usize = null,
|
||||
minimum_tabs_shown: usize,
|
||||
place_next: Placement = .atend,
|
||||
|
||||
tab_style: Style,
|
||||
tab_style_bufs: [][]const u8,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
const Placement = union(enum) {
|
||||
atend,
|
||||
before: usize,
|
||||
after: usize,
|
||||
};
|
||||
|
||||
const TabBarTab = struct {
|
||||
buffer_ref: usize,
|
||||
widget: Widget,
|
||||
|
|
@ -151,10 +158,24 @@ pub const TabBar = struct {
|
|||
pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
|
||||
const buffer_manager = tui.get_buffer_manager() orelse @panic("tabs no buffer manager");
|
||||
var file_path: []const u8 = undefined;
|
||||
var buffer_ref_a: usize = undefined;
|
||||
var buffer_ref_b: usize = undefined;
|
||||
if (try m.match(.{"next_tab"})) {
|
||||
self.select_next_tab();
|
||||
} else if (try m.match(.{"previous_tab"})) {
|
||||
self.select_previous_tab();
|
||||
} else if (try m.match(.{"move_tab_next"})) {
|
||||
self.move_tab_next();
|
||||
} else if (try m.match(.{"move_tab_previous"})) {
|
||||
self.move_tab_previous();
|
||||
} else if (try m.match(.{ "swap_tabs", tp.extract(&buffer_ref_a), tp.extract(&buffer_ref_b) })) {
|
||||
self.swap_tabs(buffer_ref_a, buffer_ref_b);
|
||||
} else if (try m.match(.{ "place_next_tab", "after", tp.extract(&buffer_ref_a) })) {
|
||||
self.place_next_tab(.after, buffer_ref_a);
|
||||
} else if (try m.match(.{ "place_next_tab", "before", tp.extract(&buffer_ref_a) })) {
|
||||
self.place_next_tab(.before, buffer_ref_a);
|
||||
} else if (try m.match(.{ "place_next_tab", "atend" })) {
|
||||
self.place_next = .atend;
|
||||
} else if (try m.match(.{ "E", "open", tp.extract(&file_path), tp.more })) {
|
||||
self.active_buffer_ref = if (buffer_manager.get_buffer_for_file(file_path)) |buffer|
|
||||
buffer_manager.buffer_to_ref(buffer)
|
||||
|
|
@ -227,18 +248,32 @@ pub const TabBar = struct {
|
|||
outer: for (buffers) |buffer| {
|
||||
for (result.items) |result_tab| if (result_tab.buffer_ref == buffer_manager.buffer_to_ref(buffer))
|
||||
continue :outer;
|
||||
if (!buffer.hidden) {
|
||||
const buffer_ref = buffer_manager.buffer_to_ref(buffer);
|
||||
(try result.addOne(self.allocator)).* = .{
|
||||
.buffer_ref = buffer_ref,
|
||||
.widget = try Tab.create(self, buffer_ref, &self.tab_style, self.event_handler),
|
||||
};
|
||||
}
|
||||
if (!buffer.hidden)
|
||||
try self.place_new_tab(&result, buffer);
|
||||
}
|
||||
|
||||
self.tabs = try result.toOwnedSlice(self.allocator);
|
||||
}
|
||||
|
||||
fn place_new_tab(self: *Self, result: *std.ArrayListUnmanaged(TabBarTab), buffer: *Buffer) !void {
|
||||
const buffer_manager = tui.get_buffer_manager() orelse @panic("tabs no buffer manager");
|
||||
const buffer_ref = buffer_manager.buffer_to_ref(buffer);
|
||||
const tab = try Tab.create(self, buffer_ref, &self.tab_style, self.event_handler);
|
||||
const pos = switch (self.place_next) {
|
||||
.atend => try result.addOne(self.allocator),
|
||||
.before => |i| if (i < result.items.len)
|
||||
&(try result.addManyAt(self.allocator, i, 1))[0]
|
||||
else
|
||||
try result.addOne(self.allocator),
|
||||
.after => |i| if (i < result.items.len - 1)
|
||||
&(try result.addManyAt(self.allocator, i + 1, 1))[0]
|
||||
else
|
||||
try result.addOne(self.allocator),
|
||||
};
|
||||
pos.* = .{ .buffer_ref = buffer_ref, .widget = tab };
|
||||
self.place_next = .atend;
|
||||
}
|
||||
|
||||
fn make_spacer(self: @This()) !Widget {
|
||||
return spacer.create(
|
||||
self.allocator,
|
||||
|
|
@ -277,6 +312,58 @@ pub const TabBar = struct {
|
|||
if (goto) |tab| navigate_to_tab(tab);
|
||||
}
|
||||
|
||||
fn move_tab_next(self: *Self) void {
|
||||
tp.trace(tp.channel.debug, .{"move_tab_next"});
|
||||
for (self.tabs, 0..) |*tab, idx| if (tab.buffer_ref == self.active_buffer_ref and idx < self.tabs.len - 1) {
|
||||
const tmp = self.tabs[idx + 1];
|
||||
self.tabs[idx + 1] = self.tabs[idx];
|
||||
self.tabs[idx] = tmp;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
fn move_tab_previous(self: *Self) void {
|
||||
tp.trace(tp.channel.debug, .{"move_tab_previous"});
|
||||
for (self.tabs, 0..) |*tab, idx| if (tab.buffer_ref == self.active_buffer_ref and idx > 0) {
|
||||
const tmp = self.tabs[idx - 1];
|
||||
self.tabs[idx - 1] = self.tabs[idx];
|
||||
self.tabs[idx] = tmp;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
fn swap_tabs(self: *Self, buffer_ref_a: usize, buffer_ref_b: usize) void {
|
||||
tp.trace(tp.channel.debug, .{ "swap_tabs", "buffers", buffer_ref_a, buffer_ref_b });
|
||||
if (buffer_ref_a == buffer_ref_b) {
|
||||
tp.trace(tp.channel.debug, .{ "swap_tabs", "same_buffer" });
|
||||
return;
|
||||
}
|
||||
const tab_a_idx = for (self.tabs, 0..) |*tab, idx| if (tab.buffer_ref == buffer_ref_a) break idx else continue else {
|
||||
tp.trace(tp.channel.debug, .{ "swap_tabs", "not_found", "buffer_ref_a" });
|
||||
return;
|
||||
};
|
||||
const tab_b_idx = for (self.tabs, 0..) |*tab, idx| if (tab.buffer_ref == buffer_ref_b) break idx else continue else {
|
||||
tp.trace(tp.channel.debug, .{ "swap_tabs", "not_found", "buffer_ref_b" });
|
||||
return;
|
||||
};
|
||||
const tmp = self.tabs[tab_a_idx];
|
||||
self.tabs[tab_a_idx] = self.tabs[tab_b_idx];
|
||||
self.tabs[tab_b_idx] = tmp;
|
||||
tp.trace(tp.channel.debug, .{ "swap_tabs", "swapped", "indexes", tab_a_idx, tab_b_idx });
|
||||
}
|
||||
|
||||
fn place_next_tab(self: *Self, position: enum { before, after }, buffer_ref: usize) void {
|
||||
tp.trace(tp.channel.debug, .{ "place_next_tab", position, buffer_ref });
|
||||
const tab_idx = for (self.tabs, 0..) |*tab, idx| if (tab.buffer_ref == buffer_ref) break idx else continue else {
|
||||
tp.trace(tp.channel.debug, .{ "place_next_tab", "not_found", buffer_ref });
|
||||
return;
|
||||
};
|
||||
self.place_next = switch (position) {
|
||||
.before => .{ .before = tab_idx },
|
||||
.after => .{ .after = tab_idx },
|
||||
};
|
||||
}
|
||||
|
||||
fn navigate_to_tab(tab: *const TabBarTab) void {
|
||||
const buffer_manager = tui.get_buffer_manager() orelse @panic("tabs no buffer manager");
|
||||
if (buffer_manager.buffer_from_ref(tab.buffer_ref)) |buffer|
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue