diff --git a/include/ghostty/vt/terminal.h b/include/ghostty/vt/terminal.h index f8bb3aa22..a6ea128e7 100644 --- a/include/ghostty/vt/terminal.h +++ b/include/ghostty/vt/terminal.h @@ -556,6 +556,20 @@ typedef enum { * Output type: GhosttyString * */ GHOSTTY_TERMINAL_DATA_PWD = 13, + + /** + * The total number of rows in the active screen including scrollback. + * + * Output type: size_t * + */ + GHOSTTY_TERMINAL_DATA_TOTAL_ROWS = 14, + + /** + * The number of scrollback rows (total rows minus viewport rows). + * + * Output type: size_t * + */ + GHOSTTY_TERMINAL_DATA_SCROLLBACK_ROWS = 15, } GhosttyTerminalData; /** diff --git a/src/terminal/c/terminal.zig b/src/terminal/c/terminal.zig index f5b271e35..c366134b5 100644 --- a/src/terminal/c/terminal.zig +++ b/src/terminal/c/terminal.zig @@ -445,6 +445,8 @@ pub const TerminalData = enum(c_int) { mouse_tracking = 11, title = 12, pwd = 13, + total_rows = 14, + scrollback_rows = 15, /// Output type expected for querying the data of the given kind. pub fn OutType(comptime self: TerminalData) type { @@ -457,6 +459,7 @@ pub const TerminalData = enum(c_int) { .scrollbar => TerminalScrollbar, .cursor_style => style_c.Style, .title, .pwd => lib.String, + .total_rows, .scrollback_rows => usize, }; } }; @@ -513,6 +516,8 @@ fn getTyped( const pwd = t.getPwd() orelse ""; out.* = .{ .ptr = pwd.ptr, .len = pwd.len }; }, + .total_rows => out.* = t.screens.active.pages.total_rows, + .scrollback_rows => out.* = t.screens.active.pages.total_rows - t.rows, } return .success; @@ -1004,6 +1009,48 @@ test "get mouse_tracking" { try testing.expect(!tracking); } +test "get total_rows" { + var t: Terminal = null; + try testing.expectEqual(Result.success, new( + &lib_alloc.test_allocator, + &t, + .{ + .cols = 80, + .rows = 24, + .max_scrollback = 10_000, + }, + )); + defer free(t); + + var total: usize = undefined; + try testing.expectEqual(Result.success, get(t, .total_rows, @ptrCast(&total))); + try testing.expect(total >= 24); +} + +test "get scrollback_rows" { + var t: Terminal = null; + try testing.expectEqual(Result.success, new( + &lib_alloc.test_allocator, + &t, + .{ + .cols = 80, + .rows = 3, + .max_scrollback = 10_000, + }, + )); + defer free(t); + + var scrollback: usize = undefined; + try testing.expectEqual(Result.success, get(t, .scrollback_rows, @ptrCast(&scrollback))); + try testing.expectEqual(@as(usize, 0), scrollback); + + // Write enough lines to push content into scrollback + vt_write(t, "line1\r\nline2\r\nline3\r\nline4\r\nline5\r\n", 34); + + try testing.expectEqual(Result.success, get(t, .scrollback_rows, @ptrCast(&scrollback))); + try testing.expectEqual(@as(usize, 2), scrollback); +} + test "get invalid" { var t: Terminal = null; try testing.expectEqual(Result.success, new(