diff --git a/src/Window.zig b/src/Window.zig index aaa2c4dce..77f9912f8 100644 --- a/src/Window.zig +++ b/src/Window.zig @@ -674,6 +674,10 @@ pub fn reverseIndex(self: *Window) !void { try self.terminal.reverseIndex(); } +pub fn index(self: *Window) !void { + self.terminal.index(); +} + pub fn setTopAndBottomMargin(self: *Window, top: u16, bot: u16) !void { self.terminal.setScrollingRegion(top, bot); } diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index 1b6e3320b..437554022 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -208,12 +208,14 @@ pub fn decaln(self: *Terminal) void { /// /// This unsets the pending wrap state without wrapping. pub fn index(self: *Terminal) void { - // TODO: outside of scrolling region - // If we're at the end of the screen, scroll up. This is surprisingly // common because most terminals live with a full screen so we do this // check first. if (self.cursor.y == self.rows - 1) { + // Outside of the scroll region we do nothing. + if (self.cursor.y < self.scrolling_region.top or + self.cursor.y > self.scrolling_region.bottom) return; + self.scrollUp(); return; } @@ -1046,6 +1048,35 @@ test "Terminal: index from the bottom" { } } +test "Terminal: index outside of scrolling region" { + const alloc = testing.allocator; + var t = try init(alloc, 2, 5); + defer t.deinit(alloc); + + try testing.expectEqual(@as(usize, 0), t.cursor.y); + t.setScrollingRegion(2, 5); + t.index(); + try testing.expectEqual(@as(usize, 1), t.cursor.y); +} + +test "Terminal: index from the bottom outside of scroll region" { + const alloc = testing.allocator; + var t = try init(alloc, 2, 5); + defer t.deinit(alloc); + + t.setScrollingRegion(1, 2); + t.setCursorPos(5, 1); + try t.print('A'); + t.index(); + try t.print('B'); + + { + var str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings("\n\n\n\nAB", str); + } +} + test "Terminal: DECALN" { const alloc = testing.allocator; var t = try init(alloc, 2, 2); diff --git a/src/terminal/stream.zig b/src/terminal/stream.zig index 71dd08480..46630d69b 100644 --- a/src/terminal/stream.zig +++ b/src/terminal/stream.zig @@ -375,6 +375,15 @@ pub fn Stream(comptime Handler: type) type { log.warn("unimplemented ESC action: {}", .{action}); }, + // IND - Index + 'D' => if (@hasDecl(T, "index")) switch (action.intermediates.len) { + 0 => try self.handler.index(), + else => { + log.warn("invalid index command: {}", .{action}); + return; + }, + } else log.warn("unimplemented ESC callback: {}", .{action}), + // RI - Reverse Index 'M' => if (@hasDecl(T, "reverseIndex")) switch (action.intermediates.len) { 0 => try self.handler.reverseIndex(),