From 773104d3434441f0e038260f5ff844b10c845458 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 9 Oct 2023 09:40:28 -0700 Subject: [PATCH 1/3] terminal: scroll down tests --- src/terminal/Terminal.zig | 76 +++++++++++++++++++++++++++++++++++++- website/app/vt/sd/page.mdx | 15 ++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 website/app/vt/sd/page.mdx diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index e47574b19..2930ad367 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -1702,7 +1702,6 @@ pub fn deleteLines(self: *Terminal, count: usize) !void { } /// Scroll the text down by one row. -/// TODO: test pub fn scrollDown(self: *Terminal, count: usize) !void { const tracy = trace(@src()); defer tracy.end(); @@ -5367,3 +5366,78 @@ test "Terminal: cursorRight right of right margin" { try testing.expectEqualStrings(" X", str); } } + +test "Terminal: scrollDown simple" { + const alloc = testing.allocator; + var t = try init(alloc, 5, 5); + defer t.deinit(alloc); + + try t.printString("ABC"); + t.carriageReturn(); + try t.linefeed(); + try t.printString("DEF"); + t.carriageReturn(); + try t.linefeed(); + try t.printString("GHI"); + t.setCursorPos(2, 2); + const cursor = t.screen.cursor; + try t.scrollDown(1); + try testing.expectEqual(cursor, t.screen.cursor); + + { + var str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings("\nABC\nDEF\nGHI", str); + } +} + +test "Terminal: scrollDown outside of scroll region" { + const alloc = testing.allocator; + var t = try init(alloc, 5, 5); + defer t.deinit(alloc); + + try t.printString("ABC"); + t.carriageReturn(); + try t.linefeed(); + try t.printString("DEF"); + t.carriageReturn(); + try t.linefeed(); + try t.printString("GHI"); + t.setScrollingRegion(3, 4); + t.setCursorPos(2, 2); + const cursor = t.screen.cursor; + try t.scrollDown(1); + try testing.expectEqual(cursor, t.screen.cursor); + + { + var str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings("ABC\nDEF\n\nGHI", str); + } +} + +test "Terminal: scrollDown left/right scroll region" { + const alloc = testing.allocator; + var t = try init(alloc, 10, 10); + defer t.deinit(alloc); + + try t.printString("ABC123"); + t.carriageReturn(); + try t.linefeed(); + try t.printString("DEF456"); + t.carriageReturn(); + try t.linefeed(); + try t.printString("GHI789"); + t.scrolling_region.left = 1; + t.scrolling_region.right = 3; + t.setCursorPos(2, 2); + const cursor = t.screen.cursor; + try t.scrollDown(1); + try testing.expectEqual(cursor, t.screen.cursor); + + { + var str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings("A 23\nDBC156\nGEF489\n HI7", str); + } +} diff --git a/website/app/vt/sd/page.mdx b/website/app/vt/sd/page.mdx new file mode 100644 index 000000000..bdd685295 --- /dev/null +++ b/website/app/vt/sd/page.mdx @@ -0,0 +1,15 @@ +import VTSequence from "@/components/VTSequence"; + +# Scroll Down (SD) + + + +Inserts `n` lines at the top of the scroll region and shift existing +lines down. + +This sequence is functionally identical to +[Insert Line (IL)](/vt/il) with the cursor position set to the top of +the scroll region. The cursor position after the operation must be unchanged +from when SD was invoked. + +This sequence unsets the pending wrap state. From ed23f2f1d0c96834cc0e2bf2dd02e92fec86c2d7 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 9 Oct 2023 09:43:28 -0700 Subject: [PATCH 2/3] terminal: implement DECID (ESC Z) --- src/terminal/stream.zig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/terminal/stream.zig b/src/terminal/stream.zig index ecc599a98..cf7f16ab5 100644 --- a/src/terminal/stream.zig +++ b/src/terminal/stream.zig @@ -1102,6 +1102,11 @@ pub fn Stream(comptime Handler: type) type { }, } else log.warn("unimplemented invokeCharset: {}", .{action}), + // DECID + 'Z' => if (@hasDecl(T, "deviceAttributes")) { + try self.handler.deviceAttributes(.primary, &.{}); + } else log.warn("unimplemented ESC callback: {}", .{action}), + // RIS - Full Reset 'c' => if (@hasDecl(T, "fullReset")) switch (action.intermediates.len) { 0 => try self.handler.fullReset(), From fc08f9ab17d99b0ed25a31eba67c3843541672bc Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 9 Oct 2023 10:01:23 -0700 Subject: [PATCH 3/3] terminal: TBC tests --- src/terminal/Terminal.zig | 24 ++++++++++++++++++- website/app/vt/tbc/page.mdx | 47 +++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 website/app/vt/tbc/page.mdx diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index 2930ad367..e845c6e46 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -1452,7 +1452,6 @@ pub fn horizontalTabBack(self: *Terminal) !void { } /// Clear tab stops. -/// TODO: test pub fn tabClear(self: *Terminal, cmd: csi.TabClear) void { switch (cmd) { .current => self.tabstops.unset(self.screen.cursor.x), @@ -5441,3 +5440,26 @@ test "Terminal: scrollDown left/right scroll region" { try testing.expectEqualStrings("A 23\nDBC156\nGEF489\n HI7", str); } } + +test "Terminal: tabClear single" { + const alloc = testing.allocator; + var t = try init(alloc, 30, 5); + defer t.deinit(alloc); + + try t.horizontalTab(); + t.tabClear(.current); + t.setCursorPos(1, 1); + try t.horizontalTab(); + try testing.expectEqual(@as(usize, 16), t.screen.cursor.x); +} + +test "Terminal: tabClear all" { + const alloc = testing.allocator; + var t = try init(alloc, 30, 5); + defer t.deinit(alloc); + + t.tabClear(.all); + t.setCursorPos(1, 1); + try t.horizontalTab(); + try testing.expectEqual(@as(usize, 29), t.screen.cursor.x); +} diff --git a/website/app/vt/tbc/page.mdx b/website/app/vt/tbc/page.mdx new file mode 100644 index 000000000..acb39330b --- /dev/null +++ b/website/app/vt/tbc/page.mdx @@ -0,0 +1,47 @@ +import VTSequence from "@/components/VTSequence"; + +# Tab Clear (TBC) + + + +Clear one or all tab stops. + +The parameter `n` must be `0` or `3`. If `n` is omitted, `n` defaults to `0`. + +If the parameter `n` is `0`, the cursor column position is marked as +not a tab stop. If the column was already not a tab stop, this does nothing. + +If the parameter `n` is `3`, all tab stops are cleared. + +## Validation + +### TBC V-1: Tab Clear Single + +```bash +printf "\033[1;1H" # move to top-left +printf "\033[0J" # clear screen +printf "\033[?W" # reset tabs +printf "\t" +printf "\033[g" +printf "\033[1G" +printf "\t" +``` + +``` +|_______________c_______| +``` + +### TBC V-3: Clear All Tabstops + +```bash +printf "\033[1;1H" # move to top-left +printf "\033[0J" # clear screen +printf "\033[?W" # reset tabs +printf "\033[3g" +printf "\033[1G" +printf "\t" +``` + +``` +|______________________c| +```