feat: add support for groups in clipboard history

This introduces the concept of clipboard history groups. A group is created
for each high level clipboard operation. Cut, copy, etc. Single cursor
operations will create a group with just one entry. Multi-cursor operations
on the other hand will create groups with multiple clipboard history entries.
This makes for very powerful clipboard history integration with multi-cursor
support.

This commit also adds the ability to apply integer parmeters to the paste
command to select a clipboard group to paste.

Also, pasting from the system clipboard will detect if the system clipboard is
equivalent to the top most clipboard group, and if so use the group instead.
This allows much better multi-cursor support when using the system copy & paste
commands.
This commit is contained in:
CJ van den Berg 2025-10-31 22:53:14 +01:00
parent 6f57578925
commit 4d375d2d9b
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
5 changed files with 174 additions and 73 deletions

View file

@ -16,6 +16,7 @@ pub const icon = " ";
pub const Entry = struct {
label: []const u8,
idx: usize,
group: usize,
};
pub fn load_entries(palette: *Type) !usize {
@ -24,7 +25,8 @@ pub fn load_entries(palette: *Type) !usize {
if (history.len > 0) {
var idx = history.len - 1;
while (true) : (idx -= 1) {
var label_ = history[idx];
const entry = &history[idx];
var label_ = entry.text;
while (label_.len > 0) switch (label_[0]) {
' ', '\t', '\n' => label_ = label_[1..],
else => break,
@ -32,6 +34,7 @@ pub fn load_entries(palette: *Type) !usize {
(try palette.entries.addOne(palette.allocator)).* = .{
.label = label_,
.idx = idx,
.group = entry.group,
};
if (idx == 0) break;
}
@ -51,7 +54,11 @@ pub fn add_menu_entry(palette: *Type, entry: *Entry, matches: ?[]const usize) !v
var hint: std.Io.Writer.Allocating = .init(palette.allocator);
defer hint.deinit();
const item = if (tui.clipboard_get_history()) |clipboard| clipboard[entry.idx] else &.{};
const clipboard_ = tui.clipboard_get_history();
const clipboard = clipboard_ orelse &.{};
const clipboard_entry: tui.ClipboardEntry = if (clipboard_) |_| clipboard[entry.idx] else .{};
const group_idx = tui.clipboard_current_group() - clipboard_entry.group;
const item = clipboard_entry.text;
var line_count: usize = 1;
for (0..item.len) |i| if (item[i] == '\n') {
line_count += 1;
@ -60,6 +67,7 @@ pub fn add_menu_entry(palette: *Type, entry: *Entry, matches: ?[]const usize) !v
try hint.writer.print(" {d} lines", .{line_count})
else
try hint.writer.print(" {d} {s}", .{ item.len, if (item.len == 1) "byte " else "bytes" });
try hint.writer.print(":{d}", .{group_idx});
try cbor.writeValue(writer, hint.written());
try cbor.writeValue(writer, matches orelse &[_]usize{});