feat: keybinds for text selection on copy mode

This commit is contained in:
Cameron Dart
2024-06-14 14:00:19 -07:00
committed by Mitchell Hashimoto
parent 1eb18895bf
commit cdeeeb9f88
3 changed files with 92 additions and 48 deletions

View File

@ -1364,54 +1364,6 @@ pub fn keyCallback(
}
}
// Expand selection if one exists and event is shift + <arrows, home, end, pg up/down>
if (event.mods.shift) adjust_selection: {
self.renderer_state.mutex.lock();
defer self.renderer_state.mutex.unlock();
var screen = &self.io.terminal.screen;
const sel = if (screen.selection) |*sel| sel else break :adjust_selection;
// Silently consume key releases. We only want to process selection
// adjust on press.
if (event.action != .press and event.action != .repeat) return .consumed;
sel.adjust(screen, switch (event.key) {
.left => .left,
.right => .right,
.up => .up,
.down => .down,
.page_up => .page_up,
.page_down => .page_down,
.home => .home,
.end => .end,
else => break :adjust_selection,
});
// If the selection endpoint is outside of the current viewpoint,
// scroll it in to view. Note we always specifically use sel.end
// because that is what adjust modifies.
scroll: {
const viewport_tl = screen.pages.getTopLeft(.viewport);
const viewport_br = screen.pages.getBottomRight(.viewport).?;
if (sel.end().isBetween(viewport_tl, viewport_br))
break :scroll;
// Our end point is not within the viewport. If the end
// point is after the br then we need to adjust the end so
// that it is at the bottom right of the viewport.
const target = if (sel.end().before(viewport_tl))
sel.end()
else
sel.end().up(screen.pages.rows - 1) orelse sel.end();
screen.scroll(.{ .pin = target });
}
// Queue a render so its shown
try self.queueRender();
return .consumed;
}
// If we allow KAM and KAM is enabled then we do nothing.
if (self.config.vt_kam_allowed) {
self.renderer_state.mutex.lock();
@ -3535,6 +3487,47 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
},
.quit => try self.app.setQuit(),
.selection_navigation_left, .selection_navigation_right, .selection_navigation_up, .selection_navigation_down => {
alter_navigation: {
self.renderer_state.mutex.lock();
defer self.renderer_state.mutex.unlock();
var screen = &self.io.terminal.screen;
const sel = if (screen.selection) |*sel| sel else break :alter_navigation;
sel.adjust(screen, switch (action) {
.selection_navigation_left => .left,
.selection_navigation_right => .right,
.selection_navigation_up => .up,
.selection_navigation_down => .down,
.selection_navigation_page_up => .page_up,
.selection_navigation_page_down => .page_down,
.selection_natigation_home => .home,
.selection_natigation_end => .end,
else => break :alter_navigation,
});
// If the selection endpoint is outside of the current viewpoint,
// scroll it in to view. Note we always specifically use sel.end
// because that is what adjust modifies.
scroll: {
const viewport_tl = screen.pages.getTopLeft(.viewport);
const viewport_br = screen.pages.getBottomRight(.viewport).?;
if (sel.end().isBetween(viewport_tl, viewport_br))
break :scroll;
// Our end point is not within the viewport. If the end
// point is after the br then we need to adjust the end so
// that it is at the bottom right of the viewport.
const target = if (sel.end().before(viewport_tl))
sel.end()
else
sel.end().up(screen.pages.rows - 1) orelse sel.end();
screen.scroll(.{ .pin = target });
}
}
// Queue a render so its shown
try self.queueRender();
},
}
return true;

View File

@ -1494,6 +1494,48 @@ pub fn default(alloc_gpa: Allocator) Allocator.Error!Config {
.{ .key = .{ .translated = .insert }, .mods = .{ .shift = true } },
.{ .paste_from_selection = {} },
);
// Selection Navigation
try result.keybind.set.put(
alloc,
.{ .key = .{ .translated = .left }, .mods = .{ .shift = true } },
.{ .selection_navigation_left = {} },
);
try result.keybind.set.put(
alloc,
.{ .key = .{ .translated = .right }, .mods = .{ .shift = true } },
.{ .selection_navigation_right = {} },
);
try result.keybind.set.put(
alloc,
.{ .key = .{ .translated = .up }, .mods = .{ .shift = true } },
.{ .selection_navigation_up = {} },
);
try result.keybind.set.put(
alloc,
.{ .key = .{ .translated = .down }, .mods = .{ .shift = true } },
.{ .selection_navigation_down = {} },
);
try result.keybind.set.put(
alloc,
.{ .key = .{ .translated = .page_up }, .mods = .{ .shift = true } },
.{ .selection_navigation_page_up = {} },
);
try result.keybind.set.put(
alloc,
.{ .key = .{ .translated = .page_down }, .mods = .{ .shift = true } },
.{ .selection_navigation_page_down = {} },
);
try result.keybind.set.put(
alloc,
.{ .key = .{ .translated = .home }, .mods = .{ .shift = true } },
.{ .selection_navigation_home = {} },
);
try result.keybind.set.put(
alloc,
.{ .key = .{ .translated = .end }, .mods = .{ .shift = true } },
.{ .selection_navigation_end = {} },
);
}
{
// Cmd+N for goto tab N

View File

@ -169,6 +169,15 @@ pub const Action = union(enum) {
/// enter after to get a new prompt.
reset: void,
selection_navigation_left: void,
selection_navigation_right: void,
selection_navigation_up: void,
selection_navigation_down: void,
selection_navigation_page_up: void,
selection_navigation_page_down: void,
selection_natigation_home: void,
selection_natigation_end: void,
/// Copy and paste.
copy_to_clipboard: void,
paste_from_clipboard: void,