diff --git a/src/benchmark/ScrollbackCompression.zig b/src/benchmark/ScrollbackCompression.zig index 3968427b4..d971c551d 100644 --- a/src/benchmark/ScrollbackCompression.zig +++ b/src/benchmark/ScrollbackCompression.zig @@ -138,7 +138,7 @@ pub fn create( .terminal = try .init(global.io(), alloc, .{ .rows = opts.@"terminal-rows", .cols = opts.@"terminal-cols", - .max_scrollback = opts.@"max-scrollback", + .max_scrollback_bytes = opts.@"max-scrollback", }), }; return ptr; diff --git a/src/terminal/Screen.zig b/src/terminal/Screen.zig index f3989ee16..e954178ca 100644 --- a/src/terminal/Screen.zig +++ b/src/terminal/Screen.zig @@ -253,9 +253,14 @@ pub const Options = struct { cols: size.CellCountInt, rows: size.CellCountInt, - /// The maximum size of scrollback in bytes. Zero means unlimited. Any + /// The maximum size of scrollback in bytes. Zero disables scrollback. Any /// other value will be clamped to support a minimum of the active area. - max_scrollback: usize = 0, + max_scrollback_bytes: usize = 0, + + /// The maximum number of physical scrollback rows, excluding the active + /// area. Null is unlimited. The effective limit permits at least one + /// standard page and only complete historical pages are pruned. + max_scrollback_lines: ?usize = null, /// The total storage limit for Kitty images in bytes for this /// screen. Kitty image storage is per-screen. @@ -276,13 +281,13 @@ pub const Options = struct { pub const default: Options = .{ .cols = 80, .rows = 24, - .max_scrollback = 0, + .max_scrollback_bytes = 0, }; }; /// Initialize a new screen. /// -/// max_scrollback is the amount of scrollback to keep in bytes. This +/// max_scrollback_bytes is the amount of scrollback to keep in bytes. This /// will be rounded UP to the nearest page size because our minimum allocation /// size is that anyways. /// @@ -296,7 +301,8 @@ pub fn init( var pages = try PageList.init(alloc, .{ .cols = opts.cols, .rows = opts.rows, - .max_size = opts.max_scrollback, + .max_size = opts.max_scrollback_bytes, + .max_lines = opts.max_scrollback_lines, }); errdefer pages.deinit(); @@ -309,7 +315,7 @@ pub fn init( .io = io, .alloc = alloc, .pages = pages, - .no_scrollback = opts.max_scrollback == 0, + .no_scrollback = opts.max_scrollback_bytes == 0, .cursor = .{ .x = 0, .y = 0, @@ -3776,12 +3782,26 @@ pub fn testWriteString(self: *Screen, text: []const u8) !void { } } +test "Screen forwards max scrollback lines" { + const testing = std.testing; + const max_lines: usize = 123; + var s = try init(testing.io, testing.allocator, .{ + .cols = 80, + .rows = 24, + .max_scrollback_bytes = 10_000, + .max_scrollback_lines = max_lines, + }); + defer s.deinit(); + + try testing.expectEqual(max_lines, s.pages.explicit_max_lines); +} + test "Screen read and write" { const testing = std.testing; const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); try testing.expectEqual(@as(style.Id, 0), s.cursor.style_id); @@ -3796,7 +3816,7 @@ test "Screen read and write newline" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); try testing.expectEqual(@as(style.Id, 0), s.cursor.style_id); @@ -3811,7 +3831,7 @@ test "Screen read and write scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 2, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 2, .max_scrollback_bytes = 1000 }); defer s.deinit(); try s.testWriteString("hello\nworld\ntest"); @@ -3832,7 +3852,7 @@ test "Screen read and write no scrollback small" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 2, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 2, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("hello\nworld\ntest"); @@ -3853,7 +3873,7 @@ test "Screen read and write no scrollback large" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 2, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 2, .max_scrollback_bytes = 0 }); defer s.deinit(); for (0..1_000) |i| { @@ -3875,13 +3895,13 @@ test "Screen cursorCopy x/y" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); s.cursorAbsolute(2, 3); try testing.expect(s.cursor.x == 2); try testing.expect(s.cursor.y == 3); - var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s2.deinit(); try s2.cursorCopy(s.cursor, .{}); try testing.expect(s2.cursor.x == 2); @@ -3900,10 +3920,10 @@ test "Screen cursorCopy style deref" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); - var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s2.deinit(); const page = s2.cursor.page_pin.node.page(); @@ -3923,10 +3943,10 @@ test "Screen cursorCopy style deref new page" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); - var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 2048 }); + var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 2048 }); defer s2.deinit(); // We need to get the cursor on a new page. @@ -3997,11 +4017,11 @@ test "Screen cursorCopy style copy" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.setAttribute(.{ .bold = {} }); - var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s2.deinit(); const page = s2.cursor.page_pin.node.page(); try s2.cursorCopy(s.cursor, .{}); @@ -4014,10 +4034,10 @@ test "Screen cursorCopy hyperlink deref" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); - var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s2.deinit(); const page = s2.cursor.page_pin.node.page(); @@ -4040,7 +4060,7 @@ test "Screen write regrows compacted page capacity" { var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, - .max_scrollback = 0, + .max_scrollback_bytes = 0, }); defer s.deinit(); @@ -4086,10 +4106,10 @@ test "Screen cursorCopy hyperlink deref new page" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); - var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 2048 }); + var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 2048 }); defer s2.deinit(); // We need to get the cursor on a new page. @@ -4160,7 +4180,7 @@ test "Screen cursorCopy hyperlink copy" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); // Create a hyperlink for the cursor. @@ -4168,7 +4188,7 @@ test "Screen cursorCopy hyperlink copy" { try testing.expectEqual(@as(usize, 1), s.cursor.page_pin.node.page().hyperlink_set.count()); try testing.expect(s.cursor.hyperlink_id != 0); - var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s2.deinit(); const page = s2.cursor.page_pin.node.page(); @@ -4186,7 +4206,7 @@ test "Screen cursorCopy hyperlink copy disabled" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); // Create a hyperlink for the cursor. @@ -4194,7 +4214,7 @@ test "Screen cursorCopy hyperlink copy disabled" { try testing.expectEqual(@as(usize, 1), s.cursor.page_pin.node.page().hyperlink_set.count()); try testing.expect(s.cursor.hyperlink_id != 0); - var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s2 = try Screen.init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s2.deinit(); const page = s2.cursor.page_pin.node.page(); @@ -4212,7 +4232,7 @@ test "Screen style basics" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); const page = s.cursor.page_pin.node.page(); try testing.expectEqual(@as(usize, 0), page.styles.count()); @@ -4235,7 +4255,7 @@ test "Screen style reset to default" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); const page = s.cursor.page_pin.node.page(); try testing.expectEqual(@as(usize, 0), page.styles.count()); @@ -4256,7 +4276,7 @@ test "Screen style reset with unset" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); const page = s.cursor.page_pin.node.page(); try testing.expectEqual(@as(usize, 0), page.styles.count()); @@ -4277,7 +4297,7 @@ test "Screen clearRows active one line" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); try s.testWriteString("hello, world"); @@ -4293,7 +4313,7 @@ test "Screen clearRows active multi line" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); try s.testWriteString("hello\nworld"); @@ -4310,7 +4330,7 @@ test "Screen clearRows active styled line" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); try s.setAttribute(.{ .bold = {} }); @@ -4349,7 +4369,7 @@ test "Screen clearRows uses stored page width" { var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 2, .rows = 1, - .max_scrollback = 0, + .max_scrollback_bytes = 0, }); defer s.deinit(); @@ -4368,7 +4388,7 @@ test "Screen clearRows protected" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); try s.testWriteString("UNPROTECTED"); @@ -4397,7 +4417,7 @@ test "Screen eraseRows history" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 1000 }); defer s.deinit(); try s.testWriteString("1\n2\n3\n4\n5\n6"); @@ -4432,7 +4452,7 @@ test "Screen eraseRows history with more lines" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 1000 }); defer s.deinit(); try s.testWriteString("A\nB\nC\n1\n2\n3\n4\n5\n6"); @@ -4467,7 +4487,7 @@ test "Screen eraseRows active partial" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("1\n2\n3"); @@ -4497,7 +4517,7 @@ test "Screen: cursorCellEndOfPrev across mixed-width pages" { var s = try init(testing.io, testing.allocator, .{ .cols = 4, .rows = 2, - .max_scrollback = 0, + .max_scrollback_bytes = 0, }); defer s.deinit(); @@ -4518,7 +4538,7 @@ test "Screen: cursorDown across pages preserves style" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); // Scroll down enough to go to another page @@ -4571,7 +4591,7 @@ test "Screen: cursorUp across pages preserves style" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); // Scroll down enough to go to another page @@ -4619,7 +4639,7 @@ test "Screen: cursorAbsolute across pages preserves style" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); // Scroll down enough to go to another page @@ -4675,7 +4695,7 @@ test "Screen: cursorAbsolute to page with insufficient capacity" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); // Scroll down enough to go to another page @@ -4743,7 +4763,7 @@ test "Screen: scrolling" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.setAttribute(.{ .direct_color_bg = .{ .r = 155 } }); try s.testWriteString("1ABCD\n2EFGH\n3IJKL"); @@ -4786,7 +4806,7 @@ test "Screen: scrolling with a single-row screen no scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 1, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 1, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("1ABCD"); @@ -4807,7 +4827,7 @@ test "Screen: scrolling with a single-row screen with scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 1, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 1, .max_scrollback_bytes = 1 }); defer s.deinit(); try s.testWriteString("1ABCD"); @@ -4838,7 +4858,7 @@ test "Screen: scrolling across pages preserves style" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); try s.setAttribute(.{ .bold = {} }); try s.testWriteString("1ABCD\n2EFGH\n3IJKL"); @@ -4868,7 +4888,7 @@ test "Screen: scroll down from 0" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL"); @@ -4888,7 +4908,7 @@ test "Screen: scrollback various cases" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL"); try s.cursorDownScroll(); @@ -4970,7 +4990,7 @@ test "Screen: scrollback with multi-row delta" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 3 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 3 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL\n4ABCD\n5EFGH\n6IJKL"); @@ -4997,7 +5017,7 @@ test "Screen: scrollback empty" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 50 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 50 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL"); s.scroll(.{ .delta_row = 1 }); @@ -5013,7 +5033,7 @@ test "Screen: scrollback doesn't move viewport if not at bottom" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 3 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 3 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL\n4ABCD\n5EFGH"); @@ -5049,7 +5069,7 @@ test "Screen: scrolling moves selection" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL"); @@ -5129,7 +5149,7 @@ test "Screen: cursorScrollRegionUp simple" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL\n4MNOP\n5QRST"); @@ -5157,7 +5177,7 @@ test "Screen: cursorScrollRegionUp renews page generation" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL\n4MNOP\n5QRST"); s.cursorAbsolute(0, 2); @@ -5174,7 +5194,7 @@ test "Screen: cursorScrollRegionUp moves selection" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL\n4MNOP\n5QRST"); @@ -5213,7 +5233,7 @@ test "Screen: cursorScrollRegionUp region spans pages" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback = 10 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 10 }); defer s.deinit(); // We need to get the cursor to a new page @@ -5278,7 +5298,7 @@ test "Screen: cursorScrollRegionUp region spans pages with background SGR" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback = 10 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 10 }); defer s.deinit(); // We need to get the cursor to a new page. See the previous test @@ -5322,7 +5342,7 @@ test "Screen: cursorScrollRegionUp with styled erased row" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); // Write a styled row at the top so the erased row has managed @@ -5352,7 +5372,7 @@ test "Screen: scrolling moves viewport" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL\n"); try s.testWriteString("1ABCD\n2EFGH\n3IJKL"); @@ -5378,7 +5398,7 @@ test "Screen: scrolling when viewport is pruned" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 215, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 215, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); // Write some to create scrollback and move back into our scrollback. @@ -5405,7 +5425,7 @@ test "Screen: scroll and clear full screen" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 5 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL"); @@ -5433,7 +5453,7 @@ test "Screen: scroll and clear partial screen" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 5 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH"); @@ -5461,7 +5481,7 @@ test "Screen: scroll and clear empty screen" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 5 }); defer s.deinit(); try s.scrollClear(); { @@ -5481,7 +5501,7 @@ test "Screen: scroll and clear ignore blank lines" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 10 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 10 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH"); try s.scrollClear(); @@ -5525,7 +5545,7 @@ test "Screen: scroll above same page" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 10 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 10 }); defer s.deinit(); try s.setAttribute(.{ .direct_color_bg = .{ .r = 155 } }); try s.testWriteString("1ABCD\n2EFGH\n3IJKL"); @@ -5588,7 +5608,7 @@ test "Screen: scroll above same page but cursor on previous page" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback = 10 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 10 }); defer s.deinit(); // We need to get the cursor to a new page @@ -5676,7 +5696,7 @@ test "Screen: scroll above same page but cursor on previous page last row" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback = 10 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 10 }); defer s.deinit(); // We need to get the cursor to a new page @@ -5767,7 +5787,7 @@ test "Screen: scroll above creates new page" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 10 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 10 }); defer s.deinit(); // We need to get the cursor to a new page @@ -5843,7 +5863,7 @@ test "Screen: scroll above with cursor on non-final row" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 4, .max_scrollback = 10 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 4, .max_scrollback_bytes = 10 }); defer s.deinit(); // Get the cursor to be 2 rows above a new page @@ -5921,7 +5941,7 @@ test "Screen: scroll above no scrollback bottom of page" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const first_page_size = s.pages.pages.first.?.capacity().rows; @@ -5995,7 +6015,7 @@ test "Screen: scroll above hyperlink-dense row to fresh page" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback = 10000 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 10000 }); defer s.deinit(); // Fill the first page so it is exactly full and the cursor is on @@ -6084,7 +6104,7 @@ test "Screen: scroll above hyperlink-dense row to existing page" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback = 10000 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 10000 }); defer s.deinit(); // Fill the first page so it is exactly full and the cursor is on @@ -6150,7 +6170,7 @@ test "Screen: clone" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 10 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 10 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH"); { @@ -6193,7 +6213,7 @@ test "Screen: clone partial" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 10 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 10 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH"); { @@ -6223,7 +6243,7 @@ test "Screen: clone partial cursor out of bounds" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 10 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 10 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH"); { @@ -6258,7 +6278,7 @@ test "Screen: clone contains full selection" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL"); @@ -6297,7 +6317,7 @@ test "Screen: clone contains none of selection" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL"); @@ -6326,7 +6346,7 @@ test "Screen: clone contains selection start cutoff" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL"); @@ -6365,7 +6385,7 @@ test "Screen: clone contains selection end cutoff" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL"); @@ -6404,7 +6424,7 @@ test "Screen: clone contains selection end cutoff reversed" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL"); @@ -6443,7 +6463,7 @@ test "Screen: clone contains subset of selection" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 4, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 4, .max_scrollback_bytes = 1 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL\n4ABCD"); @@ -6482,7 +6502,7 @@ test "Screen: clone clamps clipped selections to mixed-width pages" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 4, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 4, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const first = s.pages.pages.first.?; @@ -6530,7 +6550,7 @@ test "Screen: clone contains subset of rectangle selection" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 4, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 4, .max_scrollback_bytes = 1 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL\n4ABCD"); @@ -6571,7 +6591,7 @@ test "Screen: clone basic" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL"); @@ -6611,7 +6631,7 @@ test "Screen: clone empty viewport" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); { @@ -6635,7 +6655,7 @@ test "Screen: clone one line viewport" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("1ABC"); @@ -6660,7 +6680,7 @@ test "Screen: clone empty active" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); { @@ -6684,7 +6704,7 @@ test "Screen: clone one line active with extra space" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("1ABC"); @@ -6709,7 +6729,7 @@ test "Screen: clear history with no history" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 3 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 3 }); defer s.deinit(); try s.testWriteString("4ABCD\n5EFGH\n6IJKL"); try testing.expect(s.pages.viewport == .active); @@ -6734,7 +6754,7 @@ test "Screen: clear history" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 3 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 3 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL\n4ABCD\n5EFGH\n6IJKL"); try testing.expect(s.pages.viewport == .active); @@ -6769,7 +6789,7 @@ test "Screen: clear above cursor" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 3 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 3 }); defer s.deinit(); try s.testWriteString("4ABCD\n5EFGH\n6IJKL"); s.clearRows( @@ -6797,7 +6817,7 @@ test "Screen: clear above cursor with history" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 3 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 3 }); defer s.deinit(); try s.testWriteString("1ABCD\n2EFGH\n3IJKL\n"); try s.testWriteString("4ABCD\n5EFGH\n6IJKL"); @@ -6826,7 +6846,7 @@ test "Screen: resize (no reflow) more rows" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL"; try s.testWriteString(str); @@ -6845,7 +6865,7 @@ test "Screen: resize (no reflow) less rows" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL"; try s.testWriteString(str); @@ -6869,7 +6889,7 @@ test "Screen: resize (no reflow) less rows trims blank lines" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD"; try s.testWriteString(str); @@ -6905,7 +6925,7 @@ test "Screen: resize (no reflow) more rows trims blank lines" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD"; try s.testWriteString(str); @@ -6941,7 +6961,7 @@ test "Screen: resize (no reflow) more cols" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL"; try s.testWriteString(str); @@ -6959,7 +6979,7 @@ test "Screen: resize (no reflow) less cols" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL"; try s.testWriteString(str); @@ -6978,7 +6998,7 @@ test "Screen: resize (no reflow) more rows with scrollback cursor end" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 7, .rows = 3, .max_scrollback = 2 }); + var s = try init(io, alloc, .{ .cols = 7, .rows = 3, .max_scrollback_bytes = 2 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL\n4ABCD\n5EFGH"; try s.testWriteString(str); @@ -6996,7 +7016,7 @@ test "Screen: resize (no reflow) less rows with scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 7, .rows = 3, .max_scrollback = 2 }); + var s = try init(io, alloc, .{ .cols = 7, .rows = 3, .max_scrollback_bytes = 2 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL\n4ABCD\n5EFGH"; try s.testWriteString(str); @@ -7016,7 +7036,7 @@ test "Screen: resize (no reflow) less rows with empty trailing" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 5 }); defer s.deinit(); const str = "1\n2\n3\n4\n5\n6\n7\n8"; try s.testWriteString(str); @@ -7041,7 +7061,7 @@ test "Screen: resize (no reflow) more rows with soft wrapping" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 2, .rows = 3, .max_scrollback = 3 }); + var s = try init(io, alloc, .{ .cols = 2, .rows = 3, .max_scrollback_bytes = 3 }); defer s.deinit(); const str = "1A2B\n3C4E\n5F6G"; try s.testWriteString(str); @@ -7083,7 +7103,7 @@ test "Screen: resize more rows no scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL"; try s.testWriteString(str); @@ -7111,7 +7131,7 @@ test "Screen: resize more rows with empty scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 10 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 10 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL"; try s.testWriteString(str); @@ -7139,7 +7159,7 @@ test "Screen: resize more rows with populated scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 5 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL\n4ABCD\n5EFGH"; try s.testWriteString(str); @@ -7185,7 +7205,7 @@ test "Screen: resize more cols no reflow" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL"; try s.testWriteString(str); @@ -7215,7 +7235,7 @@ test "Screen: resize more cols perfect split" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD2EFGH3IJKL"; try s.testWriteString(str); @@ -7234,7 +7254,7 @@ test "Screen: resize (no reflow) more cols with scrollback scrolled up" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 5 }); defer s.deinit(); const str = "1\n2\n3\n4\n5\n6\n7\n8"; try s.testWriteString(str); @@ -7268,7 +7288,7 @@ test "Screen: resize (no reflow) less cols with scrollback scrolled up" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 5 }); defer s.deinit(); const str = "1\n2\n3\n4\n5\n6\n7\n8"; try s.testWriteString(str); @@ -7313,7 +7333,7 @@ test "Screen: resize more cols no reflow preserves semantic prompt" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); // Set one of the rows to be a prompt @@ -7358,7 +7378,7 @@ test "Screen: resize more cols with reflow that fits full width" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD2EFGH\n3IJKL"; try s.testWriteString(str); @@ -7399,7 +7419,7 @@ test "Screen: resize more cols with reflow that ends in newline" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 6, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 6, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD2EFGH\n3IJKL"; try s.testWriteString(str); @@ -7445,7 +7465,7 @@ test "Screen: resize more cols with reflow that forces more wrapping" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD2EFGH\n3IJKL"; try s.testWriteString(str); @@ -7487,7 +7507,7 @@ test "Screen: resize more cols with reflow that unwraps multiple times" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD2EFGH3IJKL"; try s.testWriteString(str); @@ -7529,7 +7549,7 @@ test "Screen: resize more cols with populated scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 5 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL\n4ABCD5EFGH"; try s.testWriteString(str); @@ -7582,7 +7602,7 @@ test "Screen: resize more cols bounded scrollback keeps viewport valid" { var s = try init(io, alloc, .{ .cols = 2, .rows = 10, - .max_scrollback = 10_000, + .max_scrollback_bytes = 10_000, }); defer s.deinit(); @@ -7655,7 +7675,7 @@ test "Screen: resize more cols with reflow" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 2, .rows = 3, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 2, .rows = 3, .max_scrollback_bytes = 5 }); defer s.deinit(); const str = "1ABC\n2DEF\n3ABC\n4DEF"; try s.testWriteString(str); @@ -7704,7 +7724,7 @@ test "Screen: resize errors preserve state" { var s = try init(io, alloc, .{ .cols = 10, .rows = 3, - .max_scrollback = 0, + .max_scrollback_bytes = 0, }); defer s.deinit(); @@ -7786,7 +7806,7 @@ test "Screen: resize cursor references when node survives" { var s = try init(io, alloc, .{ .cols = 5, .rows = 3, - .max_scrollback = 1000, + .max_scrollback_bytes = 1000, }); defer s.deinit(); @@ -7836,7 +7856,7 @@ test "Screen: resize cursor references when node is replaced" { var s = try init(io, alloc, .{ .cols = 5, .rows = 3, - .max_scrollback = 1000, + .max_scrollback_bytes = 1000, }); defer s.deinit(); @@ -7885,7 +7905,7 @@ test "Screen: resize more rows and cols with wrapping" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 2, .rows = 4, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 2, .rows = 4, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1A2B\n3C4D"; try s.testWriteString(str); @@ -7919,7 +7939,7 @@ test "Screen: resize less rows no scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL"; try s.testWriteString(str); @@ -7951,7 +7971,7 @@ test "Screen: resize less rows moving cursor" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL"; try s.testWriteString(str); @@ -7992,7 +8012,7 @@ test "Screen: resize less rows with empty scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 10 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 10 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL"; try s.testWriteString(str); @@ -8016,7 +8036,7 @@ test "Screen: resize less rows with populated scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 5 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL\n4ABCD\n5EFGH"; try s.testWriteString(str); @@ -8048,7 +8068,7 @@ test "Screen: resize less rows with full scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 3 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 3 }); defer s.deinit(); const str = "00000\n1ABCD\n2EFGH\n3IJKL\n4ABCD\n5EFGH"; try s.testWriteString(str); @@ -8089,7 +8109,7 @@ test "Screen: resize less cols no reflow" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1AB\n2EF\n3IJ"; try s.testWriteString(str); @@ -8119,7 +8139,7 @@ test "Screen: resize less cols with reflow but row space" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); const str = "1ABCD"; try s.testWriteString(str); @@ -8158,7 +8178,7 @@ test "Screen: resize less cols with reflow with trimmed rows" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "3IJKL\n4ABCD\n5EFGH"; try s.testWriteString(str); @@ -8183,7 +8203,7 @@ test "Screen: resize less cols with reflow with trimmed rows and scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); const str = "3IJKL\n4ABCD\n5EFGH"; try s.testWriteString(str); @@ -8208,7 +8228,7 @@ test "Screen: resize less cols with reflow previously wrapped" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "3IJKL4ABCD5EFGH"; try s.testWriteString(str); @@ -8242,7 +8262,7 @@ test "Screen: resize less cols with reflow and scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 5 }); defer s.deinit(); const str = "1A\n2B\n3C\n4D\n5E"; try s.testWriteString(str); @@ -8276,7 +8296,7 @@ test "Screen: resize less cols with reflow previously wrapped and scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 2 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 2 }); defer s.deinit(); const str = "1ABCD2EFGH3IJKL4ABCD5EFGH"; try s.testWriteString(str); @@ -8331,7 +8351,7 @@ test "Screen: resize less cols with scrollback keeps cursor row" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 5 }); defer s.deinit(); const str = "1A\n2B\n3C\n4D\n5E"; try s.testWriteString(str); @@ -8361,7 +8381,7 @@ test "Screen: resize more rows, less cols with reflow with scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 3 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 3 }); defer s.deinit(); const str = "1ABCD\n2EFGH3IJKL\n4MNOP"; try s.testWriteString(str); @@ -8403,7 +8423,7 @@ test "Screen: resize more rows then shrink again" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 10 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 10 }); defer s.deinit(); const str = "1ABC"; try s.testWriteString(str); @@ -8453,7 +8473,7 @@ test "Screen: resize less cols to eliminate wide char" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 2, .rows = 1, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 2, .rows = 1, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "😀"; try s.testWriteString(str); @@ -8489,7 +8509,7 @@ test "Screen: resize less cols to wrap wide char" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 3, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 3, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "x😀"; try s.testWriteString(str); @@ -8529,7 +8549,7 @@ test "Screen: resize less cols to eliminate wide char with row space" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 2, .rows = 2, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 2, .rows = 2, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "😀"; try s.testWriteString(str); @@ -8562,7 +8582,7 @@ test "Screen: resize less cols reflows cursor after wrapped text" { const testing = std.testing; const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 50, .rows = 7, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 50, .rows = 7, .max_scrollback_bytes = 0 }); defer s.deinit(); for (0..30) |_| try s.testWriteString("a"); @@ -8580,7 +8600,7 @@ test "Screen: resize less cols reflows cursor after empty cells" { const testing = std.testing; const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("abc"); @@ -8600,7 +8620,7 @@ test "Screen: resize more cols with wide spacer head" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 3, .rows = 2, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 3, .rows = 2, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = " 😀"; try s.testWriteString(str); @@ -8654,7 +8674,7 @@ test "Screen: resize more cols with wide spacer head multiple lines" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 3, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 3, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "xxxyy😀"; try s.testWriteString(str); @@ -8706,7 +8726,7 @@ test "Screen: resize more cols requiring a wide spacer head" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 2, .rows = 2, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 2, .rows = 2, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "xx😀"; try s.testWriteString(str); @@ -8758,7 +8778,7 @@ test "Screen: resize more cols with cursor at prompt" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 5 }); defer s.deinit(); // zig fmt: off @@ -8799,7 +8819,7 @@ test "Screen: resize more cols with cursor not at prompt" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 5 }); defer s.deinit(); // zig fmt: off @@ -8841,7 +8861,7 @@ test "Screen: resize with prompt_redraw last clears only one line" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 4, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 4, .max_scrollback_bytes = 5 }); defer s.deinit(); // zig fmt: off @@ -8881,7 +8901,7 @@ test "Screen: resize with prompt_redraw last multiline prompt clears only last l const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 5 }); defer s.deinit(); // Create a 3-line prompt: 1 initial + 2 continuation lines @@ -8922,7 +8942,7 @@ test "Screen: select untracked" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("ABC DEF\n 123\n456"); @@ -8943,7 +8963,7 @@ test "Screen: select replaces existing pins" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("ABC DEF\n 123\n456"); @@ -8970,7 +8990,7 @@ test "Screen: reselecting tracked selection preserves its pins" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 2, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 2, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.select(Selection.init( @@ -8988,7 +9008,7 @@ test "Screen: selectAll" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); { @@ -9025,7 +9045,7 @@ test "Screen: selectLine" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("ABC DEF\n 123\n456"); @@ -9107,7 +9127,7 @@ test "Screen: selectLine across soft-wrap" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString(" 12 34012 \n 123"); @@ -9134,7 +9154,7 @@ test "Screen: selectLine across full soft-wrap" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("1ABCD2EFGH\n3IJKL"); @@ -9160,7 +9180,7 @@ test "Screen: selectLine across soft-wrap ignores blank lines" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString(" 12 34012 \n 123"); @@ -9221,7 +9241,7 @@ test "Screen: selectLine disabled whitespace trimming" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString(" 12 34012 \n 123"); @@ -9271,7 +9291,7 @@ test "Screen: selectLine with scrollback" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 2, .rows = 3, .max_scrollback = 5 }); + var s = try init(io, alloc, .{ .cols = 2, .rows = 3, .max_scrollback_bytes = 5 }); defer s.deinit(); try s.testWriteString("1A\n2B\n3C\n4D\n5E"); @@ -9316,7 +9336,7 @@ test "Screen: selectLine semantic prompt boundary" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("ABCDE\n"); s.cursorSetSemanticContent(.{ .prompt = .initial }); @@ -9367,7 +9387,7 @@ test "Screen: selectLine semantic prompt to input boundary" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Write prompt followed by user input on same row: "$>command" @@ -9417,7 +9437,7 @@ test "Screen: selectLine semantic input to output boundary" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Row 0: user input @@ -9463,7 +9483,7 @@ test "Screen: selectLine semantic mid-row boundary" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Single row with output then prompt then input: "out$>cmd" @@ -9532,7 +9552,7 @@ test "Screen: selectLine semantic boundary soft-wrap with mid-row transition" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Row 0: prompt "$ " + input "cmd" (soft-wraps) @@ -9602,7 +9622,7 @@ test "Screen: selectLine semantic boundary disabled" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Write prompt followed by input @@ -9635,7 +9655,7 @@ test "Screen: selectLine semantic boundary first cell of row" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Row 0: input that soft-wraps @@ -9692,7 +9712,7 @@ test "Screen: selectLine semantic boundary across mixed-width pages" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 4, .rows = 2, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 4, .rows = 2, .max_scrollback_bytes = 0 }); defer s.deinit(); s.cursorSetSemanticContent(.{ .input = .clear_explicit }); @@ -9724,7 +9744,7 @@ test "Screen: selectLine semantic all same content" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // All prompt content that soft-wraps @@ -9759,7 +9779,7 @@ test "Screen: selectWord" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("ABC DEF\n 123\n456"); @@ -9884,7 +9904,7 @@ test "Screen: selectWord across soft-wrap" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString(" 1234012\n 123"); @@ -9960,7 +9980,7 @@ test "Screen: selectWord whitespace across soft-wrap" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("1 1\n 123"); @@ -10060,7 +10080,7 @@ test "Screen: selectWord with character boundary" { }; for (cases) |case| { - var s = try init(io, alloc, .{ .cols = 20, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString(case); @@ -10141,7 +10161,7 @@ test "Screen: selectOutput" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 15, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 15, .max_scrollback_bytes = 0 }); defer s.deinit(); // Build content with cell-level semantic content: @@ -10238,7 +10258,7 @@ test "Screen: selectionString basic" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL"; try s.testWriteString(str); @@ -10264,7 +10284,7 @@ test "Screen: selectionString start outside of written area" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL"; try s.testWriteString(str); @@ -10290,7 +10310,7 @@ test "Screen: selectionString end outside of written area" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD\n2EFGH\n3IJKL"; try s.testWriteString(str); @@ -10316,7 +10336,7 @@ test "Screen: selectionString trim space" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1AB \n2EFGH\n3IJKL"; try s.testWriteString(str); @@ -10354,7 +10374,7 @@ test "Screen: selectionString trim empty line" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1AB \n\n2EFGH\n3IJKL"; try s.testWriteString(str); @@ -10392,7 +10412,7 @@ test "Screen: selectionString soft wrap" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD2EFGH3IJKL"; try s.testWriteString(str); @@ -10418,7 +10438,7 @@ test "Screen: selectionString wide char" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1A⚡"; try s.testWriteString(str); @@ -10474,7 +10494,7 @@ test "Screen: selectionString wide char with header" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABC⚡"; try s.testWriteString(str); @@ -10501,7 +10521,7 @@ test "Screen: selectionString empty with soft wrap" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 2, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 2, .max_scrollback_bytes = 0 }); defer s.deinit(); // Let me describe the situation that caused this because this @@ -10535,7 +10555,7 @@ test "Screen: selectionString with zero width joiner" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 1, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 1, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "👨‍"; // this has a ZWJ try s.testWriteString(str); @@ -10572,7 +10592,7 @@ test "Screen: selectionString, rectangle, basic" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 30, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 30, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = \\Lorem ipsum dolor @@ -10606,7 +10626,7 @@ test "Screen: selectionString, rectangle, w/EOL" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 30, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 30, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = \\Lorem ipsum dolor @@ -10642,7 +10662,7 @@ test "Screen: selectionString, rectangle, more complex w/breaks" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 30, .rows = 8, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 30, .rows = 8, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = \\Lorem ipsum dolor @@ -10682,7 +10702,7 @@ test "Screen: selectionString multi-page" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 2048 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 2048 }); defer s.deinit(); const first_page_size = s.pages.pages.first.?.capacity().rows; @@ -10717,7 +10737,7 @@ test "Screen: lineIterator" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD\n2EFGH"; try s.testWriteString(str); @@ -10749,7 +10769,7 @@ test "Screen: lineIterator soft wrap" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD2EFGH\n3ABCD"; try s.testWriteString(str); @@ -10782,7 +10802,7 @@ test "Screen: hyperlink start/end" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); try testing.expect(s.cursor.hyperlink_id == 0); { @@ -10810,7 +10830,7 @@ test "Screen: hyperlink accepts its current values" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.startHyperlink("http://example.com", "current"); @@ -10826,7 +10846,7 @@ test "Screen: implicit hyperlink ID wraps" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); s.cursor.hyperlink_implicit_id = std.math.maxInt(size.OffsetInt); @@ -10864,7 +10884,7 @@ test "Screen: hyperlink reuse" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); try testing.expect(s.cursor.hyperlink_id == 0); @@ -10903,7 +10923,7 @@ test "Screen: hyperlink cursor state on resize" { // it may be invalid one day. It's here to document/verify the // current behavior. - var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 5, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); // Start a hyperlink @@ -10935,7 +10955,7 @@ test "Screen: cursorSetHyperlink OOM + URI too large for string alloc" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 0 }); defer s.deinit(); // Start a hyperlink with a URI that just barely fits in the string alloc. @@ -10973,7 +10993,7 @@ test "Screen: increaseCapacity cursor style ref count preserved" { var s = try init(io, alloc, .{ .cols = 5, .rows = 5, - .max_scrollback = 0, + .max_scrollback_bytes = 0, }); defer s.deinit(); try s.setAttribute(.bold); @@ -11029,7 +11049,7 @@ test "Screen: increaseCapacity cursor hyperlink ref count preserved" { var s = try init(io, alloc, .{ .cols = 5, .rows = 5, - .max_scrollback = 0, + .max_scrollback_bytes = 0, }); defer s.deinit(); try s.startHyperlink("https://example.com/", null); @@ -11073,7 +11093,7 @@ test "Screen: increaseCapacity cursor with both style and hyperlink preserved" { var s = try init(io, alloc, .{ .cols = 5, .rows = 5, - .max_scrollback = 0, + .max_scrollback_bytes = 0, }); defer s.deinit(); @@ -11139,7 +11159,7 @@ test "Screen: increaseCapacity non-cursor page returns early" { var s = try init(io, alloc, .{ .cols = 80, .rows = 24, - .max_scrollback = 10000, + .max_scrollback_bytes = 10000, }); defer s.deinit(); @@ -11223,7 +11243,7 @@ test "Screen: cursorDown to page with insufficient capacity" { const io = testing.io; // Small screen to make page boundary crossing easy to set up - var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback = 1 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 3, .max_scrollback_bytes = 1 }); defer s.deinit(); // Scroll down enough to create a second page @@ -11293,7 +11313,7 @@ test "Screen setAttribute increases capacity when style map is full" { const io = testing.io; // Use a small screen with multiple rows - var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback = 10 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 10 }); defer s.deinit(); // Write content to multiple rows @@ -11345,7 +11365,7 @@ test "Screen setAttribute splits page on OutOfSpace at max styles" { var s = try init(io, alloc, .{ .cols = 10, .rows = 10, - .max_scrollback = 0, + .max_scrollback_bytes = 0, }); defer s.deinit(); @@ -11413,7 +11433,7 @@ test "selectionString map allocation failure cleanup" { const testing = std.testing; const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("hello"); @@ -11444,7 +11464,7 @@ test "Screen: promptClickMove line right basic" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode @@ -11472,7 +11492,7 @@ test "Screen: promptClickMove line right cursor not on input" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode @@ -11500,7 +11520,7 @@ test "Screen: promptClickMove line right click on same position" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode @@ -11527,7 +11547,7 @@ test "Screen: promptClickMove line right skips non-input cells" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode @@ -11560,7 +11580,7 @@ test "Screen: promptClickMove line right soft-wrapped line" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode @@ -11599,7 +11619,7 @@ test "Screen: promptClickMove disabled when click is none" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Click mode is .none by default (disabled) @@ -11626,7 +11646,7 @@ test "Screen: promptClickMove line right stops at hard wrap" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode @@ -11659,7 +11679,7 @@ test "Screen: promptClickMove line right stops at non-continuation row" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode @@ -11707,7 +11727,7 @@ test "Screen: promptClickMove line left basic" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode @@ -11735,7 +11755,7 @@ test "Screen: promptClickMove line left skips non-input cells" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode @@ -11768,7 +11788,7 @@ test "Screen: promptClickMove line left soft-wrapped line" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode @@ -11807,7 +11827,7 @@ test "Screen: promptClickMove line left stops at hard wrap" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode @@ -11843,7 +11863,7 @@ test "Screen: promptClickMove click right of input same line" { // Set up: "> hello" where "> " is prompt and "hello" is input // Clicking to the right of the 'o' should move cursor past the input - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode @@ -11871,7 +11891,7 @@ test "Screen: promptClickMove click right of input cursor at end" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode @@ -11898,7 +11918,7 @@ test "Screen: promptClickMove click right of input on lower line" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode @@ -11928,7 +11948,7 @@ test "Screen: promptClickMove click right of input cursor at end lower line" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode @@ -11954,7 +11974,7 @@ test "Screen: promptClickMove click right of input cursor on last char" { const alloc = testing.allocator; const io = testing.io; - var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback = 0 }); + var s = try init(io, alloc, .{ .cols = 20, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); // Enable line click mode diff --git a/src/terminal/Selection.zig b/src/terminal/Selection.zig index b85e56254..398496da6 100644 --- a/src/terminal/Selection.zig +++ b/src/terminal/Selection.zig @@ -512,7 +512,7 @@ pub fn adjust( test "Selection: adjust right" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("A1234\nB5678\nC1234\nD5678"); @@ -579,7 +579,7 @@ test "Selection: adjust right" { test "Selection: adjust left" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("A1234\nB5678\nC1234\nD5678"); @@ -628,7 +628,7 @@ test "Selection: adjust left" { test "Selection: adjust left skips blanks" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("A1234\nB5678\nC12\nD56"); @@ -677,7 +677,7 @@ test "Selection: adjust left skips blanks" { test "Selection: adjust up" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("A\nB\nC\nD\nE"); @@ -724,7 +724,7 @@ test "Selection: adjust up" { test "Selection: adjust down" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("A\nB\nC\nD\nE"); @@ -771,7 +771,7 @@ test "Selection: adjust down" { test "Selection: adjust down with not full screen" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("A\nB\nC"); @@ -799,7 +799,7 @@ test "Selection: adjust down with not full screen" { test "Selection: adjust home" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("A\nB\nC"); @@ -827,7 +827,7 @@ test "Selection: adjust home" { test "Selection: adjust end with not full screen" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("A\nB\nC"); @@ -855,7 +855,7 @@ test "Selection: adjust end with not full screen" { test "Selection: adjust beginning of line" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 8, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 8, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("A12 B34\nC12 D34"); @@ -925,7 +925,7 @@ test "Selection: adjust beginning of line" { test "Selection: adjust end of line" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 8, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 8, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("A12 B34\nC12 D34"); @@ -996,7 +996,7 @@ test "Selection: order, standard" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 100, .rows = 100, .max_scrollback = 1 }); + var s = try Screen.init(io, alloc, .{ .cols = 100, .rows = 100, .max_scrollback_bytes = 1 }); defer s.deinit(); { @@ -1061,7 +1061,7 @@ test "Selection: rectangle corners clamp across mixed-width pages" { var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 4, .rows = 2, - .max_scrollback = 0, + .max_scrollback_bytes = 0, }); defer s.deinit(); @@ -1087,7 +1087,7 @@ test "Selection: order, rectangle" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 100, .rows = 100, .max_scrollback = 1 }); + var s = try Screen.init(io, alloc, .{ .cols = 100, .rows = 100, .max_scrollback_bytes = 1 }); defer s.deinit(); // Conventions: @@ -1199,7 +1199,7 @@ test "Selection: order, rectangle" { test "topLeft" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); { // forward @@ -1262,7 +1262,7 @@ test "topLeft" { test "bottomRight" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); { // forward @@ -1325,7 +1325,7 @@ test "bottomRight" { test "ordered" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); { // forward @@ -1406,7 +1406,7 @@ test "ordered" { test "Selection: contains" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 10, .max_scrollback_bytes = 0 }); defer s.deinit(); { const sel = Selection.init( @@ -1452,7 +1452,7 @@ test "Selection: contains" { test "Selection: contains, rectangle" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 15, .rows = 15, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 15, .rows = 15, .max_scrollback_bytes = 0 }); defer s.deinit(); { const sel = Selection.init( @@ -1514,7 +1514,7 @@ test "Selection: contains, rectangle" { test "Selection: containedRow" { const testing = std.testing; - var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 5, .max_scrollback = 0 }); + var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); { @@ -1637,7 +1637,7 @@ test "Selection: containedRow clamps mixed-width pages" { var s = try Screen.init(testing.io, testing.allocator, .{ .cols = 4, .rows = 3, - .max_scrollback = 0, + .max_scrollback_bytes = 0, }); defer s.deinit(); diff --git a/src/terminal/SelectionGesture.zig b/src/terminal/SelectionGesture.zig index ddcb05be4..a842b2471 100644 --- a/src/terminal/SelectionGesture.zig +++ b/src/terminal/SelectionGesture.zig @@ -1029,7 +1029,7 @@ fn testDragSelection( .padding_left = 5, .screen_height = 110, }; - var screen = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 5, .max_scrollback = 0 }); + var screen = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 0 }); defer screen.deinit(); const click_pin = screen.pages.pin(.{ @@ -1090,7 +1090,7 @@ fn testDragSelectionIsNull( .padding_left = 5, .screen_height = 110, }; - var screen = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 5, .max_scrollback = 0 }); + var screen = try Screen.init(testing.io, testing.allocator, .{ .cols = 10, .rows = 5, .max_scrollback_bytes = 0 }); defer screen.deinit(); const click_pin = screen.pages.pin(.{ @@ -1724,7 +1724,7 @@ test "SelectionGesture autoscroll tick scrolls and continues drag" { } test "SelectionGesture autoscroll tick resolves drag pin after scrolling" { - var t = try Terminal.init(testing.io, testing.allocator, .{ .cols = 5, .rows = 3, .max_scrollback = 10 }); + var t = try Terminal.init(testing.io, testing.allocator, .{ .cols = 5, .rows = 3, .max_scrollback_bytes = 10 }); defer t.deinit(testing.allocator); try t.printString("1111\n2222\n3333\n4444\n5555"); t.scrollViewport(.{ .delta = -2 }); diff --git a/src/terminal/StringMap.zig b/src/terminal/StringMap.zig index d5de87426..9b2fa3ca8 100644 --- a/src/terminal/StringMap.zig +++ b/src/terminal/StringMap.zig @@ -131,7 +131,7 @@ test "StringMap searchIterator" { defer re.deinit(); // Initialize our screen - var s = try Screen.init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 5, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); const str = "1ABCD2EFGH\n3IJKL"; try s.testWriteString(str); @@ -190,7 +190,7 @@ test "StringMap searchIterator URL detection" { defer re.deinit(); // Initialize our screen with text containing a URL - var s = try Screen.init(io, alloc, .{ .cols = 40, .rows = 5, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 40, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("hello https://example.com/path world"); @@ -252,7 +252,7 @@ test "StringMap searchIterator URL with click position" { defer re.deinit(); // Initialize our screen with text containing a URL - var s = try Screen.init(io, alloc, .{ .cols = 40, .rows = 5, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 40, .rows = 5, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("hello https://example.com world"); diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index 52c066ebc..b048d4d99 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -256,7 +256,15 @@ pub const Cursor = struct { pub const Options = struct { cols: size.CellCountInt, rows: size.CellCountInt, - max_scrollback: usize = 10_000, + + /// The maximum size of scrollback in bytes. Zero disables scrollback. + max_scrollback_bytes: usize = 10_000, + + /// The maximum number of physical scrollback rows, excluding the active + /// area. Null is unlimited. The effective limit permits at least one + /// standard page and only complete historical pages are pruned. + max_scrollback_lines: ?usize = null, + colors: Colors = .default, /// The default mode state. When the terminal gets a reset, it @@ -300,7 +308,8 @@ pub fn init( var screen_set: ScreenSet = try .init(io_impl, alloc, .{ .cols = cols, .rows = rows, - .max_scrollback = opts.max_scrollback, + .max_scrollback_bytes = opts.max_scrollback_bytes, + .max_scrollback_lines = opts.max_scrollback_lines, .kitty_image_storage_limit = opts.kitty_image_storage_limit, .kitty_image_loading_limits = opts.kitty_image_loading_limits, }); @@ -3823,7 +3832,7 @@ pub fn resize( .{ .cols = opts.cols, .rows = opts.rows, - .max_scrollback = 0, + .max_scrollback_bytes = 0, .kitty_image_storage_limit = if (comptime build_options.kitty_graphics) primary.kitty_images.total_limit else @@ -3871,6 +3880,21 @@ pub fn resize( }; } +test "Terminal forwards max scrollback lines" { + const max_lines: usize = 123; + var t = try init(testing.io, testing.allocator, .{ + .cols = 80, + .rows = 24, + .max_scrollback_lines = max_lines, + }); + defer t.deinit(testing.allocator); + + try testing.expectEqual( + max_lines, + t.screens.active.pages.explicit_max_lines, + ); +} + test "Terminal: resize resets synchronized output" { const alloc = testing.allocator; const io_impl = testing.io; @@ -4287,7 +4311,7 @@ pub fn switchScreen(self: *Terminal, key: ScreenSet.Key) !?*Screen { .{ .cols = self.cols, .rows = self.rows, - .max_scrollback = switch (key) { + .max_scrollback_bytes = switch (key) { .primary => primary.pages.explicit_max_size, .alternate => 0, }, @@ -7656,7 +7680,7 @@ test "Terminal: insertLines top/bottom scroll region" { test "Terminal: insertLines across page boundary marks all shifted rows dirty" { const alloc = testing.allocator; const io_impl = testing.io; - var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 10, .max_scrollback = 1024 }); + var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 10, .max_scrollback_bytes = 1024 }); defer t.deinit(alloc); const first_page = t.screens.active.pages.pages.first.?; @@ -7711,7 +7735,7 @@ test "Terminal: insertLines hyperlink-dense row crosses page boundary" { // page's capacity and retry rather than corrupting the page list. const alloc = testing.allocator; const io_impl = testing.io; - var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 10, .max_scrollback = 1024 }); + var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 10, .max_scrollback_bytes = 1024 }); defer t.deinit(alloc); const pages = &t.screens.active.pages; @@ -8403,7 +8427,7 @@ test "Terminal: scrollUp creates scrollback in primary screen" { // scrollUp (CSI S) should push lines into scrollback like xterm. const alloc = testing.allocator; const io_impl = testing.io; - var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 5, .max_scrollback = 10 }); + var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 5, .max_scrollback_bytes = 10 }); defer t.deinit(alloc); // Fill the screen with content @@ -8446,11 +8470,11 @@ test "Terminal: scrollUp creates scrollback in primary screen" { } } -test "Terminal: scrollUp with max_scrollback zero" { - // When max_scrollback is 0, scrollUp should still work but not retain history +test "Terminal: scrollUp with max_scrollback_bytes zero" { + // When max_scrollback_bytes is 0, scrollUp should still work but not retain history const alloc = testing.allocator; const io_impl = testing.io; - var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 5, .max_scrollback = 0 }); + var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 5, .max_scrollback_bytes = 0 }); defer t.deinit(alloc); try t.printString("AAAAA"); @@ -8479,11 +8503,11 @@ test "Terminal: scrollUp with max_scrollback zero" { } } -test "Terminal: scrollUp with max_scrollback zero and top margin" { - // When max_scrollback is 0 and top margin is set, should use deleteLines path +test "Terminal: scrollUp with max_scrollback_bytes zero and top margin" { + // When max_scrollback_bytes is 0 and top margin is set, should use deleteLines path const alloc = testing.allocator; const io_impl = testing.io; - var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 5, .max_scrollback = 0 }); + var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 5, .max_scrollback_bytes = 0 }); defer t.deinit(alloc); try t.printString("AAAAA"); @@ -8510,11 +8534,11 @@ test "Terminal: scrollUp with max_scrollback zero and top margin" { } } -test "Terminal: scrollUp with max_scrollback zero and left/right margin" { - // When max_scrollback is 0 with left/right margins, uses deleteLines path +test "Terminal: scrollUp with max_scrollback_bytes zero and left/right margin" { + // When max_scrollback_bytes is 0 with left/right margins, uses deleteLines path const alloc = testing.allocator; const io_impl = testing.io; - var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 10, .max_scrollback = 0 }); + var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 10, .max_scrollback_bytes = 0 }); defer t.deinit(alloc); try t.printString("AAAAABBBBB"); @@ -9696,7 +9720,7 @@ test "Terminal: index bottom of scroll region with hyperlinks" { test "Terminal: index bottom of scroll region clear hyperlinks" { const alloc = testing.allocator; const io_impl = testing.io; - var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 5, .max_scrollback = 0 }); + var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 5, .max_scrollback_bytes = 0 }); defer t.deinit(alloc); t.setTopAndBottomMargin(2, 3); @@ -9889,7 +9913,7 @@ test "Terminal: index bottom of scroll region creates scrollback" { test "Terminal: index bottom of scroll region no scrollback" { const alloc = testing.allocator; const io_impl = testing.io; - var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 5, .max_scrollback = 0 }); + var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 5, .max_scrollback_bytes = 0 }); defer t.deinit(alloc); t.setTopAndBottomMargin(1, 3); @@ -10056,7 +10080,7 @@ test "Terminal: index bottom of alt screen top region" { test "Terminal: scrollUp top region no scrollback" { const alloc = testing.allocator; const io_impl = testing.io; - var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 5, .max_scrollback = 0 }); + var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 5, .max_scrollback_bytes = 0 }); defer t.deinit(alloc); try t.printString("A\nB\nC\nD\nE"); @@ -10641,7 +10665,7 @@ test "Terminal: deleteLines colors with bg color" { test "Terminal: deleteLines across page boundary marks all shifted rows dirty" { const alloc = testing.allocator; const io_impl = testing.io; - var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 10, .max_scrollback = 1024 }); + var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 10, .max_scrollback_bytes = 1024 }); defer t.deinit(alloc); const first_page = t.screens.active.pages.pages.first.?; @@ -10701,7 +10725,7 @@ test "Terminal: deleteLines hyperlink-dense row crosses page boundary" { // this exercises the cursor accounting of the capacity increase. const alloc = testing.allocator; const io_impl = testing.io; - var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 10, .max_scrollback = 1024 }); + var t = try init(io_impl, alloc, .{ .rows = 5, .cols = 10, .max_scrollback_bytes = 1024 }); defer t.deinit(alloc); const pages = &t.screens.active.pages; diff --git a/src/terminal/c/terminal.zig b/src/terminal/c/terminal.zig index 195dd94dd..d7514957d 100644 --- a/src/terminal/c/terminal.zig +++ b/src/terminal/c/terminal.zig @@ -365,7 +365,7 @@ fn new_( .{ .cols = opts.cols, .rows = opts.rows, - .max_scrollback = opts.max_scrollback, + .max_scrollback_bytes = opts.max_scrollback, }, ); errdefer t.deinit(alloc); diff --git a/src/terminal/render.zig b/src/terminal/render.zig index c70e69627..867cd6224 100644 --- a/src/terminal/render.zig +++ b/src/terminal/render.zig @@ -1427,7 +1427,7 @@ test "incremental updates match full rebuild" { var t = try Terminal.init(io, alloc, .{ .cols = 20, .rows = 8, - .max_scrollback = 500, + .max_scrollback_bytes = 500, }); defer t.deinit(alloc); @@ -2010,7 +2010,7 @@ test "linkCells with scrollback spanning pages" { var t = try Terminal.init(io, alloc, .{ .cols = page.std_capacity.cols, .rows = viewport_rows, - .max_scrollback = 10_000, + .max_scrollback_bytes = 10_000, }); defer t.deinit(alloc); diff --git a/src/terminal/search/pagelist.zig b/src/terminal/search/pagelist.zig index f9fb3c9c1..01d4233d1 100644 --- a/src/terminal/search/pagelist.zig +++ b/src/terminal/search/pagelist.zig @@ -381,7 +381,7 @@ test "compressed history match spanning page boundary remains compressed" { var t: Terminal = try .init(io, alloc, .{ .cols = 80, .rows = 24, - .max_scrollback = 10 * 1024 * 1024, + .max_scrollback_bytes = 10 * 1024 * 1024, }); defer t.deinit(alloc); diff --git a/src/terminal/search/screen.zig b/src/terminal/search/screen.zig index fee53e007..81e43ecaf 100644 --- a/src/terminal/search/screen.zig +++ b/src/terminal/search/screen.zig @@ -977,7 +977,7 @@ test "simple search with history" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 2, - .max_scrollback = std.math.maxInt(usize), + .max_scrollback_bytes = std.math.maxInt(usize), }); defer t.deinit(alloc); const list: *PageList = &t.screens.active.pages; @@ -1019,7 +1019,7 @@ test "reload active with history change" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 2, - .max_scrollback = std.math.maxInt(usize), + .max_scrollback_bytes = std.math.maxInt(usize), }); defer t.deinit(alloc); const list: *PageList = &t.screens.active.pages; @@ -1207,7 +1207,7 @@ test "select after resize resets stale flattened results" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 3, - .max_scrollback = std.math.maxInt(usize), + .max_scrollback_bytes = std.math.maxInt(usize), }); defer t.deinit(alloc); @@ -1307,7 +1307,7 @@ test "select into history" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 2, - .max_scrollback = std.math.maxInt(usize), + .max_scrollback_bytes = std.math.maxInt(usize), }); defer t.deinit(alloc); const list: *PageList = &t.screens.active.pages; @@ -1485,7 +1485,7 @@ test "select prev with history" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 2, - .max_scrollback = std.math.maxInt(usize), + .max_scrollback_bytes = std.math.maxInt(usize), }); defer t.deinit(alloc); const list: *PageList = &t.screens.active.pages; @@ -1540,7 +1540,7 @@ test "select prev wraps when all matches are in history" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 2, - .max_scrollback = std.math.maxInt(usize), + .max_scrollback_bytes = std.math.maxInt(usize), }); defer t.deinit(alloc); const list: *PageList = &t.screens.active.pages; @@ -1605,7 +1605,7 @@ test "select after partial history erase drops a pruned selection" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 2, - .max_scrollback = std.math.maxInt(usize), + .max_scrollback_bytes = std.math.maxInt(usize), }); defer t.deinit(alloc); const list: *PageList = &t.screens.active.pages; @@ -1638,7 +1638,7 @@ test "select after history compaction ignores replaced results" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 2, - .max_scrollback = std.math.maxInt(usize), + .max_scrollback_bytes = std.math.maxInt(usize), }); defer t.deinit(alloc); const list: *PageList = &t.screens.active.pages; @@ -1673,7 +1673,7 @@ test "select after partial history page erase ignores shifted results" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 2, - .max_scrollback = std.math.maxInt(usize), + .max_scrollback_bytes = std.math.maxInt(usize), }); defer t.deinit(alloc); const list: *PageList = &t.screens.active.pages; @@ -1707,7 +1707,7 @@ test "reload defers pruning unselected history results" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 2, - .max_scrollback = std.math.maxInt(usize), + .max_scrollback_bytes = std.math.maxInt(usize), }); defer t.deinit(alloc); const list: *PageList = &t.screens.active.pages; @@ -1742,7 +1742,7 @@ test "reload after partial history page erase drops shifted selection first" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 2, - .max_scrollback = std.math.maxInt(usize), + .max_scrollback_bytes = std.math.maxInt(usize), }); defer t.deinit(alloc); const list: *PageList = &t.screens.active.pages; @@ -1781,7 +1781,7 @@ test "select after history page split ignores moved results" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 2, - .max_scrollback = std.math.maxInt(usize), + .max_scrollback_bytes = std.math.maxInt(usize), }); defer t.deinit(alloc); const list: *PageList = &t.screens.active.pages; @@ -1815,7 +1815,7 @@ test "screen search no scrollback has no history" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 2, - .max_scrollback = 0, + .max_scrollback_bytes = 0, }); defer t.deinit(alloc); @@ -1852,7 +1852,7 @@ test "reloadActive partial history cleanup on appendSlice error" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 2, - .max_scrollback = std.math.maxInt(usize), + .max_scrollback_bytes = std.math.maxInt(usize), }); defer t.deinit(alloc); const list: *PageList = &t.screens.active.pages; @@ -1900,7 +1900,7 @@ test "reloadActive partial history cleanup on loop append error" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 2, - .max_scrollback = std.math.maxInt(usize), + .max_scrollback_bytes = std.math.maxInt(usize), }); defer t.deinit(alloc); const list: *PageList = &t.screens.active.pages; @@ -1947,7 +1947,7 @@ test "select after clearing scrollback" { var t: Terminal = try .init(io, alloc, .{ .cols = 10, .rows = 2, - .max_scrollback = std.math.maxInt(usize), + .max_scrollback_bytes = std.math.maxInt(usize), }); defer t.deinit(alloc); const list: *PageList = &t.screens.active.pages; diff --git a/src/terminal/search/sliding_window.zig b/src/terminal/search/sliding_window.zig index e83a187ae..95b37d730 100644 --- a/src/terminal/search/sliding_window.zig +++ b/src/terminal/search/sliding_window.zig @@ -722,7 +722,7 @@ test "SlidingWindow empty needle has no matches" { var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, - .max_scrollback = 0, + .max_scrollback_bytes = 0, }); defer s.deinit(); try s.testWriteString("hello"); @@ -739,7 +739,7 @@ test "SlidingWindow single append" { var w: SlidingWindow = try .init(alloc, .forward, "boo!"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("hello. boo! hello. boo!"); @@ -785,7 +785,7 @@ test "SlidingWindow single append case insensitive ASCII" { var w: SlidingWindow = try .init(alloc, .forward, "Boo!"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("hello. boo! hello. boo!"); @@ -831,7 +831,7 @@ test "SlidingWindow single append single char" { var w: SlidingWindow = try .init(alloc, .forward, "b"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("hello. boo! hello. boo!"); @@ -877,7 +877,7 @@ test "SlidingWindow single append no match" { var w: SlidingWindow = try .init(alloc, .forward, "nope!"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("hello. boo! hello. boo!"); @@ -902,7 +902,7 @@ test "SlidingWindow two pages" { var w: SlidingWindow = try .init(alloc, .forward, "boo!"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); // Fill up the first page. The final bytes in the first page @@ -958,7 +958,7 @@ test "SlidingWindow two pages single char" { var w: SlidingWindow = try .init(alloc, .forward, "b"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); // Fill up the first page. The final bytes in the first page @@ -1014,7 +1014,7 @@ test "SlidingWindow two pages match across boundary" { var w: SlidingWindow = try .init(alloc, .forward, "hello, world"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); // Fill up the first page. The final bytes in the first page @@ -1060,7 +1060,7 @@ test "SlidingWindow two pages no match across boundary with newline" { var w: SlidingWindow = try .init(alloc, .forward, "hello, world"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); // Fill up the first page. The final bytes in the first page @@ -1094,7 +1094,7 @@ test "SlidingWindow two pages no match across boundary with newline reverse" { var w: SlidingWindow = try .init(alloc, .reverse, "hello, world"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); // Fill up the first page. The final bytes in the first page @@ -1125,7 +1125,7 @@ test "SlidingWindow two pages no match prunes first page" { var w: SlidingWindow = try .init(alloc, .forward, "nope!"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); // Fill up the first page. The final bytes in the first page @@ -1158,7 +1158,7 @@ test "SlidingWindow two pages no match keeps both pages" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); // Fill up the first page. The final bytes in the first page @@ -1202,7 +1202,7 @@ test "SlidingWindow single append across circular buffer boundary" { var w: SlidingWindow = try .init(alloc, .forward, "abc"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("XXXXXXXXXXXXXXXXXXXboo!XXXXX"); @@ -1259,7 +1259,7 @@ test "SlidingWindow single append match on boundary" { var w: SlidingWindow = try .init(alloc, .forward, "abcd"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("o!XXXXXXXXXXXXXXXXXXXbo"); @@ -1319,7 +1319,7 @@ test "SlidingWindow single append reversed" { var w: SlidingWindow = try .init(alloc, .reverse, "boo!"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("hello. boo! hello. boo!"); @@ -1365,7 +1365,7 @@ test "SlidingWindow single append no match reversed" { var w: SlidingWindow = try .init(alloc, .reverse, "nope!"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("hello. boo! hello. boo!"); @@ -1390,7 +1390,7 @@ test "SlidingWindow two pages reversed" { var w: SlidingWindow = try .init(alloc, .reverse, "boo!"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); // Fill up the first page. The final bytes in the first page @@ -1446,7 +1446,7 @@ test "SlidingWindow two pages match across boundary reversed" { var w: SlidingWindow = try .init(alloc, .reverse, "hello, world"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); // Fill up the first page. The final bytes in the first page @@ -1502,7 +1502,7 @@ test "SlidingWindow two pages no match prunes first page reversed" { var w: SlidingWindow = try .init(alloc, .reverse, "nope!"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); // Fill up the first page. The final bytes in the first page @@ -1535,7 +1535,7 @@ test "SlidingWindow two pages no match keeps both pages reversed" { const alloc = testing.allocator; const io = testing.io; - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 1000 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 1000 }); defer s.deinit(); // Fill up the first page. The final bytes in the first page @@ -1579,7 +1579,7 @@ test "SlidingWindow single append across circular buffer boundary reversed" { var w: SlidingWindow = try .init(alloc, .reverse, "abc"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("XXXXXXXXXXXXXXXXXXXboo!XXXXX"); @@ -1637,7 +1637,7 @@ test "SlidingWindow single append match on boundary reversed" { var w: SlidingWindow = try .init(alloc, .reverse, "abcd"); defer w.deinit(); - var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback = 0 }); + var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, .max_scrollback_bytes = 0 }); defer s.deinit(); try s.testWriteString("o!XXXXXXXXXXXXXXXXXXXbo"); @@ -1779,7 +1779,7 @@ test "SlidingWindow append whitespace only node" { var s = try Screen.init(io, alloc, .{ .cols = 80, .rows = 24, - .max_scrollback = 0, + .max_scrollback_bytes = 0, }); defer s.deinit(); diff --git a/src/terminal/stream_terminal.zig b/src/terminal/stream_terminal.zig index bbbe5f83e..7aa1067bc 100644 --- a/src/terminal/stream_terminal.zig +++ b/src/terminal/stream_terminal.zig @@ -2108,7 +2108,7 @@ test "stream: CSI W with intermediate but no params" { var t: Terminal = try .init(testing.io, testing.allocator, .{ .cols = 80, .rows = 24, - .max_scrollback = 100, + .max_scrollback_bytes = 100, }); defer t.deinit(testing.allocator); diff --git a/src/termio/Termio.zig b/src/termio/Termio.zig index 5d7a47d25..c93180314 100644 --- a/src/termio/Termio.zig +++ b/src/termio/Termio.zig @@ -246,7 +246,7 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void { break :opts .{ .cols = grid_size.columns, .rows = grid_size.rows, - .max_scrollback = opts.full_config.@"scrollback-limit", + .max_scrollback_bytes = opts.full_config.@"scrollback-limit", .default_modes = default_modes, .default_cursor_style = opts.config.cursor_style, .default_cursor_blink = opts.config.cursor_blink, diff --git a/test/fuzz-libghostty/src/fuzz_stream.zig b/test/fuzz-libghostty/src/fuzz_stream.zig index 4c14086f0..6f19b4b19 100644 --- a/test/fuzz-libghostty/src/fuzz_stream.zig +++ b/test/fuzz-libghostty/src/fuzz_stream.zig @@ -44,7 +44,7 @@ pub export fn zig_fuzz_test( var t = Terminal.init(threaded.io(), alloc, .{ .cols = 80, .rows = 24, - .max_scrollback = 100, + .max_scrollback_bytes = 100, }) catch return; defer t.deinit(alloc);