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_down", "move_down"],
|
||||
["home", "smart_move_begin"],
|
||||
["ctrl+k home", "move_begin"],
|
||||
["end", "move_end"],
|
||||
["kp_home", "smart_move_begin"],
|
||||
["ctrl+k kp_home", "move_begin"],
|
||||
["kp_end", "move_end"],
|
||||
["page_up", "move_page_up"],
|
||||
["page_down", "move_page_down"],
|
||||
|
|
|
|||
|
|
@ -2675,6 +2675,7 @@ pub const Editor = struct {
|
|||
var all_stop = true;
|
||||
var root = root_;
|
||||
|
||||
tui.clipboard_start_group();
|
||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
||||
if (cursel.selection) |_| {
|
||||
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 b = self.buf_for_update() catch return;
|
||||
var root = b.root;
|
||||
tui.clipboard_start_group();
|
||||
if (self.cursels.items.len == 1 and primary.selection == null)
|
||||
try self.select_line_at_cursor(root, primary, .include_eol);
|
||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
||||
|
|
@ -2713,15 +2715,14 @@ pub const Editor = struct {
|
|||
var root = b.root;
|
||||
if (self.cursels.items.len == 1 and primary.selection == null)
|
||||
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| {
|
||||
count += 1;
|
||||
const cut_text, root = try self.cut_selection(root, cursel, tui.clipboard_allocator());
|
||||
tui.clipboard_add_chunk(cut_text);
|
||||
};
|
||||
try self.update_buf(root);
|
||||
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" };
|
||||
|
||||
|
|
@ -2735,18 +2736,16 @@ pub const Editor = struct {
|
|||
try move_cursor_end(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| {
|
||||
count += 1;
|
||||
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" };
|
||||
|
||||
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 "*"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
fn copy_cursels_file_name_and_location(self: *const Self) error{OutOfMemory}!usize {
|
||||
var count: usize = 0;
|
||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel| {
|
||||
count += 1;
|
||||
fn copy_cursels_file_name_and_location(self: *const Self) error{OutOfMemory}!void {
|
||||
for (self.cursels.items) |*cursel_| if (cursel_.*) |*cursel|
|
||||
self.copy_cursel_file_name_and_location(cursel) catch return error.OutOfMemory;
|
||||
};
|
||||
return count;
|
||||
}
|
||||
|
||||
pub fn copy_file_name(self: *Self, ctx: Context) Result {
|
||||
var mode: enum { all, file_name_only } = .all;
|
||||
_ = 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(),
|
||||
.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 = .{
|
||||
.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 {
|
||||
const root = self.buf_root() catch return;
|
||||
tui.clipboard_start_group();
|
||||
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));
|
||||
}
|
||||
|
|
@ -2817,49 +2814,69 @@ pub const Editor = struct {
|
|||
try move_cursor_end(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|
|
||||
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 fn paste(self: *Self, ctx: Context) Result {
|
||||
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 u8{text_}
|
||||
var group_idx: usize = 0;
|
||||
var text_: []const u8 = &.{};
|
||||
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
|
||||
tui.clipboard_get_history() orelse return;
|
||||
tui.clipboard_get_group(0);
|
||||
|
||||
const b = try self.buf_for_update();
|
||||
var root = b.root;
|
||||
|
||||
var bytes: usize = 0;
|
||||
var cursel_idx = self.cursels.items.len - 1;
|
||||
var idx = clipboard.len - 1;
|
||||
while (true) {
|
||||
const cursel_ = &self.cursels.items[cursel_idx];
|
||||
if (cursel_.*) |*cursel| {
|
||||
const text = clipboard[idx];
|
||||
root = try self.insert(root, cursel, text, b.allocator);
|
||||
idx = if (idx == 0) clipboard.len - 1 else idx - 1;
|
||||
bytes += text.len;
|
||||
}
|
||||
if (cursel_idx == 0) break;
|
||||
cursel_idx -= 1;
|
||||
|
||||
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 idx = clipboard.len - 1;
|
||||
while (true) {
|
||||
const cursel_ = &self.cursels.items[cursel_idx];
|
||||
if (cursel_.*) |*cursel| {
|
||||
const text = clipboard[idx].text;
|
||||
root = try self.insert(root, cursel, text, b.allocator);
|
||||
idx = if (idx == 0) clipboard.len - 1 else idx - 1;
|
||||
bytes += text.len;
|
||||
}
|
||||
if (cursel_idx == 0) break;
|
||||
cursel_idx -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
self.logger.print("paste: {d} bytes", .{bytes});
|
||||
|
||||
try self.update_buf(root);
|
||||
self.clamp();
|
||||
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 {
|
||||
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 u8{text_}
|
||||
const clipboard: []const tui.ClipboardEntry = if (ctx.args.buf.len > 0 and try ctx.args.match(.{tp.extract(&text_)}))
|
||||
&[_]tui.ClipboardEntry{.{ .text = text_ }}
|
||||
else
|
||||
tui.clipboard_get_history() orelse return;
|
||||
tui.clipboard_get_group(0);
|
||||
|
||||
const b = try self.buf_for_update();
|
||||
var root = b.root;
|
||||
|
|
@ -2870,7 +2887,7 @@ pub const Editor = struct {
|
|||
while (true) {
|
||||
const cursel_ = &self.cursels.items[cursel_idx];
|
||||
if (cursel_.*) |*cursel| {
|
||||
const text = clipboard[idx];
|
||||
const text = clipboard[idx].text;
|
||||
root = try self.insert_line_vim(root, cursel, text, b.allocator);
|
||||
idx = if (idx == 0) clipboard.len - 1 else idx - 1;
|
||||
bytes += text.len;
|
||||
|
|
|
|||
|
|
@ -1409,7 +1409,11 @@ pub fn write_restore_info(self: *Self) void {
|
|||
|
||||
if (tui.clipboard_get_history()) |clipboard| {
|
||||
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 {
|
||||
cbor.writeValue(writer, null) catch return;
|
||||
}
|
||||
|
|
@ -1443,11 +1447,18 @@ fn read_restore_info(self: *Self) !void {
|
|||
|
||||
tui.clipboard_clear_all();
|
||||
var len = try cbor.decodeArrayHeader(&iter);
|
||||
var prev_group: usize = 0;
|
||||
const clipboard_allocator = tui.clipboard_allocator();
|
||||
while (len > 0) : (len -= 1) {
|
||||
var chunk: []const u8 = undefined;
|
||||
if (!try cbor.matchValue(&iter, cbor.extract(&chunk))) return error.Stop;
|
||||
tui.clipboard_add_chunk(try clipboard_allocator.dupe(u8, chunk));
|
||||
const len_ = try cbor.decodeArrayHeader(&iter);
|
||||
if (len_ != 2) return error.Stop;
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -307,7 +307,7 @@ const cmds_ = struct {
|
|||
const mv = tui.mainview() orelse return;
|
||||
const ed = mv.get_active_editor() orelse return;
|
||||
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);
|
||||
try ed.update_buf(root);
|
||||
ed.clamp();
|
||||
|
|
@ -418,7 +418,7 @@ const cmds_ = struct {
|
|||
const ed = mv.get_active_editor() orelse 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|
|
||||
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;
|
||||
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 u8{text_}
|
||||
const clipboard: []const tui.ClipboardEntry = if (ctx.args.buf.len > 0 and try ctx.args.match(.{tp.extract(&text_)}))
|
||||
&[_]tui.ClipboardEntry{.{ .text = text_ }}
|
||||
else
|
||||
tui.clipboard_get_history() orelse return;
|
||||
tui.clipboard_get_group(0);
|
||||
|
||||
const b = try ed.buf_for_update();
|
||||
var root = b.root;
|
||||
|
|
@ -905,11 +905,11 @@ fn paste_helix(ctx: command.Context, do_paste: pasting_function) command.Result
|
|||
var bytes: usize = 0;
|
||||
for (ed.cursels.items, 0..) |*cursel_, idx| if (cursel_.*) |*cursel| {
|
||||
if (idx < clipboard.len) {
|
||||
root = try do_paste(ed, root, cursel, clipboard[idx], b.allocator);
|
||||
bytes += clipboard[idx].len;
|
||||
root = try do_paste(ed, root, cursel, clipboard[idx].text, b.allocator);
|
||||
bytes += clipboard[idx].text.len;
|
||||
} else {
|
||||
bytes += clipboard[clipboard.len - 1].len;
|
||||
root = try do_paste(ed, root, cursel, clipboard[clipboard.len - 1], b.allocator);
|
||||
bytes += clipboard[clipboard.len - 1].text.len;
|
||||
root = try do_paste(ed, root, cursel, clipboard[clipboard.len - 1].text, b.allocator);
|
||||
}
|
||||
};
|
||||
ed.logger.print("paste: {d} bytes", .{bytes});
|
||||
|
|
|
|||
|
|
@ -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{});
|
||||
|
|
|
|||
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,
|
||||
query_cache_: *syntax.QueryCache,
|
||||
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_locked: bool = false,
|
||||
|
||||
pub const ClipboardEntry = struct {
|
||||
text: []const u8 = &.{},
|
||||
group: usize = 0,
|
||||
};
|
||||
|
||||
const keepalive = std.time.us_per_day * 365; // one year
|
||||
const idle_frames = 0;
|
||||
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;
|
||||
if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
|
||||
try self.dispatch_flush_input_event();
|
||||
return if (command.get_id("mini_mode_paste")) |id|
|
||||
command.execute(id, command.fmt(.{text}))
|
||||
else
|
||||
command.executeName("paste", command.fmt(.{text}));
|
||||
return self.handle_system_clipboard(text);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 {
|
||||
const Ctx = struct {
|
||||
widget: ?*Widget = null,
|
||||
|
|
@ -1302,7 +1319,7 @@ const cmds = struct {
|
|||
return error.InvalidClipboardDeleteArgument;
|
||||
const clipboard = if (self.clipboard) |*clipboard| clipboard else return;
|
||||
const removed = clipboard.orderedRemove(idx);
|
||||
self.allocator.free(removed);
|
||||
self.allocator.free(removed.text);
|
||||
}
|
||||
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 {
|
||||
if (self.clipboard) |*clipboard| {
|
||||
for (clipboard.items) |chunk|
|
||||
self.allocator.free(chunk);
|
||||
self.allocator.free(chunk.text);
|
||||
clipboard.deinit(self.allocator);
|
||||
}
|
||||
self.clipboard = null;
|
||||
|
|
@ -1912,7 +1929,7 @@ pub fn clipboard_allocator() Allocator {
|
|||
return self.allocator;
|
||||
}
|
||||
|
||||
pub fn clipboard_get_history() ?[]const []const u8 {
|
||||
pub fn clipboard_get_history() ?[]const ClipboardEntry {
|
||||
const self = current();
|
||||
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 {
|
||||
const self = current();
|
||||
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 {
|
||||
const self = current();
|
||||
self.clipboard_deinit();
|
||||
self.clipboard_current_group_number = 0;
|
||||
}
|
||||
|
||||
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.?;
|
||||
};
|
||||
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 {
|
||||
const self = current();
|
||||
var buffer: std.Io.Writer.Allocating = .init(self.allocator);
|
||||
fn clipboard_system_clipboard_text(allocator: std.mem.Allocator) error{ Stop, WriteFailed, OutOfMemory }![]const u8 {
|
||||
var buffer: std.Io.Writer.Allocating = .init(allocator);
|
||||
defer buffer.deinit();
|
||||
const writer = &buffer.writer;
|
||||
const clipboard = if (self.clipboard) |clipboard| clipboard.items else return error.Stop;
|
||||
if (clipboard.len < n_chunks) return error.Stop;
|
||||
if (n_chunks == 1) return self.clipboard_send_to_system_internal(clipboard[clipboard.len - 1]);
|
||||
const clipboard = clipboard_get_group(0);
|
||||
var first = true;
|
||||
const chunks = clipboard[clipboard.len - n_chunks ..];
|
||||
for (chunks) |chunk| {
|
||||
for (clipboard) |chunk| {
|
||||
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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue