terminal: move cursor home after formatting tabstops

Home the cursor after serializing custom tab stops, since formatting VT
expects it to be there for new lines.
This commit is contained in:
Mitchell Hashimoto
2026-08-12 10:26:17 -07:00
parent 1eaf457b18
commit e523cf8104

View File

@@ -460,6 +460,9 @@ pub const TerminalFormatter = struct {
}
}
// Screen contents are formatted relative to the top-left.
try writer.writeAll("\x1b[H");
// If we have a pin_map, add the bytes we wrote to map.
if (self.pin_map) |*m| {
var discarding: std.Io.Writer.Discarding = .init(&.{});
@@ -5617,7 +5620,7 @@ test "Terminal vt with tabstops" {
s.nextSlice("\x1b[5G\x1bH"); // Set tab at column 5
s.nextSlice("\x1b[15G\x1bH"); // Set tab at column 15
s.nextSlice("\x1b[30G\x1bH"); // Set tab at column 30
s.nextSlice("hello");
s.nextSlice("\x1b[Hhello");
var pin_map: PinMap.Map = .empty;
defer pin_map.deinit(alloc);
@@ -5651,6 +5654,14 @@ test "Terminal vt with tabstops" {
try testing.expect(t2.tabstops.get(29)); // Column 30 (1-indexed)
try testing.expect(!t2.tabstops.get(8)); // Not a tab
// Tabstop serialization must not offset the screen contents.
for ("hello", 0..) |expected, col| {
const cell = t2.screens.active.pages.getCell(.{
.screen = .{ .x = @intCast(col), .y = 0 },
}).?;
try testing.expectEqual(expected, cell.cell.codepoint());
}
// Emitting tabstops moves the cursor to each configured column. When
// cursor state is included, it must be restored afterwards.
try testing.expectEqual(t.screens.active.cursor.x, t2.screens.active.cursor.x);