lib-vt: move scrollback limits to terminal_set

Terminal construction previously accepted GhosttyTerminalOptions with
dimensions and one scrollback byte limit. Remove the options struct from
the ABI and make ghostty_terminal_new accept columns and rows directly.

Add byte and line limit options to ghostty_terminal_set and forward them
to the runtime Terminal setters. NULL removes a limit, while zero bytes
disables scrollback. Update type metadata, tests, and all API examples.
This commit is contained in:
Mitchell Hashimoto
2026-07-27 07:11:33 -07:00
parent f4c68d65e5
commit 03d5fa2689
31 changed files with 486 additions and 739 deletions

View File

@@ -7,12 +7,7 @@
int main() {
// Create a terminal with a small grid
GhosttyTerminal terminal;
GhosttyTerminalOptions opts = {
.cols = 80,
.rows = 24,
.max_scrollback = 0,
};
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, opts);
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, 80, 24);
assert(result == GHOSTTY_SUCCESS);
// Write some VT-encoded content into the terminal

View File

@@ -7,12 +7,7 @@
int main() {
// Create a terminal with a small grid
GhosttyTerminal terminal;
GhosttyTerminalOptions opts = {
.cols = 80,
.rows = 24,
.max_scrollback = 0,
};
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, opts);
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, 80, 24);
assert(result == GHOSTTY_SUCCESS);
// Write some VT-encoded content into the terminal

View File

@@ -7,12 +7,7 @@
int main() {
// Create a terminal with a small grid
GhosttyTerminal terminal;
GhosttyTerminalOptions opts = {
.cols = 80,
.rows = 24,
.max_scrollback = 0,
};
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, opts);
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, 80, 24);
assert(result == GHOSTTY_SUCCESS);
// Write some VT-encoded content into the terminal

View File

@@ -87,12 +87,7 @@ void print_all_colors(GhosttyTerminal terminal, const char* label) {
int main() {
// Create a terminal
GhosttyTerminal terminal = NULL;
GhosttyTerminalOptions opts = {
.cols = 80,
.rows = 24,
.max_scrollback = 0,
};
if (ghostty_terminal_new(NULL, &terminal, opts) != GHOSTTY_SUCCESS) {
if (ghostty_terminal_new(NULL, &terminal, 80, 24) != GHOSTTY_SUCCESS) {
fprintf(stderr, "Failed to create terminal\n");
return 1;
}

View File

@@ -30,12 +30,14 @@ static bool compression_idle_step(GhosttyTerminal terminal) {
int main(void) {
GhosttyTerminal terminal;
GhosttyTerminalOptions opts = {
.cols = 80,
.rows = 24,
.max_scrollback = 10 * 1024 * 1024,
};
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, opts);
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, 80, 24);
assert(result == GHOSTTY_SUCCESS);
size_t max_scrollback_bytes = 10 * 1024 * 1024;
result = ghostty_terminal_set(
terminal,
GHOSTTY_TERMINAL_OPT_SCROLLBACK_MAX_BYTES,
&max_scrollback_bytes);
assert(result == GHOSTTY_SUCCESS);
//! [compression-activity]

View File

@@ -74,12 +74,7 @@ GhosttyClipboardWriteResult on_clipboard_write(
int main() {
// Create a terminal
GhosttyTerminal terminal = NULL;
GhosttyTerminalOptions opts = {
.cols = 80,
.rows = 24,
.max_scrollback = 0,
};
if (ghostty_terminal_new(NULL, &terminal, opts) != GHOSTTY_SUCCESS) {
if (ghostty_terminal_new(NULL, &terminal, 80, 24) != GHOSTTY_SUCCESS) {
fprintf(stderr, "Failed to create terminal\n");
return 1;
}

View File

@@ -7,12 +7,7 @@
int main() {
// Create a terminal with a small grid
GhosttyTerminal terminal;
GhosttyTerminalOptions opts = {
.cols = 80,
.rows = 24,
.max_scrollback = 0,
};
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, opts);
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, 80, 24);
assert(result == GHOSTTY_SUCCESS);
// Write VT-encoded content into the terminal to exercise various

View File

@@ -25,12 +25,7 @@ static uint32_t codepoint_at_tracked_ref(GhosttyTrackedGridRef tracked) {
int main() {
GhosttyTerminal terminal;
GhosttyTerminalOptions opts = {
.cols = 8,
.rows = 3,
.max_scrollback = 100,
};
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, opts);
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, 8, 3);
assert(result == GHOSTTY_SUCCESS);
const char *text = "alpha\r\n"

View File

@@ -7,12 +7,7 @@
int main() {
// Create a small terminal
GhosttyTerminal terminal;
GhosttyTerminalOptions opts = {
.cols = 10,
.rows = 3,
.max_scrollback = 0,
};
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, opts);
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, 10, 3);
assert(result == GHOSTTY_SUCCESS);
// Write some content so the grid has interesting data

View File

@@ -72,12 +72,7 @@ int main() {
/* Create a terminal with Kitty graphics enabled. */
GhosttyTerminal terminal = NULL;
GhosttyTerminalOptions opts = {
.cols = 80,
.rows = 24,
.max_scrollback = 0,
};
if (ghostty_terminal_new(NULL, &terminal, opts) != GHOSTTY_SUCCESS) {
if (ghostty_terminal_new(NULL, &terminal, 80, 24) != GHOSTTY_SUCCESS) {
fprintf(stderr, "Failed to create terminal\n");
return 1;
}

View File

@@ -26,12 +26,7 @@ int main(void) {
// from the terminal. The render state captures a snapshot of everything
// needed to draw a frame.
GhosttyTerminal terminal = NULL;
GhosttyTerminalOptions terminal_opts = {
.cols = 40,
.rows = 5,
.max_scrollback = 10000,
};
result = ghostty_terminal_new(NULL, &terminal, terminal_opts);
result = ghostty_terminal_new(NULL, &terminal, 40, 5);
assert(result == GHOSTTY_SUCCESS);
GhosttyRenderState render_state = NULL;

View File

@@ -54,12 +54,7 @@ static GhosttySelectionGestureEvent new_event(
int main() {
GhosttyTerminal terminal;
GhosttyTerminalOptions opts = {
.cols = 20,
.rows = 4,
.max_scrollback = 100,
};
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, opts);
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, 20, 4);
assert(result == GHOSTTY_SUCCESS);
vt_write(terminal, "hello world\r\nsecond line");

View File

@@ -49,12 +49,7 @@ static void print_selection(
int main() {
GhosttyTerminal terminal;
GhosttyTerminalOptions opts = {
.cols = 80,
.rows = 8,
.max_scrollback = 0,
};
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, opts);
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, 80, 8);
assert(result == GHOSTTY_SUCCESS);
// A realistic shell transcript with OSC 133 semantic prompt markers.

View File

@@ -7,12 +7,7 @@ int main(void) {
//! [vt-stream-init]
// Create a terminal
GhosttyTerminal terminal;
GhosttyTerminalOptions opts = {
.cols = 80,
.rows = 24,
.max_scrollback = 0,
};
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, opts);
GhosttyResult result = ghostty_terminal_new(NULL, &terminal, 80, 24);
assert(result == GHOSTTY_SUCCESS);
//! [vt-stream-init]

View File

@@ -6,12 +6,7 @@
int main() {
// Create a terminal
GhosttyTerminal terminal;
GhosttyTerminalOptions opts = {
.cols = 80,
.rows = 24,
.max_scrollback = 0,
};
GhosttyResult result = ghostty_terminal_new(nullptr, &terminal, opts);
GhosttyResult result = ghostty_terminal_new(nullptr, &terminal, 80, 24);
assert(result == GHOSTTY_SUCCESS);
// Feed VT data into the terminal

View File

@@ -3,12 +3,7 @@ import GhosttyVt
// Create a terminal with a small grid
var terminal: GhosttyTerminal?
var opts = GhosttyTerminalOptions(
cols: 80,
rows: 24,
max_scrollback: 0
)
let result = ghostty_terminal_new(nil, &terminal, opts)
let result = ghostty_terminal_new(nil, &terminal, 80, 24)
guard result == GHOSTTY_SUCCESS, let terminal else {
fatalError("Failed to create terminal")
}

View File

@@ -199,20 +199,15 @@
const rows = parseInt(document.getElementById('rows').value, 10);
const vtText = parseEscapes(document.getElementById('vtInput').value);
const TERM_OPTS_SIZE = typeLayout['GhosttyTerminalOptions'].size;
const optsPtr = wasmInstance.exports.ghostty_wasm_alloc_u8_array(TERM_OPTS_SIZE);
new Uint8Array(getBuffer(), optsPtr, TERM_OPTS_SIZE).fill(0);
const optsView = new DataView(getBuffer(), optsPtr, TERM_OPTS_SIZE);
setField(optsView, 'GhosttyTerminalOptions', 'cols', cols);
setField(optsView, 'GhosttyTerminalOptions', 'rows', rows);
setField(optsView, 'GhosttyTerminalOptions', 'max_scrollback', 0);
// Allocate pointer to receive the terminal handle
const termPtrPtr = wasmInstance.exports.ghostty_wasm_alloc_opaque();
// Create terminal
const newResult = wasmInstance.exports.ghostty_terminal_new(0, termPtrPtr, optsPtr);
wasmInstance.exports.ghostty_wasm_free_u8_array(optsPtr, TERM_OPTS_SIZE);
const newResult = wasmInstance.exports.ghostty_terminal_new(
0,
termPtrPtr,
cols,
rows);
if (newResult !== GHOSTTY_SUCCESS) {
throw new Error(`ghostty_terminal_new failed with result ${newResult}`);

View File

@@ -42,8 +42,7 @@
* @code{.c}
* // Create a terminal and feed it some VT data that changes modes
* GhosttyTerminal terminal;
* ghostty_terminal_new(NULL, &terminal,
* (GhosttyTerminalOptions){.cols = 80, .rows = 24, .max_scrollback = 0});
* ghostty_terminal_new(NULL, &terminal, 80, 24);
*
* // Application might write data that enables Kitty keyboard protocol, etc.
* ghostty_terminal_vt_write(terminal, vt_data, vt_len);

View File

@@ -39,8 +39,7 @@
* @code{.c}
* // Create a terminal and feed it some VT data that enables mouse tracking
* GhosttyTerminal terminal;
* ghostty_terminal_new(NULL, &terminal,
* (GhosttyTerminalOptions){.cols = 80, .rows = 24, .max_scrollback = 0});
* ghostty_terminal_new(NULL, &terminal, 80, 24);
*
* // Application might write data that enables mouse reporting, etc.
* ghostty_terminal_vt_write(terminal, vt_data, vt_len);

View File

@@ -172,26 +172,6 @@ extern "C" {
* @{
*/
/**
* Terminal initialization options.
*
* @ingroup terminal
*/
typedef struct {
/** Terminal width in cells. Must be greater than zero. */
uint16_t cols;
/** Terminal height in cells. Must be greater than zero. */
uint16_t rows;
/** Maximum number of lines to keep in scrollback history. */
size_t max_scrollback;
// TODO: Consider ABI compatibility implications of this struct.
// We may want to artificially pad it significantly to support
// future options.
} GhosttyTerminalOptions;
/**
* Amount of compression work to perform before returning.
*
@@ -888,6 +868,28 @@ typedef enum GHOSTTY_ENUM_TYPED {
* Input type: GhosttyTerminalClipboardWriteFn
*/
GHOSTTY_TERMINAL_OPT_CLIPBOARD_WRITE = 26,
/**
* Set the maximum scrollback allocation in bytes.
*
* Lowering the limit immediately removes eligible complete historical
* pages. A value of zero disables scrollback and erases retained history.
* A NULL value pointer removes the byte limit.
*
* Input type: size_t*
*/
GHOSTTY_TERMINAL_OPT_SCROLLBACK_MAX_BYTES = 27,
/**
* Set the maximum number of physical lines retained in scrollback.
*
* Lowering the limit immediately removes eligible complete historical
* pages. The effective limit retains the active-area and page-granularity
* minimums. A NULL value pointer removes the line limit.
*
* Input type: size_t*
*/
GHOSTTY_TERMINAL_OPT_SCROLLBACK_MAX_LINES = 28,
GHOSTTY_TERMINAL_OPT_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
} GhosttyTerminalOption;
@@ -1221,16 +1223,22 @@ typedef enum GHOSTTY_ENUM_TYPED {
/**
* Create a new terminal instance.
*
* The terminal starts with various reasonable defaults e.g. around
* scrollback limits. Use ghostty_terminal_set() to change any options
* prior to using the terminal.
*
* @param allocator Pointer to allocator, or NULL to use the default allocator
* @param terminal Pointer to store the created terminal handle
* @param options Terminal initialization options
* @param cols Terminal width in cells (must be greater than zero)
* @param rows Terminal height in cells (must be greater than zero)
* @return GHOSTTY_SUCCESS on success, or an error code on failure
*
* @ingroup terminal
*/
GHOSTTY_API GhosttyResult ghostty_terminal_new(const GhosttyAllocator* allocator,
GhosttyTerminal* terminal,
GhosttyTerminalOptions options);
GhosttyTerminal* terminal,
uint16_t cols,
uint16_t rows);
/**
* Free a terminal instance.
@@ -1291,7 +1299,8 @@ GHOSTTY_API GhosttyResult ghostty_terminal_resize(GhosttyTerminal terminal,
* write_pty callback and userdata pointer. The value is passed
* directly for pointer types (callbacks, userdata) or as a pointer
* to the value for non-pointer types (e.g. GhosttyString*).
* NULL clears the option to its default.
* The behavior of a NULL value is specific to each option and is
* documented by the corresponding GhosttyTerminalOption value.
*
* Callbacks are invoked synchronously during ghostty_terminal_vt_write().
* Callbacks must not call ghostty_terminal_vt_write() on the same

View File

@@ -223,7 +223,8 @@ test "terminal_new/free" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(t);
@@ -258,7 +259,8 @@ test "format plain" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(t);
@@ -284,7 +286,8 @@ test "format reflects terminal changes" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(t);
@@ -316,7 +319,8 @@ test "format null returns required size" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(t);
@@ -348,7 +352,8 @@ test "format buffer too small" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(t);
@@ -381,7 +386,8 @@ test "format vt" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(t);
@@ -408,7 +414,8 @@ test "format plain with selection" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(t);
@@ -452,7 +459,8 @@ test "format html" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(t);

View File

@@ -205,7 +205,8 @@ test "grid_ref_hyperlink_uri no hyperlink" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(terminal);
@@ -228,7 +229,8 @@ test "grid_ref_hyperlink_uri with hyperlink" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(terminal);

View File

@@ -96,7 +96,8 @@ test "tracked_grid_ref snapshots after terminal scroll" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -128,7 +129,8 @@ test "tracked_grid_ref reports no value after reset" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -154,7 +156,8 @@ test "tracked_grid_ref reports no value after alternate screen reset" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -194,7 +197,8 @@ test "tracked_grid_ref reports no value after terminal free" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
terminal_c.vt_write(terminal, "A", 1);

View File

@@ -257,7 +257,8 @@ test "setopt_from_terminal" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -283,7 +284,8 @@ test "setopt_from_terminal null" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
setopt_from_terminal(null, t);

View File

@@ -659,7 +659,8 @@ test "placement_iterator next on empty storage" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -688,7 +689,8 @@ test "placement_iterator get before next returns invalid" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -719,7 +721,8 @@ test "placement_iterator with transmit and display" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -772,7 +775,8 @@ test "placement_iterator with multiple placements" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -829,7 +833,8 @@ test "placement_iterator_set layer filter" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -919,7 +924,8 @@ test "image_get_handle returns null for missing id" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -940,7 +946,8 @@ test "image_get_handle and image_get with transmitted image" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -990,7 +997,8 @@ test "placement_rect with transmit and display" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -1051,7 +1059,8 @@ test "placement_pixel_size with transmit and display" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -1106,7 +1115,8 @@ test "placement_grid_size with transmit and display" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -1160,7 +1170,8 @@ test "placement_viewport_pos with transmit and display" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -1205,7 +1216,8 @@ test "placement_viewport_pos fully off-screen above" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 5, .max_scrollback = 100 },
80,
5,
));
defer terminal_c.free(t);
try testing.expectEqual(Result.success, terminal_c.resize(t, 80, 5, 10, 20));
@@ -1244,7 +1256,8 @@ test "placement_viewport_pos top off-screen" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 5, .max_scrollback = 100 },
80,
5,
));
defer terminal_c.free(t);
try testing.expectEqual(Result.success, terminal_c.resize(t, 80, 5, 10, 20));
@@ -1287,7 +1300,8 @@ test "placement_viewport_pos bottom off-screen" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 5, .max_scrollback = 0 },
80,
5,
));
defer terminal_c.free(t);
try testing.expectEqual(Result.success, terminal_c.resize(t, 80, 5, 10, 20));
@@ -1327,7 +1341,8 @@ test "placement_viewport_pos top and bottom off-screen" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 5, .max_scrollback = 100 },
80,
5,
));
defer terminal_c.free(t);
try testing.expectEqual(Result.success, terminal_c.resize(t, 80, 5, 10, 20));
@@ -1378,7 +1393,8 @@ test "placement_source_rect defaults to full image" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
try testing.expectEqual(Result.success, terminal_c.resize(t, 80, 24, 10, 20));
@@ -1417,7 +1433,8 @@ test "placement_source_rect with explicit source rect" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
try testing.expectEqual(Result.success, terminal_c.resize(t, 80, 24, 10, 20));
@@ -1461,7 +1478,8 @@ test "placement_source_rect clamps to image bounds" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
try testing.expectEqual(Result.success, terminal_c.resize(t, 80, 24, 10, 20));
@@ -1522,7 +1540,8 @@ test "placement_render_info returns all fields" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
try testing.expectEqual(Result.success, terminal_c.resize(t, 80, 24, 10, 20));
@@ -1561,7 +1580,8 @@ test "placement_render_info off-screen sets viewport_visible false" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 5, .max_scrollback = 100 },
80,
5,
));
defer terminal_c.free(t);
try testing.expectEqual(Result.success, terminal_c.resize(t, 80, 5, 10, 20));
@@ -1610,7 +1630,8 @@ test "image_get_multi success" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
try testing.expectEqual(Result.success, terminal_c.resize(t, 80, 24, 10, 20));
@@ -1664,7 +1685,8 @@ test "placement_get_multi success" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
try testing.expectEqual(Result.success, terminal_c.resize(t, 80, 24, 10, 20));
@@ -1722,7 +1744,8 @@ test "storage generation via get" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -1774,7 +1797,8 @@ test "image generation detects same-sized retransmission" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -1835,7 +1859,8 @@ test "image generation via image_get_multi" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -1871,7 +1896,8 @@ test "image compression and format always report decoded data" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -1917,7 +1943,8 @@ test "generation never recurs across resets and screen switches" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);

View File

@@ -324,7 +324,8 @@ test "setopt_from_terminal" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
@@ -346,7 +347,8 @@ test "setopt_from_terminal null" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 0 },
80,
24,
));
defer terminal_c.free(t);
setopt_from_terminal(null, t);

View File

@@ -827,11 +827,8 @@ test "render: begin/end update" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 10,
.rows = 3,
.max_scrollback = 10_000,
},
10,
3,
));
defer terminal_c.free(terminal);
@@ -952,11 +949,8 @@ test "render: row iterator new/free" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 80,
.rows = 24,
.max_scrollback = 10_000,
},
80,
24,
));
defer terminal_c.free(terminal);
@@ -1008,11 +1002,8 @@ test "render: row get invalid data" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 80,
.rows = 24,
.max_scrollback = 10_000,
},
80,
24,
));
defer terminal_c.free(terminal);
@@ -1047,11 +1038,8 @@ test "render: row set before iteration" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 80,
.rows = 24,
.max_scrollback = 10_000,
},
80,
24,
));
defer terminal_c.free(terminal);
@@ -1081,11 +1069,8 @@ test "render: row get before iteration" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 80,
.rows = 24,
.max_scrollback = 10_000,
},
80,
24,
));
defer terminal_c.free(terminal);
@@ -1115,11 +1100,8 @@ test "render: row get/set dirty" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 80,
.rows = 24,
.max_scrollback = 10_000,
},
80,
24,
));
defer terminal_c.free(terminal);
@@ -1173,11 +1155,8 @@ test "render: row get selection" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 10,
.rows = 3,
.max_scrollback = 10_000,
},
10,
3,
));
defer terminal_c.free(terminal);
@@ -1227,11 +1206,8 @@ test "render: row cells get selected" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 10,
.rows = 3,
.max_scrollback = 10_000,
},
10,
3,
));
defer terminal_c.free(terminal);
@@ -1310,11 +1286,8 @@ test "render: row cells get has_styling" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 10,
.rows = 3,
.max_scrollback = 10_000,
},
10,
3,
));
defer terminal_c.free(terminal);
@@ -1390,7 +1363,8 @@ test "render: row cells get graphemes utf8" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 10, .rows = 3, .max_scrollback = 10_000 },
10,
3,
));
defer terminal_c.free(terminal);
@@ -1447,7 +1421,8 @@ test "render: row cells get graphemes utf8" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 10, .rows = 3, .max_scrollback = 10_000 },
10,
3,
));
defer terminal_c.free(terminal);
@@ -1493,11 +1468,8 @@ test "render: row iterator next" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 80,
.rows = 24,
.max_scrollback = 10_000,
},
80,
24,
));
defer terminal_c.free(terminal);
@@ -1543,11 +1515,8 @@ test "render: update" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 80,
.rows = 24,
.max_scrollback = 10_000,
},
80,
24,
));
defer terminal_c.free(terminal);
@@ -1576,11 +1545,8 @@ test "render: colors get" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 80,
.rows = 24,
.max_scrollback = 10_000,
},
80,
24,
));
defer terminal_c.free(terminal);
@@ -1618,11 +1584,8 @@ test "render: row cells bg_color no background" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 80,
.rows = 24,
.max_scrollback = 10_000,
},
80,
24,
));
defer terminal_c.free(terminal);
@@ -1668,11 +1631,8 @@ test "render: row cells bg_color from style" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 80,
.rows = 24,
.max_scrollback = 10_000,
},
80,
24,
));
defer terminal_c.free(terminal);
@@ -1720,11 +1680,8 @@ test "render: row cells bg_color from content tag" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 80,
.rows = 24,
.max_scrollback = 10_000,
},
80,
24,
));
defer terminal_c.free(terminal);
@@ -1774,11 +1731,8 @@ test "render: row cells fg_color no foreground" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 80,
.rows = 24,
.max_scrollback = 10_000,
},
80,
24,
));
defer terminal_c.free(terminal);
@@ -1824,11 +1778,8 @@ test "render: row cells fg_color from style" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 80,
.rows = 24,
.max_scrollback = 10_000,
},
80,
24,
));
defer terminal_c.free(terminal);
@@ -1876,11 +1827,8 @@ test "render: colors get supports truncated sized struct" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{
.cols = 80,
.rows = 24,
.max_scrollback = 10_000,
},
80,
24,
));
defer terminal_c.free(terminal);
@@ -1911,7 +1859,8 @@ test "render: get_multi success" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(terminal);
@@ -1947,7 +1896,8 @@ test "render: row_get_multi success" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(terminal);
@@ -1990,7 +1940,8 @@ test "render: row_cells_get_multi success" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(terminal);

View File

@@ -397,7 +397,8 @@ test "selection_format_alloc uses active selection" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(t);
@@ -457,7 +458,8 @@ test "selection_format_buf uses provided selection" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(t);
@@ -513,7 +515,8 @@ test "selection_format_alloc returns no_value without active selection" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&t,
.{ .cols = 80, .rows = 24, .max_scrollback = 10_000 },
80,
24,
));
defer terminal_c.free(t);

View File

@@ -752,7 +752,8 @@ test "selection gesture lifecycle and get" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -788,7 +789,8 @@ test "selection gesture get_multi" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -832,7 +834,8 @@ test "selection gesture get_multi returns first failing index" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -944,7 +947,8 @@ test "selection gesture event applies press" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -991,7 +995,8 @@ test "selection gesture event press requires ref" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -1019,7 +1024,8 @@ test "selection gesture event null output still reports no selection" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -1053,7 +1059,8 @@ test "selection gesture event applies release" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -1104,7 +1111,8 @@ test "selection gesture release without ref marks dragged" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -1151,7 +1159,8 @@ test "selection gesture event applies drag" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -1223,7 +1232,8 @@ test "selection gesture drag requires ref and geometry" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -1267,7 +1277,8 @@ test "selection gesture event applies autoscroll tick" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -1350,7 +1361,8 @@ test "selection gesture autoscroll tick requires viewport and geometry" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -1389,7 +1401,8 @@ test "selection gesture event applies deep press" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);
@@ -1444,7 +1457,8 @@ test "selection gesture deep press without active anchor returns no value" {
try testing.expectEqual(Result.success, terminal_c.new(
&lib.alloc.test_allocator,
&terminal,
.{ .cols = 5, .rows = 2, .max_scrollback = 10_000 },
5,
2,
));
defer terminal_c.free(terminal);

File diff suppressed because it is too large Load Diff

View File

@@ -68,7 +68,6 @@ pub const structs: std.StaticStringMap(StructInfo) = structs: {
.{ "GhosttySurfacePosition", StructInfo.init(SurfacePosition) },
.{ "GhosttyStyle", StructInfo.init(style_c.Style) },
.{ "GhosttyStyleColor", StructInfo.init(style_c.Color) },
.{ "GhosttyTerminalOptions", StructInfo.init(terminal.Options) },
.{ "GhosttyTerminalScrollbar", StructInfo.init(terminal.TerminalScrollbar) },
.{ "GhosttyTerminalScrollViewport", StructInfo.init(terminal.ScrollViewport) },
});
@@ -216,7 +215,6 @@ test "json parses" {
// Verify we have all expected structs
try std.testing.expect(root.contains("GhosttyClipboardContent"));
try std.testing.expect(root.contains("GhosttyClipboardWrite"));
try std.testing.expect(root.contains("GhosttyTerminalOptions"));
try std.testing.expect(root.contains("GhosttyFormatterTerminalOptions"));
const clipboard_content = root.get("GhosttyClipboardContent").?.object;
@@ -231,20 +229,7 @@ test "json parses" {
try std.testing.expect(clipboard_write_fields.contains("contents"));
try std.testing.expect(clipboard_write_fields.contains("contents_len"));
// Verify GhosttyTerminalOptions fields
const term_opts = root.get("GhosttyTerminalOptions").?.object;
try std.testing.expect(term_opts.contains("size"));
try std.testing.expect(term_opts.contains("align"));
try std.testing.expect(term_opts.contains("fields"));
const fields = term_opts.get("fields").?.object;
try std.testing.expect(fields.contains("cols"));
try std.testing.expect(fields.contains("rows"));
try std.testing.expect(fields.contains("max_scrollback"));
// Verify field offsets make sense (cols should be at 0)
const cols = fields.get("cols").?.object;
try std.testing.expectEqual(0, cols.get("offset").?.integer);
try std.testing.expect(!root.contains("GhosttyTerminalOptions"));
}
test "struct sizes are non-zero" {