Commit af0e1f3
Eric Bower
·
2026-04-08 23:05:34 -0400 EDT
parent 3971f2d
chore: cleanup util formatting
1 files changed,
+32,
-52
+32,
-52
| ... | ... | @@ -339,11 +339,13 @@ pub fn serializeTerminalState(alloc: std.mem.Allocator, term: *ghostty_vt.Termin | |
| 339 | 339 | sb_bottom.x = @intCast(pages.cols - 1); | |
| 340 | 340 | ||
| 341 | 341 | var scroll_fmt = ghostty_vt.formatter.TerminalFormatter.init(term, .vt); | |
| 342 | - | scroll_fmt.content = .{ .selection = ghostty_vt.Selection.init( | |
| 343 | - | screen_top, | |
| 344 | - | sb_bottom, | |
| 345 | - | false, | |
| 346 | - | ) }; | |
| 342 | + | scroll_fmt.content = .{ | |
| 343 | + | .selection = ghostty_vt.Selection.init( | |
| 344 | + | screen_top, | |
| 345 | + | sb_bottom, | |
| 346 | + | false, | |
| 347 | + | ), | |
| 348 | + | }; | |
| 347 | 349 | scroll_fmt.extra = .none; // no modes, cursor, keyboard — just content | |
| 348 | 350 | scroll_fmt.format(&builder.writer) catch |err| { | |
| 349 | 351 | std.log.warn("failed to format scrollback err={s}", .{@errorName(err)}); |
| ... | ... | @@ -361,17 +363,21 @@ pub fn serializeTerminalState(alloc: std.mem.Allocator, term: *ghostty_vt.Termin | |
| 361 | 363 | ||
| 362 | 364 | // Restrict content to the active viewport only | |
| 363 | 365 | const active_tl = pages.pin(.{ .active = .{ .x = 0, .y = 0 } }); | |
| 364 | - | const active_br = pages.pin(.{ .active = .{ | |
| 365 | - | .x = @intCast(pages.cols - 1), | |
| 366 | - | .y = @intCast(pages.rows - 1), | |
| 367 | - | } }); | |
| 366 | + | const active_br = pages.pin(.{ | |
| 367 | + | .active = .{ | |
| 368 | + | .x = @intCast(pages.cols - 1), | |
| 369 | + | .y = @intCast(pages.rows - 1), | |
| 370 | + | }, | |
| 371 | + | }); | |
| 368 | 372 | ||
| 369 | 373 | if (active_tl != null and active_br != null) { | |
| 370 | - | vis_fmt.content = .{ .selection = ghostty_vt.Selection.init( | |
| 371 | - | active_tl.?, | |
| 372 | - | active_br.?, | |
| 373 | - | false, | |
| 374 | - | ) }; | |
| 374 | + | vis_fmt.content = .{ | |
| 375 | + | .selection = ghostty_vt.Selection.init( | |
| 376 | + | active_tl.?, | |
| 377 | + | active_br.?, | |
| 378 | + | false, | |
| 379 | + | ), | |
| 380 | + | }; | |
| 375 | 381 | } | |
| 376 | 382 | // Fallback: if pins are somehow invalid, use null selection (all content) | |
| 377 | 383 |
| ... | ... | @@ -815,20 +821,6 @@ test "serializeTerminalState excludes synchronized output replay" { | |
| 815 | 821 | try std.testing.expect(std.mem.indexOf(u8, output, "\x1b[?2026h") == null); | |
| 816 | 822 | } | |
| 817 | 823 | ||
| 818 | - | // --------------------------------------------------------------------------- | |
| 819 | - | // Integration tests: serializeTerminalState roundtrip verification | |
| 820 | - | // | |
| 821 | - | // These tests exercise the ghostty-vt roundtrip pattern: | |
| 822 | - | // 1. Create Terminal A, feed VT sequences (scrollback, markers, cursor) | |
| 823 | - | // 2. Serialize A via serializeTerminalState() | |
| 824 | - | // 3. Create Terminal B (same dimensions), feed serialized bytes | |
| 825 | - | // 4. Compare B's screen content and cursor with A's | |
| 826 | - | // | |
| 827 | - | // This verifies that what the user sees after re-attach matches what the | |
| 828 | - | // daemon's terminal state actually contains — including in nested sessions | |
| 829 | - | // (zmx→SSH→zmx) where serialized state flows through multiple layers. | |
| 830 | - | // --------------------------------------------------------------------------- | |
| 831 | - | ||
| 832 | 824 | fn testCreateTerminal(alloc: std.mem.Allocator, cols: u16, rows: u16, vt_data: []const u8) !ghostty_vt.Terminal { | |
| 833 | 825 | var term = try ghostty_vt.Terminal.init(alloc, .{ | |
| 834 | 826 | .cols = cols, |
| ... | ... | @@ -892,8 +884,7 @@ fn expectMarkerAtRow(alloc: std.mem.Allocator, term: *ghostty_vt.Terminal, marke | |
| 892 | 884 | test "serializeTerminalState roundtrip preserves cursor position" { | |
| 893 | 885 | const alloc = std.testing.allocator; | |
| 894 | 886 | ||
| 895 | - | var term = try testCreateTerminal(alloc, 80, 24, | |
| 896 | - | "\x1b[2J" ++ // clear | |
| 887 | + | var term = try testCreateTerminal(alloc, 80, 24, "\x1b[2J" ++ // clear | |
| 897 | 888 | "\x1b[10;20H" // cursor at row 10, col 20 (1-indexed) | |
| 898 | 889 | ); | |
| 899 | 890 | defer term.deinit(alloc); |
| ... | ... | @@ -909,14 +900,12 @@ test "serializeTerminalState roundtrip preserves cursor position" { | |
| 909 | 900 | test "serializeTerminalState roundtrip preserves CUP-positioned markers" { | |
| 910 | 901 | const alloc = std.testing.allocator; | |
| 911 | 902 | ||
| 912 | - | var term = try testCreateTerminal(alloc, 80, 24, | |
| 913 | - | "\x1b[2J" ++ | |
| 903 | + | var term = try testCreateTerminal(alloc, 80, 24, "\x1b[2J" ++ | |
| 914 | 904 | "\x1b[2;5HMARK_A" ++ | |
| 915 | 905 | "\x1b[6;15HMARK_B" ++ | |
| 916 | 906 | "\x1b[10;30HMARK_C" ++ | |
| 917 | 907 | "\x1b[14;50HMARK_D" ++ | |
| 918 | - | "\x1b[16;20H" | |
| 919 | - | ); | |
| 908 | + | "\x1b[16;20H"); | |
| 920 | 909 | defer term.deinit(alloc); | |
| 921 | 910 | ||
| 922 | 911 | var client = try serializeRoundtrip(alloc, &term); |
| ... | ... | @@ -947,13 +936,11 @@ test "serializeTerminalState with scrollback preserves visible content" { | |
| 947 | 936 | } | |
| 948 | 937 | ||
| 949 | 938 | // Clear screen and place markers at specific positions | |
| 950 | - | try stream.nextSlice( | |
| 951 | - | "\x1b[2J" ++ | |
| 939 | + | try stream.nextSlice("\x1b[2J" ++ | |
| 952 | 940 | "\x1b[2;5HMARK_A" ++ | |
| 953 | 941 | "\x1b[6;15HMARK_B" ++ | |
| 954 | 942 | "\x1b[10;30HMARK_C" ++ | |
| 955 | - | "\x1b[16;20H" | |
| 956 | - | ); | |
| 943 | + | "\x1b[16;20H"); | |
| 957 | 944 | ||
| 958 | 945 | // Verify source terminal has scrollback | |
| 959 | 946 | const pages = &term.screens.active.pages; |
| ... | ... | @@ -989,12 +976,10 @@ test "serializeTerminalState nested roundtrip preserves content" { | |
| 989 | 976 | const line = std.fmt.bufPrint(&buf, "SCROLL_{d}\r\n", .{i}) catch unreachable; | |
| 990 | 977 | try inner_stream.nextSlice(line); | |
| 991 | 978 | } | |
| 992 | - | try inner_stream.nextSlice( | |
| 993 | - | "\x1b[2J" ++ | |
| 979 | + | try inner_stream.nextSlice("\x1b[2J" ++ | |
| 994 | 980 | "\x1b[3;10HINNER_A" ++ | |
| 995 | 981 | "\x1b[12;25HINNER_B" ++ | |
| 996 | - | "\x1b[20;5H" | |
| 997 | - | ); | |
| 982 | + | "\x1b[20;5H"); | |
| 998 | 983 | } | |
| 999 | 984 | ||
| 1000 | 985 | // Record inner's ground truth |
| ... | ... | @@ -1030,8 +1015,7 @@ test "serializeTerminalState nested roundtrip preserves content" { | |
| 1030 | 1015 | test "serializeTerminalState alternate screen not leaked" { | |
| 1031 | 1016 | const alloc = std.testing.allocator; | |
| 1032 | 1017 | ||
| 1033 | - | var term = try testCreateTerminal(alloc, 80, 24, | |
| 1034 | - | "\x1b[?1049h" ++ // enter alt screen | |
| 1018 | + | var term = try testCreateTerminal(alloc, 80, 24, "\x1b[?1049h" ++ // enter alt screen | |
| 1035 | 1019 | "\x1b[2J\x1b[3;10HALT_MARK" ++ // write on alt screen | |
| 1036 | 1020 | "\x1b[?1049l" ++ // exit alt screen | |
| 1037 | 1021 | "\x1b[2J\x1b[2;5HMAIN_MARK\x1b[8;20H" // write on main screen |
| ... | ... | @@ -1052,13 +1036,11 @@ test "serializeTerminalState alternate screen not leaked" { | |
| 1052 | 1036 | test "serializeTerminalState size mismatch roundtrip" { | |
| 1053 | 1037 | const alloc = std.testing.allocator; | |
| 1054 | 1038 | ||
| 1055 | - | var term = try testCreateTerminal(alloc, 80, 30, | |
| 1056 | - | "\x1b[2J" ++ | |
| 1039 | + | var term = try testCreateTerminal(alloc, 80, 30, "\x1b[2J" ++ | |
| 1057 | 1040 | "\x1b[3;10HSIZE_A" ++ | |
| 1058 | 1041 | "\x1b[12;20HSIZE_B" ++ | |
| 1059 | 1042 | "\x1b[20;40HSIZE_C" ++ | |
| 1060 | - | "\x1b[15;15H" | |
| 1061 | - | ); | |
| 1043 | + | "\x1b[15;15H"); | |
| 1062 | 1044 | defer term.deinit(alloc); | |
| 1063 | 1045 | ||
| 1064 | 1046 | // Resize to 24 rows (simulates outer terminal being smaller) |
| ... | ... | @@ -1085,12 +1067,10 @@ test "serializeTerminalState scrollback + size mismatch nested roundtrip" { | |
| 1085 | 1067 | const line = std.fmt.bufPrint(&buf, "LINE_{d}\r\n", .{i}) catch unreachable; | |
| 1086 | 1068 | try inner_stream.nextSlice(line); | |
| 1087 | 1069 | } | |
| 1088 | - | try inner_stream.nextSlice( | |
| 1089 | - | "\x1b[2J" ++ | |
| 1070 | + | try inner_stream.nextSlice("\x1b[2J" ++ | |
| 1090 | 1071 | "\x1b[3;10HSTRESS_A" ++ | |
| 1091 | 1072 | "\x1b[12;25HSTRESS_B" ++ | |
| 1092 | - | "\x1b[16;20H" | |
| 1093 | - | ); | |
| 1073 | + | "\x1b[16;20H"); | |
| 1094 | 1074 | } | |
| 1095 | 1075 | ||
| 1096 | 1076 | // Resize inner to 24 rows (outer terminal is smaller) |