core: scroll to selection working

This commit is contained in:
Mitchell Hashimoto
2024-03-13 13:23:55 -07:00
parent 522c28207e
commit 935063d892
3 changed files with 35 additions and 16 deletions

View File

@ -1358,14 +1358,14 @@ pub fn keyCallback(
if (event.mods.shift) adjust_selection: {
self.renderer_state.mutex.lock();
defer self.renderer_state.mutex.unlock();
var screen = self.io.terminal.screen;
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) {
sel.adjust(screen, switch (event.key) {
.left => .left,
.right => .right,
.up => .up,
@ -1378,20 +1378,24 @@ pub fn keyCallback(
});
// If the selection endpoint is outside of the current viewpoint,
// scroll it in to view.
// TODO(paged-terminal)
// scroll: {
// const viewport_max = terminal.Screen.RowIndexTag.viewport.maxLen(&screen) - 1;
// const viewport_end = screen.viewport + viewport_max;
// const delta: isize = if (sel.end.y < screen.viewport)
// @intCast(screen.viewport)
// else if (sel.end.y > viewport_end)
// @intCast(viewport_end)
// else
// break :scroll;
// const start_y: isize = @intCast(sel.end.y);
// try self.io.terminal.scrollViewport(.{ .delta = start_y - delta });
// }
// 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();

View File

@ -1413,6 +1413,10 @@ pub const Scroll = union(enum) {
/// prompts. If the absolute value is greater than the number of prompts
/// in either direction, jump to the furthest prompt in that direction.
delta_prompt: isize,
/// Scroll directly to a specific pin in the page. This will be set
/// as the top left of the viewport (ignoring the pin x value).
pin: Pin,
};
/// Scroll the viewport. This will never create new scrollback, allocate
@ -1422,6 +1426,15 @@ pub fn scroll(self: *PageList, behavior: Scroll) void {
switch (behavior) {
.active => self.viewport = .{ .active = {} },
.top => self.viewport = .{ .top = {} },
.pin => |p| {
if (self.pinIsActive(p)) {
self.viewport = .{ .active = {} };
return;
}
self.viewport_pin.* = p;
self.viewport = .{ .pin = {} };
},
.delta_prompt => |n| self.scrollPrompt(n),
.delta_row => |n| {
if (n == 0) return;

View File

@ -552,6 +552,7 @@ pub const Scroll = union(enum) {
/// For all of these, see PageList.Scroll.
active,
top,
pin: Pin,
delta_row: isize,
delta_prompt: isize,
};
@ -566,6 +567,7 @@ pub fn scroll(self: *Screen, behavior: Scroll) void {
switch (behavior) {
.active => self.pages.scroll(.{ .active = {} }),
.top => self.pages.scroll(.{ .top = {} }),
.pin => |p| self.pages.scroll(.{ .pin = p }),
.delta_row => |v| self.pages.scroll(.{ .delta_row = v }),
.delta_prompt => |v| self.pages.scroll(.{ .delta_prompt = v }),
}