Compare commits
2 commits
63745f1e6b
...
4d375d2d9b
| Author | SHA1 | Date | |
|---|---|---|---|
| 4d375d2d9b | |||
| 6f57578925 |
6 changed files with 176 additions and 73 deletions
|
|
@ -230,8 +230,10 @@
|
||||||
["kp_up", "move_up"],
|
["kp_up", "move_up"],
|
||||||
["kp_down", "move_down"],
|
["kp_down", "move_down"],
|
||||||
["home", "smart_move_begin"],
|
["home", "smart_move_begin"],
|
||||||
|
["ctrl+k home", "move_begin"],
|
||||||
["end", "move_end"],
|
["end", "move_end"],
|
||||||
["kp_home", "smart_move_begin"],
|
["kp_home", "smart_move_begin"],
|
||||||
|
["ctrl+k kp_home", "move_begin"],
|
||||||
["kp_end", "move_end"],
|
["kp_end", "move_end"],
|
||||||
["page_up", "move_page_up"],
|
["page_up", "move_page_up"],
|
||||||
["page_down", "move_page_down"],
|
["page_down", "move_page_down"],
|
||||||
|
|
|
||||||
|
|
@ -2675,6 +2675,7 @@ pub const Editor = struct {
|
||||||
var all_stop = true;
|
var all_stop = true;
|
||||||
var root = root_;
|
var root = root_;
|
||||||
|
|
||||||
|
tui.clipboard_start_group();
|
||||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
||||||
if (cursel.selection) |_| {
|
if (cursel.selection) |_| {
|
||||||
const cut_text, root = self.cut_selection(root, cursel, tui.clipboard_allocator()) catch continue;
|
const cut_text, root = self.cut_selection(root, cursel, tui.clipboard_allocator()) catch continue;
|
||||||
|
|
@ -2696,6 +2697,7 @@ pub const Editor = struct {
|
||||||
const primary = self.get_primary();
|
const primary = self.get_primary();
|
||||||
const b = self.buf_for_update() catch return;
|
const b = self.buf_for_update() catch return;
|
||||||
var root = b.root;
|
var root = b.root;
|
||||||
|
tui.clipboard_start_group();
|
||||||
if (self.cursels.items.len == 1 and primary.selection == null)
|
if (self.cursels.items.len == 1 and primary.selection == null)
|
||||||
try self.select_line_at_cursor(root, primary, .include_eol);
|
try self.select_line_at_cursor(root, primary, .include_eol);
|
||||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
||||||
|
|
@ -2713,15 +2715,14 @@ pub const Editor = struct {
|
||||||
var root = b.root;
|
var root = b.root;
|
||||||
if (self.cursels.items.len == 1 and primary.selection == null)
|
if (self.cursels.items.len == 1 and primary.selection == null)
|
||||||
try self.select_line_at_cursor(root, primary, .include_eol);
|
try self.select_line_at_cursor(root, primary, .include_eol);
|
||||||
var count: usize = 0;
|
tui.clipboard_start_group();
|
||||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
||||||
count += 1;
|
|
||||||
const cut_text, root = try self.cut_selection(root, cursel, tui.clipboard_allocator());
|
const cut_text, root = try self.cut_selection(root, cursel, tui.clipboard_allocator());
|
||||||
tui.clipboard_add_chunk(cut_text);
|
tui.clipboard_add_chunk(cut_text);
|
||||||
};
|
};
|
||||||
try self.update_buf(root);
|
try self.update_buf(root);
|
||||||
self.clamp();
|
self.clamp();
|
||||||
try tui.clipboard_send_to_system(count);
|
try tui.clipboard_send_to_system();
|
||||||
}
|
}
|
||||||
pub const cut_meta: Meta = .{ .description = "Cut selection or current line to clipboard" };
|
pub const cut_meta: Meta = .{ .description = "Cut selection or current line to clipboard" };
|
||||||
|
|
||||||
|
|
@ -2735,18 +2736,16 @@ pub const Editor = struct {
|
||||||
try move_cursor_end(root, &sel.end, self.metrics);
|
try move_cursor_end(root, &sel.end, self.metrics);
|
||||||
try move_cursor_right(root, &sel.end, self.metrics);
|
try move_cursor_right(root, &sel.end, self.metrics);
|
||||||
};
|
};
|
||||||
var count: usize = 0;
|
tui.clipboard_start_group();
|
||||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| if (cursel.selection) |sel| {
|
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| if (cursel.selection) |sel| {
|
||||||
count += 1;
|
|
||||||
tui.clipboard_add_chunk(try copy_selection(root, sel, tui.clipboard_allocator(), self.metrics));
|
tui.clipboard_add_chunk(try copy_selection(root, sel, tui.clipboard_allocator(), self.metrics));
|
||||||
};
|
};
|
||||||
return tui.clipboard_send_to_system(count);
|
return tui.clipboard_send_to_system();
|
||||||
}
|
}
|
||||||
pub const copy_meta: Meta = .{ .description = "Copy selection to clipboard" };
|
pub const copy_meta: Meta = .{ .description = "Copy selection to clipboard" };
|
||||||
|
|
||||||
fn copy_cursel_file_name(self: *const Self) error{OutOfMemory}!usize {
|
fn copy_cursel_file_name(self: *const Self) error{OutOfMemory}!void {
|
||||||
tui.clipboard_add_chunk(try tui.clipboard_allocator().dupe(u8, self.file_path orelse "*"));
|
tui.clipboard_add_chunk(try tui.clipboard_allocator().dupe(u8, self.file_path orelse "*"));
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_cursel_file_name_and_location(self: *const Self, cursel: *const CurSel) error{ WriteFailed, OutOfMemory }!void {
|
fn copy_cursel_file_name_and_location(self: *const Self, cursel: *const CurSel) error{ WriteFailed, OutOfMemory }!void {
|
||||||
|
|
@ -2779,23 +2778,20 @@ pub const Editor = struct {
|
||||||
tui.clipboard_add_chunk(try buffer.toOwnedSlice());
|
tui.clipboard_add_chunk(try buffer.toOwnedSlice());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_cursels_file_name_and_location(self: *const Self) error{OutOfMemory}!usize {
|
fn copy_cursels_file_name_and_location(self: *const Self) error{OutOfMemory}!void {
|
||||||
var count: usize = 0;
|
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel|
|
||||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
|
||||||
count += 1;
|
|
||||||
self.copy_cursel_file_name_and_location(cursel) catch return error.OutOfMemory;
|
self.copy_cursel_file_name_and_location(cursel) catch return error.OutOfMemory;
|
||||||
};
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_file_name(self: *Self, ctx: Context) Result {
|
pub fn copy_file_name(self: *Self, ctx: Context) Result {
|
||||||
var mode: enum { all, file_name_only } = .all;
|
var mode: enum { all, file_name_only } = .all;
|
||||||
_ = ctx.args.match(.{tp.extract(&mode)}) catch false;
|
_ = ctx.args.match(.{tp.extract(&mode)}) catch false;
|
||||||
const n = switch (mode) {
|
tui.clipboard_start_group();
|
||||||
|
switch (mode) {
|
||||||
.file_name_only => try self.copy_cursel_file_name(),
|
.file_name_only => try self.copy_cursel_file_name(),
|
||||||
.all => try self.copy_cursels_file_name_and_location(),
|
.all => try self.copy_cursels_file_name_and_location(),
|
||||||
};
|
}
|
||||||
return tui.clipboard_send_to_system(n);
|
return tui.clipboard_send_to_system();
|
||||||
}
|
}
|
||||||
pub const copy_file_name_meta: Meta = .{
|
pub const copy_file_name_meta: Meta = .{
|
||||||
.description = "Copy file name and location to clipboard",
|
.description = "Copy file name and location to clipboard",
|
||||||
|
|
@ -2803,6 +2799,7 @@ pub const Editor = struct {
|
||||||
|
|
||||||
pub fn copy_internal_vim(self: *Self, _: Context) Result {
|
pub fn copy_internal_vim(self: *Self, _: Context) Result {
|
||||||
const root = self.buf_root() catch return;
|
const root = self.buf_root() catch return;
|
||||||
|
tui.clipboard_start_group();
|
||||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| if (cursel.selection) |sel|
|
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| if (cursel.selection) |sel|
|
||||||
tui.clipboard_add_chunk(try copy_selection(root, sel, tui.clipboard_allocator(), self.metrics));
|
tui.clipboard_add_chunk(try copy_selection(root, sel, tui.clipboard_allocator(), self.metrics));
|
||||||
}
|
}
|
||||||
|
|
@ -2817,28 +2814,46 @@ pub const Editor = struct {
|
||||||
try move_cursor_end(root, &sel.end, self.metrics);
|
try move_cursor_end(root, &sel.end, self.metrics);
|
||||||
try move_cursor_right(root, &sel.end, self.metrics);
|
try move_cursor_right(root, &sel.end, self.metrics);
|
||||||
}
|
}
|
||||||
|
tui.clipboard_start_group();
|
||||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| if (cursel.selection) |sel|
|
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| if (cursel.selection) |sel|
|
||||||
tui.clipboard_add_chunk(try copy_selection(root, sel, tui.clipboard_allocator(), self.metrics));
|
tui.clipboard_add_chunk(try copy_selection(root, sel, tui.clipboard_allocator(), self.metrics));
|
||||||
}
|
}
|
||||||
pub const copy_line_internal_vim_meta: Meta = .{ .description = "Copy line to internal clipboard (vim)" };
|
pub const copy_line_internal_vim_meta: Meta = .{ .description = "Copy line to internal clipboard (vim)" };
|
||||||
|
|
||||||
pub fn paste(self: *Self, ctx: Context) Result {
|
pub fn paste(self: *Self, ctx: Context) Result {
|
||||||
var text_: []const u8 = undefined;
|
var group_idx: usize = 0;
|
||||||
const clipboard: []const []const u8 = if (ctx.args.buf.len > 0 and try ctx.args.match(.{tp.extract(&text_)}))
|
var text_: []const u8 = &.{};
|
||||||
&[_][]const u8{text_}
|
const clipboard: []const tui.ClipboardEntry = if (try ctx.args.match(.{tp.extract(&group_idx)})) blk: {
|
||||||
|
self.logger.print("paste: pasting group {d}", .{group_idx});
|
||||||
|
break :blk tui.clipboard_get_group(group_idx);
|
||||||
|
} else if (try ctx.args.match(.{tp.extract(&text_)}))
|
||||||
|
&[_]tui.ClipboardEntry{.{ .text = text_ }}
|
||||||
else
|
else
|
||||||
tui.clipboard_get_history() orelse return;
|
tui.clipboard_get_group(0);
|
||||||
|
|
||||||
const b = try self.buf_for_update();
|
const b = try self.buf_for_update();
|
||||||
var root = b.root;
|
var root = b.root;
|
||||||
|
|
||||||
var bytes: usize = 0;
|
var bytes: usize = 0;
|
||||||
|
|
||||||
|
if (clipboard.len == 0) {
|
||||||
|
self.logger.print("paste: nothing to paste", .{});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clipboard.len > 1 and self.cursels.items.len == 1) {
|
||||||
|
const cursel = self.get_primary();
|
||||||
|
for (clipboard) |item| {
|
||||||
|
root = try self.insert(root, cursel, item.text, b.allocator);
|
||||||
|
if (item.text[item.text.len - 1] != '\n')
|
||||||
|
root = try self.insert(root, cursel, "\n", b.allocator);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
var cursel_idx = self.cursels.items.len - 1;
|
var cursel_idx = self.cursels.items.len - 1;
|
||||||
var idx = clipboard.len - 1;
|
var idx = clipboard.len - 1;
|
||||||
while (true) {
|
while (true) {
|
||||||
const cursel_ = &self.cursels.items[cursel_idx];
|
const cursel_ = &self.cursels.items[cursel_idx];
|
||||||
if (cursel_.*) |*cursel| {
|
if (cursel_.*) |*cursel| {
|
||||||
const text = clipboard[idx];
|
const text = clipboard[idx].text;
|
||||||
root = try self.insert(root, cursel, text, b.allocator);
|
root = try self.insert(root, cursel, text, b.allocator);
|
||||||
idx = if (idx == 0) clipboard.len - 1 else idx - 1;
|
idx = if (idx == 0) clipboard.len - 1 else idx - 1;
|
||||||
bytes += text.len;
|
bytes += text.len;
|
||||||
|
|
@ -2846,20 +2861,22 @@ pub const Editor = struct {
|
||||||
if (cursel_idx == 0) break;
|
if (cursel_idx == 0) break;
|
||||||
cursel_idx -= 1;
|
cursel_idx -= 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.logger.print("paste: {d} bytes", .{bytes});
|
self.logger.print("paste: {d} bytes", .{bytes});
|
||||||
|
|
||||||
try self.update_buf(root);
|
try self.update_buf(root);
|
||||||
self.clamp();
|
self.clamp();
|
||||||
self.need_render();
|
self.need_render();
|
||||||
}
|
}
|
||||||
pub const paste_meta: Meta = .{ .description = "Paste from internal clipboard" };
|
pub const paste_meta: Meta = .{ .description = "Paste from internal clipboard", .arguments = &.{.integer} };
|
||||||
|
|
||||||
pub fn paste_internal_vim(self: *Self, ctx: Context) Result {
|
pub fn paste_internal_vim(self: *Self, ctx: Context) Result {
|
||||||
var text_: []const u8 = undefined;
|
var text_: []const u8 = undefined;
|
||||||
const clipboard: []const []const u8 = if (ctx.args.buf.len > 0 and try ctx.args.match(.{tp.extract(&text_)}))
|
const clipboard: []const tui.ClipboardEntry = if (ctx.args.buf.len > 0 and try ctx.args.match(.{tp.extract(&text_)}))
|
||||||
&[_][]const u8{text_}
|
&[_]tui.ClipboardEntry{.{ .text = text_ }}
|
||||||
else
|
else
|
||||||
tui.clipboard_get_history() orelse return;
|
tui.clipboard_get_group(0);
|
||||||
|
|
||||||
const b = try self.buf_for_update();
|
const b = try self.buf_for_update();
|
||||||
var root = b.root;
|
var root = b.root;
|
||||||
|
|
@ -2870,7 +2887,7 @@ pub const Editor = struct {
|
||||||
while (true) {
|
while (true) {
|
||||||
const cursel_ = &self.cursels.items[cursel_idx];
|
const cursel_ = &self.cursels.items[cursel_idx];
|
||||||
if (cursel_.*) |*cursel| {
|
if (cursel_.*) |*cursel| {
|
||||||
const text = clipboard[idx];
|
const text = clipboard[idx].text;
|
||||||
root = try self.insert_line_vim(root, cursel, text, b.allocator);
|
root = try self.insert_line_vim(root, cursel, text, b.allocator);
|
||||||
idx = if (idx == 0) clipboard.len - 1 else idx - 1;
|
idx = if (idx == 0) clipboard.len - 1 else idx - 1;
|
||||||
bytes += text.len;
|
bytes += text.len;
|
||||||
|
|
|
||||||
|
|
@ -1409,7 +1409,11 @@ pub fn write_restore_info(self: *Self) void {
|
||||||
|
|
||||||
if (tui.clipboard_get_history()) |clipboard| {
|
if (tui.clipboard_get_history()) |clipboard| {
|
||||||
cbor.writeArrayHeader(writer, clipboard.len) catch return;
|
cbor.writeArrayHeader(writer, clipboard.len) catch return;
|
||||||
for (clipboard) |item| cbor.writeValue(writer, item) catch return;
|
for (clipboard) |item| {
|
||||||
|
cbor.writeArrayHeader(writer, 2) catch return;
|
||||||
|
cbor.writeValue(writer, item.group) catch return;
|
||||||
|
cbor.writeValue(writer, item.text) catch return;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cbor.writeValue(writer, null) catch return;
|
cbor.writeValue(writer, null) catch return;
|
||||||
}
|
}
|
||||||
|
|
@ -1443,11 +1447,18 @@ fn read_restore_info(self: *Self) !void {
|
||||||
|
|
||||||
tui.clipboard_clear_all();
|
tui.clipboard_clear_all();
|
||||||
var len = try cbor.decodeArrayHeader(&iter);
|
var len = try cbor.decodeArrayHeader(&iter);
|
||||||
|
var prev_group: usize = 0;
|
||||||
const clipboard_allocator = tui.clipboard_allocator();
|
const clipboard_allocator = tui.clipboard_allocator();
|
||||||
while (len > 0) : (len -= 1) {
|
while (len > 0) : (len -= 1) {
|
||||||
var chunk: []const u8 = undefined;
|
const len_ = try cbor.decodeArrayHeader(&iter);
|
||||||
if (!try cbor.matchValue(&iter, cbor.extract(&chunk))) return error.Stop;
|
if (len_ != 2) return error.Stop;
|
||||||
tui.clipboard_add_chunk(try clipboard_allocator.dupe(u8, chunk));
|
var group: usize = 0;
|
||||||
|
var text: []const u8 = undefined;
|
||||||
|
if (!try cbor.matchValue(&iter, cbor.extract(&group))) return error.Stop;
|
||||||
|
if (!try cbor.matchValue(&iter, cbor.extract(&text))) return error.Stop;
|
||||||
|
if (prev_group != group) tui.clipboard_start_group();
|
||||||
|
prev_group = group;
|
||||||
|
tui.clipboard_add_chunk(try clipboard_allocator.dupe(u8, text));
|
||||||
}
|
}
|
||||||
|
|
||||||
try self.buffer_manager.extract_state(&iter);
|
try self.buffer_manager.extract_state(&iter);
|
||||||
|
|
|
||||||
|
|
@ -307,7 +307,7 @@ const cmds_ = struct {
|
||||||
const mv = tui.mainview() orelse return;
|
const mv = tui.mainview() orelse return;
|
||||||
const ed = mv.get_active_editor() orelse return;
|
const ed = mv.get_active_editor() orelse return;
|
||||||
const b = try ed.buf_for_update();
|
const b = try ed.buf_for_update();
|
||||||
tui.clipboard_clear_all();
|
tui.clipboard_start_group();
|
||||||
const root = try ed.cut_to(move_noop, b.root);
|
const root = try ed.cut_to(move_noop, b.root);
|
||||||
try ed.update_buf(root);
|
try ed.update_buf(root);
|
||||||
ed.clamp();
|
ed.clamp();
|
||||||
|
|
@ -418,7 +418,7 @@ const cmds_ = struct {
|
||||||
const ed = mv.get_active_editor() orelse return;
|
const ed = mv.get_active_editor() orelse return;
|
||||||
const root = ed.buf_root() catch return;
|
const root = ed.buf_root() catch return;
|
||||||
|
|
||||||
tui.clipboard_clear_all();
|
tui.clipboard_start_group();
|
||||||
|
|
||||||
for (ed.cursels.items) |*cursel_| if (cursel_.*) |*cursel| if (cursel.selection) |sel|
|
for (ed.cursels.items) |*cursel_| if (cursel_.*) |*cursel| if (cursel.selection) |sel|
|
||||||
tui.clipboard_add_chunk(try Editor.copy_selection(root, sel, tui.clipboard_allocator(), ed.metrics));
|
tui.clipboard_add_chunk(try Editor.copy_selection(root, sel, tui.clipboard_allocator(), ed.metrics));
|
||||||
|
|
@ -890,10 +890,10 @@ fn paste_helix(ctx: command.Context, do_paste: pasting_function) command.Result
|
||||||
const ed = mv.get_active_editor() orelse return;
|
const ed = mv.get_active_editor() orelse return;
|
||||||
var text_: []const u8 = undefined;
|
var text_: []const u8 = undefined;
|
||||||
|
|
||||||
const clipboard: []const []const u8 = if (ctx.args.buf.len > 0 and try ctx.args.match(.{tp.extract(&text_)}))
|
const clipboard: []const tui.ClipboardEntry = if (ctx.args.buf.len > 0 and try ctx.args.match(.{tp.extract(&text_)}))
|
||||||
&[_][]const u8{text_}
|
&[_]tui.ClipboardEntry{.{ .text = text_ }}
|
||||||
else
|
else
|
||||||
tui.clipboard_get_history() orelse return;
|
tui.clipboard_get_group(0);
|
||||||
|
|
||||||
const b = try ed.buf_for_update();
|
const b = try ed.buf_for_update();
|
||||||
var root = b.root;
|
var root = b.root;
|
||||||
|
|
@ -905,11 +905,11 @@ fn paste_helix(ctx: command.Context, do_paste: pasting_function) command.Result
|
||||||
var bytes: usize = 0;
|
var bytes: usize = 0;
|
||||||
for (ed.cursels.items, 0..) |*cursel_, idx| if (cursel_.*) |*cursel| {
|
for (ed.cursels.items, 0..) |*cursel_, idx| if (cursel_.*) |*cursel| {
|
||||||
if (idx < clipboard.len) {
|
if (idx < clipboard.len) {
|
||||||
root = try do_paste(ed, root, cursel, clipboard[idx], b.allocator);
|
root = try do_paste(ed, root, cursel, clipboard[idx].text, b.allocator);
|
||||||
bytes += clipboard[idx].len;
|
bytes += clipboard[idx].text.len;
|
||||||
} else {
|
} else {
|
||||||
bytes += clipboard[clipboard.len - 1].len;
|
bytes += clipboard[clipboard.len - 1].text.len;
|
||||||
root = try do_paste(ed, root, cursel, clipboard[clipboard.len - 1], b.allocator);
|
root = try do_paste(ed, root, cursel, clipboard[clipboard.len - 1].text, b.allocator);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ed.logger.print("paste: {d} bytes", .{bytes});
|
ed.logger.print("paste: {d} bytes", .{bytes});
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ pub const icon = " ";
|
||||||
pub const Entry = struct {
|
pub const Entry = struct {
|
||||||
label: []const u8,
|
label: []const u8,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
|
group: usize,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn load_entries(palette: *Type) !usize {
|
pub fn load_entries(palette: *Type) !usize {
|
||||||
|
|
@ -24,7 +25,8 @@ pub fn load_entries(palette: *Type) !usize {
|
||||||
if (history.len > 0) {
|
if (history.len > 0) {
|
||||||
var idx = history.len - 1;
|
var idx = history.len - 1;
|
||||||
while (true) : (idx -= 1) {
|
while (true) : (idx -= 1) {
|
||||||
var label_ = history[idx];
|
const entry = &history[idx];
|
||||||
|
var label_ = entry.text;
|
||||||
while (label_.len > 0) switch (label_[0]) {
|
while (label_.len > 0) switch (label_[0]) {
|
||||||
' ', '\t', '\n' => label_ = label_[1..],
|
' ', '\t', '\n' => label_ = label_[1..],
|
||||||
else => break,
|
else => break,
|
||||||
|
|
@ -32,6 +34,7 @@ pub fn load_entries(palette: *Type) !usize {
|
||||||
(try palette.entries.addOne(palette.allocator)).* = .{
|
(try palette.entries.addOne(palette.allocator)).* = .{
|
||||||
.label = label_,
|
.label = label_,
|
||||||
.idx = idx,
|
.idx = idx,
|
||||||
|
.group = entry.group,
|
||||||
};
|
};
|
||||||
if (idx == 0) break;
|
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);
|
var hint: std.Io.Writer.Allocating = .init(palette.allocator);
|
||||||
defer hint.deinit();
|
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;
|
var line_count: usize = 1;
|
||||||
for (0..item.len) |i| if (item[i] == '\n') {
|
for (0..item.len) |i| if (item[i] == '\n') {
|
||||||
line_count += 1;
|
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})
|
try hint.writer.print(" {d} lines", .{line_count})
|
||||||
else
|
else
|
||||||
try hint.writer.print(" {d} {s}", .{ item.len, if (item.len == 1) "byte " else "bytes" });
|
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, hint.written());
|
||||||
|
|
||||||
try cbor.writeValue(writer, matches orelse &[_]usize{});
|
try cbor.writeValue(writer, matches orelse &[_]usize{});
|
||||||
|
|
|
||||||
103
src/tui/tui.zig
103
src/tui/tui.zig
|
|
@ -76,10 +76,16 @@ fontfaces_: std.ArrayListUnmanaged([]const u8) = .{},
|
||||||
enable_mouse_idle_timer: bool = false,
|
enable_mouse_idle_timer: bool = false,
|
||||||
query_cache_: *syntax.QueryCache,
|
query_cache_: *syntax.QueryCache,
|
||||||
frames_rendered_: usize = 0,
|
frames_rendered_: usize = 0,
|
||||||
clipboard: ?std.ArrayList([]const u8) = null,
|
clipboard: ?std.ArrayList(ClipboardEntry) = null,
|
||||||
|
clipboard_current_group_number: usize = 0,
|
||||||
color_scheme: enum { dark, light } = .dark,
|
color_scheme: enum { dark, light } = .dark,
|
||||||
color_scheme_locked: bool = false,
|
color_scheme_locked: bool = false,
|
||||||
|
|
||||||
|
pub const ClipboardEntry = struct {
|
||||||
|
text: []const u8 = &.{},
|
||||||
|
group: usize = 0,
|
||||||
|
};
|
||||||
|
|
||||||
const keepalive = std.time.us_per_day * 365; // one year
|
const keepalive = std.time.us_per_day * 365; // one year
|
||||||
const idle_frames = 0;
|
const idle_frames = 0;
|
||||||
const mouse_idle_time_milliseconds = 3000;
|
const mouse_idle_time_milliseconds = 3000;
|
||||||
|
|
@ -377,10 +383,7 @@ fn receive_safe(self: *Self, from: tp.pid_ref, m: tp.message) !void {
|
||||||
var text: []const u8 = undefined;
|
var text: []const u8 = undefined;
|
||||||
if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
||||||
try self.dispatch_flush_input_event();
|
try self.dispatch_flush_input_event();
|
||||||
return if (command.get_id("mini_mode_paste")) |id|
|
return self.handle_system_clipboard(text);
|
||||||
command.execute(id, command.fmt(.{text}))
|
|
||||||
else
|
|
||||||
command.executeName("paste", command.fmt(.{text}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (try m.match(.{ "system_clipboard", tp.null_ }))
|
if (try m.match(.{ "system_clipboard", tp.null_ }))
|
||||||
|
|
@ -605,6 +608,20 @@ fn dispatch_event(ctx: *anyopaque, cbor_msg: []const u8) void {
|
||||||
tp.self_pid().send_raw(m) catch |e| self.logger.err("dispatch event", e);
|
tp.self_pid().send_raw(m) catch |e| self.logger.err("dispatch event", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_system_clipboard(self: *Self, text: []const u8) !void {
|
||||||
|
if (command.get_id("mini_mode_paste")) |id|
|
||||||
|
return command.execute(id, command.fmt(.{text}));
|
||||||
|
|
||||||
|
{
|
||||||
|
const text_ = try clipboard_system_clipboard_text(self.allocator);
|
||||||
|
defer self.allocator.free(text_);
|
||||||
|
if (std.mem.eql(u8, text_, text))
|
||||||
|
return command.executeName("paste", command.fmt(.{0}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return command.executeName("paste", command.fmt(.{text}));
|
||||||
|
}
|
||||||
|
|
||||||
fn find_coord_widget(self: *Self, y: usize, x: usize) ?*Widget {
|
fn find_coord_widget(self: *Self, y: usize, x: usize) ?*Widget {
|
||||||
const Ctx = struct {
|
const Ctx = struct {
|
||||||
widget: ?*Widget = null,
|
widget: ?*Widget = null,
|
||||||
|
|
@ -1302,7 +1319,7 @@ const cmds = struct {
|
||||||
return error.InvalidClipboardDeleteArgument;
|
return error.InvalidClipboardDeleteArgument;
|
||||||
const clipboard = if (self.clipboard) |*clipboard| clipboard else return;
|
const clipboard = if (self.clipboard) |*clipboard| clipboard else return;
|
||||||
const removed = clipboard.orderedRemove(idx);
|
const removed = clipboard.orderedRemove(idx);
|
||||||
self.allocator.free(removed);
|
self.allocator.free(removed.text);
|
||||||
}
|
}
|
||||||
pub const clipboard_delete_meta: Meta = .{};
|
pub const clipboard_delete_meta: Meta = .{};
|
||||||
};
|
};
|
||||||
|
|
@ -1901,7 +1918,7 @@ fn widget_type_config_variable(widget_type: WidgetType) *ConfigWidgetStyle {
|
||||||
fn clipboard_deinit(self: *Self) void {
|
fn clipboard_deinit(self: *Self) void {
|
||||||
if (self.clipboard) |*clipboard| {
|
if (self.clipboard) |*clipboard| {
|
||||||
for (clipboard.items) |chunk|
|
for (clipboard.items) |chunk|
|
||||||
self.allocator.free(chunk);
|
self.allocator.free(chunk.text);
|
||||||
clipboard.deinit(self.allocator);
|
clipboard.deinit(self.allocator);
|
||||||
}
|
}
|
||||||
self.clipboard = null;
|
self.clipboard = null;
|
||||||
|
|
@ -1912,7 +1929,7 @@ pub fn clipboard_allocator() Allocator {
|
||||||
return self.allocator;
|
return self.allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clipboard_get_history() ?[]const []const u8 {
|
pub fn clipboard_get_history() ?[]const ClipboardEntry {
|
||||||
const self = current();
|
const self = current();
|
||||||
return if (self.clipboard) |clipboard| clipboard.items else null;
|
return if (self.clipboard) |clipboard| clipboard.items else null;
|
||||||
}
|
}
|
||||||
|
|
@ -1920,12 +1937,55 @@ pub fn clipboard_get_history() ?[]const []const u8 {
|
||||||
pub fn clipboard_peek_chunk() ?[]const u8 {
|
pub fn clipboard_peek_chunk() ?[]const u8 {
|
||||||
const self = current();
|
const self = current();
|
||||||
const clipboard = self.clipboard orelse return null;
|
const clipboard = self.clipboard orelse return null;
|
||||||
return clipboard[clipboard.len - 1];
|
return clipboard[clipboard.len - 1].text;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clipboard_start_group() void {
|
||||||
|
const self = current();
|
||||||
|
self.clipboard_current_group_number += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clipboard_current_group() usize {
|
||||||
|
const self = current();
|
||||||
|
return self.clipboard_current_group_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clipboard_group_size(group: usize) usize {
|
||||||
|
const self = current();
|
||||||
|
const clipboard = self.clipboard orelse return 0;
|
||||||
|
var count: usize = 0;
|
||||||
|
var idx: usize = clipboard.len - 1;
|
||||||
|
while (clipboard[idx].group != group) {
|
||||||
|
if (idx == 0) return 0 else idx -= 1;
|
||||||
|
}
|
||||||
|
while (clipboard[idx].group == group) {
|
||||||
|
count += 1;
|
||||||
|
if (idx == 0) break else idx -= 1;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clipboard_get_group(group_idx: usize) []const ClipboardEntry {
|
||||||
|
const self = current();
|
||||||
|
const clipboard = (self.clipboard orelse return &.{}).items;
|
||||||
|
const group = self.clipboard_current_group_number - group_idx;
|
||||||
|
if (clipboard.len == 0) return &.{};
|
||||||
|
var group_end: usize = clipboard.len;
|
||||||
|
while (clipboard[group_end - 1].group != group) {
|
||||||
|
if (group_end == 1) return &.{} else group_end -= 1;
|
||||||
|
}
|
||||||
|
var group_begin: usize = group_end;
|
||||||
|
while (clipboard[group_begin - 1].group == group) {
|
||||||
|
group_begin -= 1;
|
||||||
|
if (group_begin == 0) break;
|
||||||
|
}
|
||||||
|
return clipboard[group_begin..group_end];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clipboard_clear_all() void {
|
pub fn clipboard_clear_all() void {
|
||||||
const self = current();
|
const self = current();
|
||||||
self.clipboard_deinit();
|
self.clipboard_deinit();
|
||||||
|
self.clipboard_current_group_number = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clipboard_add_chunk(text: []const u8) void {
|
pub fn clipboard_add_chunk(text: []const u8) void {
|
||||||
|
|
@ -1935,23 +1995,28 @@ pub fn clipboard_add_chunk(text: []const u8) void {
|
||||||
break :blk &self.clipboard.?;
|
break :blk &self.clipboard.?;
|
||||||
};
|
};
|
||||||
const chunk = clipboard.addOne(self.allocator) catch @panic("OOM clipboard_add_chunk");
|
const chunk = clipboard.addOne(self.allocator) catch @panic("OOM clipboard_add_chunk");
|
||||||
chunk.* = text;
|
chunk.text = text;
|
||||||
|
chunk.group = self.clipboard_current_group_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clipboard_send_to_system(n_chunks: usize) error{ Stop, WriteFailed }!void {
|
fn clipboard_system_clipboard_text(allocator: std.mem.Allocator) error{ Stop, WriteFailed, OutOfMemory }![]const u8 {
|
||||||
const self = current();
|
var buffer: std.Io.Writer.Allocating = .init(allocator);
|
||||||
var buffer: std.Io.Writer.Allocating = .init(self.allocator);
|
|
||||||
defer buffer.deinit();
|
defer buffer.deinit();
|
||||||
const writer = &buffer.writer;
|
const writer = &buffer.writer;
|
||||||
const clipboard = if (self.clipboard) |clipboard| clipboard.items else return error.Stop;
|
const clipboard = clipboard_get_group(0);
|
||||||
if (clipboard.len < n_chunks) return error.Stop;
|
|
||||||
if (n_chunks == 1) return self.clipboard_send_to_system_internal(clipboard[clipboard.len - 1]);
|
|
||||||
var first = true;
|
var first = true;
|
||||||
const chunks = clipboard[clipboard.len - n_chunks ..];
|
for (clipboard) |chunk| {
|
||||||
for (chunks) |chunk| {
|
|
||||||
if (first) first = false else try writer.writeByte('\n');
|
if (first) first = false else try writer.writeByte('\n');
|
||||||
try writer.writeAll(chunk);
|
try writer.writeAll(chunk.text);
|
||||||
}
|
}
|
||||||
|
return buffer.toOwnedSlice();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clipboard_send_to_system() error{ Stop, WriteFailed, OutOfMemory }!void {
|
||||||
|
const self = current();
|
||||||
|
const text = try clipboard_system_clipboard_text(self.allocator);
|
||||||
|
defer self.allocator.free(text);
|
||||||
|
return self.clipboard_send_to_system_internal(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clipboard_send_to_system_internal(self: *Self, text: []const u8) void {
|
fn clipboard_send_to_system_internal(self: *Self, text: []const u8) void {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue