diff --git a/src/config/Config.zig b/src/config/Config.zig index 90ccfc319..3d762760f 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -95,6 +95,10 @@ pub const compatibility = std.StaticStringMap( // Ghostty 1.3 rename the "window" option to "new-window". // See: https://github.com/ghostty-org/ghostty/pull/9764 .{ "macos-dock-drop-behavior", compatMacOSDockDropBehavior }, + + // Ghostty 1.4 renamed `scrollback-limit` to `scrollback-limit-bytes` + // when `scrollback-limit-lines` was added so the units are explicit. + .{ "scrollback-limit", cli.compatibilityRenamed(Config, "scrollback-limit-bytes") }, }); /// Set Ghostty's graphical user interface language to a language other than the @@ -1375,11 +1379,32 @@ input: RepeatableReadableIO = .{}, /// /// This size is per terminal surface, not for the entire application. /// -/// It is not currently possible to set an unlimited scrollback buffer. -/// This is a future planned feature. +/// A separate maximum can be set with `scrollback-limit-lines`; if both limits +/// are set, then the first one reached will determine when scrollback is +/// removed. +/// +/// It is not currently possible to set an unlimited byte limit. /// /// This can be changed at runtime but will only affect new terminal surfaces. -@"scrollback-limit": usize = 50_000_000, // 50MB +@"scrollback-limit-bytes": usize = 50_000_000, // 50MB + +/// The maximum number of lines of scrollback to retain. This excludes +/// the active screen. Soft-wrapped lines count as multiple lines. +/// +/// This limit is an estimate. Internally, Ghostty will only trim lines +/// up to the minimum allocation unit that is used internally (called a +/// "page"). The size of a page depends on how many styles, graphemes, etc. +/// take up the screen. In practice, this can be anywhere from a handful to +/// a couple hundred lines. Importantly, memory is capped either way. +/// This means that the actual limited lines will likely be slightly +/// higher in practice. +/// +/// If this is unset, then no line limit will be applied. A separate maximum +/// can be set with `scrollback-limit-bytes`; if both limits are set, then the +/// first one reached will determine when scrollback is removed. +/// +/// This can be changed at runtime but will only affect new terminal surfaces. +@"scrollback-limit-lines": ?usize = null, /// Whether to compress scrollback pages while the terminal is idle. /// @@ -10825,6 +10850,55 @@ test "theme specifying light/dark sets theme usage in conditional state" { } } +test "scrollback limits" { + const testing = std.testing; + const alloc = testing.allocator; + + var cfg = try Config.default(alloc); + defer cfg.deinit(); + var it: TestIterator = .{ .data = &.{ + "--scrollback-limit-bytes=1234", + "--scrollback-limit-lines=567", + } }; + try cfg.loadIter(alloc, &it); + + try testing.expectEqual( + @as(usize, 1234), + cfg.@"scrollback-limit-bytes", + ); + try testing.expectEqual( + @as(?usize, 567), + cfg.@"scrollback-limit-lines", + ); + + var unset_it: TestIterator = .{ .data = &.{ + "--scrollback-limit-lines=", + } }; + try cfg.loadIter(alloc, &unset_it); + + try testing.expectEqual( + @as(?usize, null), + cfg.@"scrollback-limit-lines", + ); +} + +test "compatibility: scrollback-limit renamed to bytes" { + const testing = std.testing; + const alloc = testing.allocator; + + var cfg = try Config.default(alloc); + defer cfg.deinit(); + var it: TestIterator = .{ .data = &.{ + "--scrollback-limit=1234", + } }; + try cfg.loadIter(alloc, &it); + + try testing.expectEqual( + @as(usize, 1234), + cfg.@"scrollback-limit-bytes", + ); +} + test "compatibility: gtk-single-instance desktop" { const testing = std.testing; const alloc = testing.allocator; diff --git a/src/termio/Termio.zig b/src/termio/Termio.zig index c93180314..96c5acc8a 100644 --- a/src/termio/Termio.zig +++ b/src/termio/Termio.zig @@ -246,7 +246,8 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void { break :opts .{ .cols = grid_size.columns, .rows = grid_size.rows, - .max_scrollback_bytes = opts.full_config.@"scrollback-limit", + .max_scrollback_bytes = opts.full_config.@"scrollback-limit-bytes", + .max_scrollback_lines = opts.full_config.@"scrollback-limit-lines", .default_modes = default_modes, .default_cursor_style = opts.config.cursor_style, .default_cursor_blink = opts.config.cursor_blink,