vt: add sized struct pattern and types.h

Add a size field as the first member of formatter option structs
(TerminalOptions, TerminalOptions.Extra, ScreenOptions.Extra) for ABI
compatibility. This allows adding new fields without breaking callers
compiled against older versions of the struct.

Introduce include/ghostty/vt/types.h as the foundational header
containing GhosttyResult and the GHOSTTY_INIT_SIZED macro for
zero-initializing sized structs. Remove the separate result.h header,
moving its contents into types.h.
This commit is contained in:
Mitchell Hashimoto
2026-03-14 14:33:52 -07:00
parent 09d3ebd80d
commit a2d570b51e
11 changed files with 76 additions and 31 deletions

View File

@@ -73,7 +73,7 @@
extern "C" {
#endif
#include <ghostty/vt/result.h>
#include <ghostty/vt/types.h>
#include <ghostty/vt/allocator.h>
#include <ghostty/vt/formatter.h>
#include <ghostty/vt/terminal.h>

View File

@@ -11,7 +11,7 @@
#include <stddef.h>
#include <stdint.h>
#include <ghostty/vt/allocator.h>
#include <ghostty/vt/result.h>
#include <ghostty/vt/types.h>
#include <ghostty/vt/terminal.h>
#ifdef __cplusplus
@@ -53,6 +53,9 @@ typedef enum {
* @ingroup formatter
*/
typedef struct {
/** Size of this struct in bytes. Must be set to sizeof(GhosttyFormatterScreenExtra). */
size_t size;
/** Emit cursor position using CUP (CSI H). */
bool cursor;
@@ -78,6 +81,9 @@ typedef struct {
* @ingroup formatter
*/
typedef struct {
/** Size of this struct in bytes. Must be set to sizeof(GhosttyFormatterTerminalExtra). */
size_t size;
/** Emit the palette using OSC 4 sequences. */
bool palette;
@@ -113,6 +119,9 @@ typedef struct GhosttyFormatter* GhosttyFormatter;
* @ingroup formatter
*/
typedef struct {
/** Size of this struct in bytes. Must be set to sizeof(GhosttyFormatterTerminalOptions). */
size_t size;
/** Output format to emit. */
GhosttyFormatterFormat emit;

View File

@@ -9,7 +9,7 @@
#include <stddef.h>
#include <stdint.h>
#include <ghostty/vt/result.h>
#include <ghostty/vt/types.h>
#include <ghostty/vt/allocator.h>
#include <ghostty/vt/key/event.h>

View File

@@ -10,7 +10,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <ghostty/vt/result.h>
#include <ghostty/vt/types.h>
#include <ghostty/vt/allocator.h>
/**

View File

@@ -10,7 +10,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <ghostty/vt/result.h>
#include <ghostty/vt/types.h>
#include <ghostty/vt/allocator.h>
/**

View File

@@ -1,24 +0,0 @@
/**
* @file result.h
*
* Result codes for libghostty-vt operations.
*/
#ifndef GHOSTTY_VT_RESULT_H
#define GHOSTTY_VT_RESULT_H
/**
* Result codes for libghostty-vt operations.
*/
typedef enum {
/** Operation completed successfully */
GHOSTTY_SUCCESS = 0,
/** Operation failed due to failed allocation */
GHOSTTY_OUT_OF_MEMORY = -1,
/** Operation failed due to invalid value */
GHOSTTY_INVALID_VALUE = -2,
/** Operation failed because the provided buffer was too small */
GHOSTTY_OUT_OF_SPACE = -3,
} GhosttyResult;
#endif /* GHOSTTY_VT_RESULT_H */

View File

@@ -73,7 +73,7 @@
#include <ghostty/vt/allocator.h>
#include <ghostty/vt/color.h>
#include <ghostty/vt/result.h>
#include <ghostty/vt/types.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

View File

@@ -9,7 +9,7 @@
#include <stddef.h>
#include <stdint.h>
#include <ghostty/vt/result.h>
#include <ghostty/vt/types.h>
#include <ghostty/vt/allocator.h>
#ifdef __cplusplus

View File

@@ -0,0 +1,45 @@
/**
* @file types.h
*
* Common types, macros, and utilities for libghostty-vt.
*/
#ifndef GHOSTTY_VT_TYPES_H
#define GHOSTTY_VT_TYPES_H
/**
* Result codes for libghostty-vt operations.
*/
typedef enum {
/** Operation completed successfully */
GHOSTTY_SUCCESS = 0,
/** Operation failed due to failed allocation */
GHOSTTY_OUT_OF_MEMORY = -1,
/** Operation failed due to invalid value */
GHOSTTY_INVALID_VALUE = -2,
/** Operation failed because the provided buffer was too small */
GHOSTTY_OUT_OF_SPACE = -3,
} GhosttyResult;
/**
* Initialize a sized struct to zero and set its size field.
*
* Sized structs use a `size` field as the first member for ABI
* compatibility. This macro zero-initializes the struct and sets the
* size field to `sizeof(type)`, which allows the library to detect
* which version of the struct the caller was compiled against.
*
* @param type The struct type to initialize
* @return A zero-initialized struct with the size field set
*
* Example:
* @code
* GhosttyFormatterTerminalOptions opts = GHOSTTY_INIT_SIZED(GhosttyFormatterTerminalOptions);
* opts.emit = GHOSTTY_FORMATTER_FORMAT_PLAIN;
* opts.trim = true;
* @endcode
*/
#define GHOSTTY_INIT_SIZED(type) \
((type){ .size = sizeof(type) })
#endif /* GHOSTTY_VT_TYPES_H */

View File

@@ -8,3 +8,15 @@
in `include/ghostty/vt.h`.
- In `include/ghostty/vt.h`, always sort the header contents by:
(1) macros, (2) forward declarations, (3) types, (4) functions
## ABI Compatibility
- Prefer opaque pointers for long-lived objects, such as
`GhosttyTerminal`.
- Structs:
- May contain padding bytes if we're confident we'll never grow
beyond a certain size.
- May use the "sized struct" pattern: an `extern struct` with
`size: usize = @sizeOf(Self)` as the first field. In the C header,
callers use `GHOSTTY_INIT_SIZED` from `types.h` to zero-initialize and
set the size.

View File

@@ -27,6 +27,7 @@ pub const Format = formatterpkg.Format;
pub const ScreenOptions = extern struct {
/// C: GhosttyFormatterScreenExtra
pub const Extra = extern struct {
size: usize = @sizeOf(Extra),
cursor: bool,
style: bool,
hyperlink: bool,
@@ -56,6 +57,7 @@ pub const ScreenOptions = extern struct {
/// C: GhosttyFormatterTerminalOptions
pub const TerminalOptions = extern struct {
size: usize = @sizeOf(TerminalOptions),
emit: Format,
unwrap: bool,
trim: bool,
@@ -63,6 +65,7 @@ pub const TerminalOptions = extern struct {
/// C: GhosttyFormatterTerminalExtra
pub const Extra = extern struct {
size: usize = @sizeOf(Extra),
palette: bool,
modes: bool,
scrolling_region: bool,