From e4b844dea61d96ee863b0646b9fbe6dfc2783911 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 6 Oct 2023 16:58:48 -0700 Subject: [PATCH] terminal: CHT --- src/terminal/Terminal.zig | 39 ++++++++++++++++- website/app/vt/cbt/page.mdx | 4 +- website/app/vt/cht/page.mdx | 70 +++++++++++++++++++++++++++++++ website/app/vt/tab/page.mdx | 8 ++++ website/components/VTSequence.tsx | 1 + 5 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 website/app/vt/cht/page.mdx create mode 100644 website/app/vt/tab/page.mdx diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index b80556e07f..35e724abaa 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -1497,7 +1497,7 @@ pub fn horizontalTab(self: *Terminal) !void { const tracy = trace(@src()); defer tracy.end(); - while (self.screen.cursor.x < self.cols - 1) { + while (self.screen.cursor.x < self.scrolling_region.right) { // Move the cursor right self.screen.cursor.x += 1; @@ -2294,6 +2294,43 @@ test "Terminal: horizontal tabs" { try testing.expectEqual(@as(usize, 19), t.screen.cursor.x); } +test "Terminal: horizontal tabs starting on tabstop" { + const alloc = testing.allocator; + var t = try init(alloc, 20, 5); + defer t.deinit(alloc); + + t.screen.cursor.x = 8; + try t.print('X'); + t.screen.cursor.x = 8; + try t.horizontalTab(); + try t.print('A'); + + { + var str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings(" X A", str); + } +} + +test "Terminal: horizontal tabs with right margin" { + const alloc = testing.allocator; + var t = try init(alloc, 20, 5); + defer t.deinit(alloc); + + t.scrolling_region.left = 2; + t.scrolling_region.right = 5; + t.screen.cursor.x = 0; + try t.print('X'); + try t.horizontalTab(); + try t.print('A'); + + { + var str = try t.plainString(testing.allocator); + defer testing.allocator.free(str); + try testing.expectEqualStrings("X A", str); + } +} + test "Terminal: horizontal tabs back" { const alloc = testing.allocator; var t = try init(alloc, 20, 5); diff --git a/website/app/vt/cbt/page.mdx b/website/app/vt/cbt/page.mdx index 9c17e3736d..11ed989396 100644 --- a/website/app/vt/cbt/page.mdx +++ b/website/app/vt/cbt/page.mdx @@ -34,11 +34,11 @@ printf "A" |Ac________| ``` -### CBT V-2: Left Beyond First Column +### CBT V-2: Left Starting After Tab Stop ```bash printf "\033[?W" # reset tab stops -printf "\033[1;10" +printf "\033[1;10H" printf "X" printf "\033[Z" printf "A" diff --git a/website/app/vt/cht/page.mdx b/website/app/vt/cht/page.mdx new file mode 100644 index 0000000000..61ca2743f4 --- /dev/null +++ b/website/app/vt/cht/page.mdx @@ -0,0 +1,70 @@ +import VTSequence from "@/components/VTSequence"; + +# Cursor Horizontal Tabulation (CHT) + + + +Move the cursor `n` tabs right. + +The parameter `n` must be an integer greater than or equal to 1. If `n` is less than +or equal to 0, adjust `n` to be 1. If `n` is omitted, `n` defaults to 1. + +The rightmost valid column for this operation is the rightmost column in +the terminal screen or the [right margin](#TODO), whichever is smaller. +This sequence does not change behavior with [origin mode](#TODO) set. + +Move the cursor right until the cursor position is on a tabstop. If the +cursor would move past the rightmost valid column, the cursor remains at +the rightmost valid column and the operation completes. Repeat this process +`n` times. + +Tabstops are dynamic and can be set with escape sequences such as +[horizontal tab set (HTS)](/vt/hts), [tab clear (TBC)](/vt/tbc), etc. +A terminal emulator may default tabstops at any interval, though an interval +of 8 spaces is most common. + +## Validation + +### CHT V-1: Right Beyond Last Column + +```bash +printf "\033[?W" # reset tab stops +printf "\033[100I" # assuming the test terminal has less than 800 columns +printf "A" +``` + +``` +|_________A| +``` + +### CHT V-2: Right From Before a Tabstop + +```bash +printf "\033[?W" # reset tab stops +printf "\033[1;2H" +printf "A" +printf "\033[I" +printf "X" +``` + +``` +|_A_____X__| +``` + +### CHT V-3: Right Margin + +```bash +printf "\033[1;1H" # move to top-left +printf "\033[0J" # clear screen +printf "\033[?W" # reset tab stops +printf "\033[?69h" # enable left/right margins +printf "\033[3;6s" # scroll region left/right +printf "\033[1;1H" # move cursor in region +printf "X" +printf "\033[I" +printf "A" +``` + +``` +|__AX______| +``` diff --git a/website/app/vt/tab/page.mdx b/website/app/vt/tab/page.mdx new file mode 100644 index 0000000000..95b1b3b41c --- /dev/null +++ b/website/app/vt/tab/page.mdx @@ -0,0 +1,8 @@ +import VTSequence from "@/components/VTSequence"; + +# Tab (TAB) + + + +This is an alias for [cursor horizontal tabulation (CHT)](/vt/cht) with +`n = 1`. diff --git a/website/components/VTSequence.tsx b/website/components/VTSequence.tsx index 4717195629..23a69a77aa 100644 --- a/website/components/VTSequence.tsx +++ b/website/components/VTSequence.tsx @@ -45,6 +45,7 @@ function VTElem({ elem }: { elem: string }) { const special: { [key: string]: number } = { BEL: 0x07, BS: 0x08, + TAB: 0x09, LF: 0x0a, CR: 0x0d, ESC: 0x1b,