Merge pull request #643 from mitchellh/sd

xterm audit: SD, TBC, DECID
This commit is contained in:
Mitchell Hashimoto
2023-10-09 10:06:46 -07:00
committed by GitHub
4 changed files with 165 additions and 2 deletions

View File

@ -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),
@ -1702,7 +1701,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 +5365,101 @@ 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);
}
}
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);
}

View File

@ -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(),

View File

@ -0,0 +1,15 @@
import VTSequence from "@/components/VTSequence";
# Scroll Down (SD)
<VTSequence sequence={["CSI", "Pn", "T"]} />
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.

View File

@ -0,0 +1,47 @@
import VTSequence from "@/components/VTSequence";
# Tab Clear (TBC)
<VTSequence sequence={["CSI", "Pn", "g"]} />
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|
```