mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-13 19:15:48 +00:00
vt: add GhosttyCell and GhosttyRow C API with data getters
Add opaque GhosttyCell (uint64_t) and GhosttyRow (uint64_t) types that bitcast to the internal packed Cell and Row structs from page.zig. Each type has a corresponding data enum and getter function following the same pattern as ghostty_terminal_get. ghostty_cell_get supports extracting codepoint, content tag, wide property, has_text, has_styling, style_id, has_hyperlink, protected, and semantic_content. ghostty_row_get supports wrap, wrap_continuation, grapheme, styled, hyperlink, semantic_prompt, kitty_virtual_placeholder, and dirty. The cell and row types and functions live in a new screen.h header, separate from terminal.h, with terminal.h including screen.h for convenience.
This commit is contained in:
@@ -103,6 +103,7 @@ extern "C" {
|
||||
#include <ghostty/vt/modes.h>
|
||||
#include <ghostty/vt/mouse.h>
|
||||
#include <ghostty/vt/paste.h>
|
||||
#include <ghostty/vt/screen.h>
|
||||
#include <ghostty/vt/size_report.h>
|
||||
#include <ghostty/vt/wasm.h>
|
||||
|
||||
|
||||
323
include/ghostty/vt/screen.h
Normal file
323
include/ghostty/vt/screen.h
Normal file
@@ -0,0 +1,323 @@
|
||||
/**
|
||||
* @file screen.h
|
||||
*
|
||||
* Terminal screen cell and row types.
|
||||
*/
|
||||
|
||||
#ifndef GHOSTTY_VT_SCREEN_H
|
||||
#define GHOSTTY_VT_SCREEN_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <ghostty/vt/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup screen Screen
|
||||
*
|
||||
* Terminal screen cell and row types.
|
||||
*
|
||||
* These types represent the contents of a terminal screen. A GhosttyCell
|
||||
* is a single grid cell and a GhosttyRow is a single row. Both are opaque
|
||||
* values whose fields are accessed via ghostty_cell_get() and
|
||||
* ghostty_row_get() respectively.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Opaque cell value.
|
||||
*
|
||||
* Represents a single terminal cell. The internal layout is opaque and
|
||||
* must be queried via ghostty_cell_get(). Obtain cell values from
|
||||
* terminal query APIs.
|
||||
*
|
||||
* @ingroup screen
|
||||
*/
|
||||
typedef uint64_t GhosttyCell;
|
||||
|
||||
/**
|
||||
* Opaque row value.
|
||||
*
|
||||
* Represents a single terminal row. The internal layout is opaque and
|
||||
* must be queried via ghostty_row_get(). Obtain row values from
|
||||
* terminal query APIs.
|
||||
*
|
||||
* @ingroup screen
|
||||
*/
|
||||
typedef uint64_t GhosttyRow;
|
||||
|
||||
/**
|
||||
* Cell content tag.
|
||||
*
|
||||
* Describes what kind of content a cell holds.
|
||||
*
|
||||
* @ingroup screen
|
||||
*/
|
||||
typedef enum {
|
||||
/** A single codepoint (may be zero for empty). */
|
||||
GHOSTTY_CELL_CONTENT_CODEPOINT = 0,
|
||||
|
||||
/** A codepoint that is part of a multi-codepoint grapheme cluster. */
|
||||
GHOSTTY_CELL_CONTENT_CODEPOINT_GRAPHEME = 1,
|
||||
|
||||
/** No text; background color from palette. */
|
||||
GHOSTTY_CELL_CONTENT_BG_COLOR_PALETTE = 2,
|
||||
|
||||
/** No text; background color as RGB. */
|
||||
GHOSTTY_CELL_CONTENT_BG_COLOR_RGB = 3,
|
||||
} GhosttyCellContentTag;
|
||||
|
||||
/**
|
||||
* Cell wide property.
|
||||
*
|
||||
* Describes the width behavior of a cell.
|
||||
*
|
||||
* @ingroup screen
|
||||
*/
|
||||
typedef enum {
|
||||
/** Not a wide character, cell width 1. */
|
||||
GHOSTTY_CELL_WIDE_NARROW = 0,
|
||||
|
||||
/** Wide character, cell width 2. */
|
||||
GHOSTTY_CELL_WIDE_WIDE = 1,
|
||||
|
||||
/** Spacer after wide character. Do not render. */
|
||||
GHOSTTY_CELL_WIDE_SPACER_TAIL = 2,
|
||||
|
||||
/** Spacer at end of soft-wrapped line for a wide character. */
|
||||
GHOSTTY_CELL_WIDE_SPACER_HEAD = 3,
|
||||
} GhosttyCellWide;
|
||||
|
||||
/**
|
||||
* Semantic content type of a cell.
|
||||
*
|
||||
* Set by semantic prompt sequences (OSC 133) to distinguish between
|
||||
* command output, user input, and shell prompt text.
|
||||
*
|
||||
* @ingroup screen
|
||||
*/
|
||||
typedef enum {
|
||||
/** Regular output content, such as command output. */
|
||||
GHOSTTY_CELL_SEMANTIC_OUTPUT = 0,
|
||||
|
||||
/** Content that is part of user input. */
|
||||
GHOSTTY_CELL_SEMANTIC_INPUT = 1,
|
||||
|
||||
/** Content that is part of a shell prompt. */
|
||||
GHOSTTY_CELL_SEMANTIC_PROMPT = 2,
|
||||
} GhosttyCellSemanticContent;
|
||||
|
||||
/**
|
||||
* Cell data types.
|
||||
*
|
||||
* These values specify what type of data to extract from a cell
|
||||
* using `ghostty_cell_get`.
|
||||
*
|
||||
* @ingroup screen
|
||||
*/
|
||||
typedef enum {
|
||||
/** Invalid data type. Never results in any data extraction. */
|
||||
GHOSTTY_CELL_DATA_INVALID = 0,
|
||||
|
||||
/**
|
||||
* The codepoint of the cell (0 if empty or bg-color-only).
|
||||
*
|
||||
* Output type: uint32_t *
|
||||
*/
|
||||
GHOSTTY_CELL_DATA_CODEPOINT = 1,
|
||||
|
||||
/**
|
||||
* The content tag describing what kind of content is in the cell.
|
||||
*
|
||||
* Output type: GhosttyCellContentTag *
|
||||
*/
|
||||
GHOSTTY_CELL_DATA_CONTENT_TAG = 2,
|
||||
|
||||
/**
|
||||
* The wide property of the cell.
|
||||
*
|
||||
* Output type: GhosttyCellWide *
|
||||
*/
|
||||
GHOSTTY_CELL_DATA_WIDE = 3,
|
||||
|
||||
/**
|
||||
* Whether the cell has text to render.
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_CELL_DATA_HAS_TEXT = 4,
|
||||
|
||||
/**
|
||||
* Whether the cell has non-default styling.
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_CELL_DATA_HAS_STYLING = 5,
|
||||
|
||||
/**
|
||||
* The style ID for the cell (for use with style lookups).
|
||||
*
|
||||
* Output type: uint16_t *
|
||||
*/
|
||||
GHOSTTY_CELL_DATA_STYLE_ID = 6,
|
||||
|
||||
/**
|
||||
* Whether the cell has a hyperlink.
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_CELL_DATA_HAS_HYPERLINK = 7,
|
||||
|
||||
/**
|
||||
* Whether the cell is protected.
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_CELL_DATA_PROTECTED = 8,
|
||||
|
||||
/**
|
||||
* The semantic content type of the cell (from OSC 133).
|
||||
*
|
||||
* Output type: GhosttyCellSemanticContent *
|
||||
*/
|
||||
GHOSTTY_CELL_DATA_SEMANTIC_CONTENT = 9,
|
||||
} GhosttyCellData;
|
||||
|
||||
/**
|
||||
* Row semantic prompt state.
|
||||
*
|
||||
* Indicates whether any cells in a row are part of a shell prompt,
|
||||
* as reported by OSC 133 sequences.
|
||||
*
|
||||
* @ingroup screen
|
||||
*/
|
||||
typedef enum {
|
||||
/** No prompt cells in this row. */
|
||||
GHOSTTY_ROW_SEMANTIC_NONE = 0,
|
||||
|
||||
/** Prompt cells exist and this is a primary prompt line. */
|
||||
GHOSTTY_ROW_SEMANTIC_PROMPT = 1,
|
||||
|
||||
/** Prompt cells exist and this is a continuation line. */
|
||||
GHOSTTY_ROW_SEMANTIC_PROMPT_CONTINUATION = 2,
|
||||
} GhosttyRowSemanticPrompt;
|
||||
|
||||
/**
|
||||
* Row data types.
|
||||
*
|
||||
* These values specify what type of data to extract from a row
|
||||
* using `ghostty_row_get`.
|
||||
*
|
||||
* @ingroup screen
|
||||
*/
|
||||
typedef enum {
|
||||
/** Invalid data type. Never results in any data extraction. */
|
||||
GHOSTTY_ROW_DATA_INVALID = 0,
|
||||
|
||||
/**
|
||||
* Whether this row is soft-wrapped.
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_ROW_DATA_WRAP = 1,
|
||||
|
||||
/**
|
||||
* Whether this row is a continuation of a soft-wrapped row.
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_ROW_DATA_WRAP_CONTINUATION = 2,
|
||||
|
||||
/**
|
||||
* Whether any cells in this row have grapheme clusters.
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_ROW_DATA_GRAPHEME = 3,
|
||||
|
||||
/**
|
||||
* Whether any cells in this row have styling (may have false positives).
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_ROW_DATA_STYLED = 4,
|
||||
|
||||
/**
|
||||
* Whether any cells in this row have hyperlinks (may have false positives).
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_ROW_DATA_HYPERLINK = 5,
|
||||
|
||||
/**
|
||||
* The semantic prompt state of this row.
|
||||
*
|
||||
* Output type: GhosttyRowSemanticPrompt *
|
||||
*/
|
||||
GHOSTTY_ROW_DATA_SEMANTIC_PROMPT = 6,
|
||||
|
||||
/**
|
||||
* Whether this row contains a Kitty virtual placeholder.
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_ROW_DATA_KITTY_VIRTUAL_PLACEHOLDER = 7,
|
||||
|
||||
/**
|
||||
* Whether this row is dirty and requires a redraw.
|
||||
*
|
||||
* Output type: bool *
|
||||
*/
|
||||
GHOSTTY_ROW_DATA_DIRTY = 8,
|
||||
} GhosttyRowData;
|
||||
|
||||
/**
|
||||
* Get data from a cell.
|
||||
*
|
||||
* Extracts typed data from the given cell based on the specified
|
||||
* data type. The output pointer must be of the appropriate type for the
|
||||
* requested data kind. Valid data types and output types are documented
|
||||
* in the `GhosttyCellData` enum.
|
||||
*
|
||||
* @param cell The cell value
|
||||
* @param data The type of data to extract
|
||||
* @param out Pointer to store the extracted data (type depends on data parameter)
|
||||
* @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the
|
||||
* data type is invalid
|
||||
*
|
||||
* @ingroup screen
|
||||
*/
|
||||
GhosttyResult ghostty_cell_get(GhosttyCell cell,
|
||||
GhosttyCellData data,
|
||||
void *out);
|
||||
|
||||
/**
|
||||
* Get data from a row.
|
||||
*
|
||||
* Extracts typed data from the given row based on the specified
|
||||
* data type. The output pointer must be of the appropriate type for the
|
||||
* requested data kind. Valid data types and output types are documented
|
||||
* in the `GhosttyRowData` enum.
|
||||
*
|
||||
* @param row The row value
|
||||
* @param data The type of data to extract
|
||||
* @param out Pointer to store the extracted data (type depends on data parameter)
|
||||
* @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the
|
||||
* data type is invalid
|
||||
*
|
||||
* @ingroup screen
|
||||
*/
|
||||
GhosttyResult ghostty_row_get(GhosttyRow row,
|
||||
GhosttyRowData data,
|
||||
void *out);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GHOSTTY_VT_SCREEN_H */
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <ghostty/vt/types.h>
|
||||
#include <ghostty/vt/allocator.h>
|
||||
#include <ghostty/vt/modes.h>
|
||||
#include <ghostty/vt/screen.h>
|
||||
#include <ghostty/vt/style.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -171,6 +171,8 @@ comptime {
|
||||
@export(&c.size_report_encode, .{ .name = "ghostty_size_report_encode" });
|
||||
@export(&c.style_default, .{ .name = "ghostty_style_default" });
|
||||
@export(&c.style_is_default, .{ .name = "ghostty_style_is_default" });
|
||||
@export(&c.cell_get, .{ .name = "ghostty_cell_get" });
|
||||
@export(&c.row_get, .{ .name = "ghostty_row_get" });
|
||||
@export(&c.color_rgb_get, .{ .name = "ghostty_color_rgb_get" });
|
||||
@export(&c.sgr_new, .{ .name = "ghostty_sgr_new" });
|
||||
@export(&c.sgr_free, .{ .name = "ghostty_sgr_free" });
|
||||
|
||||
158
src/terminal/c/cell.zig
Normal file
158
src/terminal/c/cell.zig
Normal file
@@ -0,0 +1,158 @@
|
||||
const std = @import("std");
|
||||
const testing = std.testing;
|
||||
const page = @import("../page.zig");
|
||||
const Cell = page.Cell;
|
||||
const style_c = @import("style.zig");
|
||||
const Result = @import("result.zig").Result;
|
||||
|
||||
/// C: GhosttyCell
|
||||
pub const CCell = u64;
|
||||
|
||||
/// C: GhosttyCellContentTag
|
||||
pub const ContentTag = enum(c_int) {
|
||||
codepoint = 0,
|
||||
codepoint_grapheme = 1,
|
||||
bg_color_palette = 2,
|
||||
bg_color_rgb = 3,
|
||||
};
|
||||
|
||||
/// C: GhosttyCellWide
|
||||
pub const Wide = enum(c_int) {
|
||||
narrow = 0,
|
||||
wide = 1,
|
||||
spacer_tail = 2,
|
||||
spacer_head = 3,
|
||||
};
|
||||
|
||||
/// C: GhosttyCellSemanticContent
|
||||
pub const SemanticContent = enum(c_int) {
|
||||
output = 0,
|
||||
input = 1,
|
||||
prompt = 2,
|
||||
};
|
||||
|
||||
/// C: GhosttyCellData
|
||||
pub const CellData = enum(c_int) {
|
||||
invalid = 0,
|
||||
|
||||
/// The codepoint of the cell (0 if empty or bg-color-only).
|
||||
/// Output type: uint32_t * (stored as u21, zero-extended)
|
||||
codepoint = 1,
|
||||
|
||||
/// The content tag describing what kind of content is in the cell.
|
||||
/// Output type: GhosttyCellContentTag *
|
||||
content_tag = 2,
|
||||
|
||||
/// The wide property of the cell.
|
||||
/// Output type: GhosttyCellWide *
|
||||
wide = 3,
|
||||
|
||||
/// Whether the cell has text to render.
|
||||
/// Output type: bool *
|
||||
has_text = 4,
|
||||
|
||||
/// Whether the cell has styling (non-default style).
|
||||
/// Output type: bool *
|
||||
has_styling = 5,
|
||||
|
||||
/// The style ID for the cell (for use with style lookups).
|
||||
/// Output type: uint16_t *
|
||||
style_id = 6,
|
||||
|
||||
/// Whether the cell has a hyperlink.
|
||||
/// Output type: bool *
|
||||
has_hyperlink = 7,
|
||||
|
||||
/// Whether the cell is protected.
|
||||
/// Output type: bool *
|
||||
protected = 8,
|
||||
|
||||
/// The semantic content type of the cell (from OSC 133).
|
||||
/// Output type: GhosttyCellSemanticContent *
|
||||
semantic_content = 9,
|
||||
|
||||
/// Output type expected for querying the data of the given kind.
|
||||
pub fn OutType(comptime self: CellData) type {
|
||||
return switch (self) {
|
||||
.invalid => void,
|
||||
.codepoint => u32,
|
||||
.content_tag => ContentTag,
|
||||
.wide => Wide,
|
||||
.has_text, .has_styling, .has_hyperlink, .protected => bool,
|
||||
.style_id => u16,
|
||||
.semantic_content => SemanticContent,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn get(
|
||||
cell_: CCell,
|
||||
data: CellData,
|
||||
out: ?*anyopaque,
|
||||
) callconv(.c) Result {
|
||||
if (comptime std.debug.runtime_safety) {
|
||||
_ = std.meta.intToEnum(CellData, @intFromEnum(data)) catch {
|
||||
return .invalid_value;
|
||||
};
|
||||
}
|
||||
|
||||
return switch (data) {
|
||||
inline else => |comptime_data| getTyped(
|
||||
cell_,
|
||||
comptime_data,
|
||||
@ptrCast(@alignCast(out)),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
fn getTyped(
|
||||
cell_: CCell,
|
||||
comptime data: CellData,
|
||||
out: *data.OutType(),
|
||||
) Result {
|
||||
const cell: Cell = @bitCast(cell_);
|
||||
switch (data) {
|
||||
.invalid => return .invalid_value,
|
||||
.codepoint => out.* = @intCast(cell.codepoint()),
|
||||
.content_tag => out.* = @enumFromInt(@intFromEnum(cell.content_tag)),
|
||||
.wide => out.* = @enumFromInt(@intFromEnum(cell.wide)),
|
||||
.has_text => out.* = cell.hasText(),
|
||||
.has_styling => out.* = cell.hasStyling(),
|
||||
.style_id => out.* = cell.style_id,
|
||||
.has_hyperlink => out.* = cell.hyperlink,
|
||||
.protected => out.* = cell.protected,
|
||||
.semantic_content => out.* = @enumFromInt(@intFromEnum(cell.semantic_content)),
|
||||
}
|
||||
|
||||
return .success;
|
||||
}
|
||||
|
||||
test "get codepoint" {
|
||||
const cell: CCell = @bitCast(Cell.init('A'));
|
||||
var cp: u32 = 0;
|
||||
try testing.expectEqual(Result.success, get(cell, .codepoint, @ptrCast(&cp)));
|
||||
try testing.expectEqual(@as(u32, 'A'), cp);
|
||||
}
|
||||
|
||||
test "get has_text" {
|
||||
const cell: CCell = @bitCast(Cell.init('A'));
|
||||
var has: bool = false;
|
||||
try testing.expectEqual(Result.success, get(cell, .has_text, @ptrCast(&has)));
|
||||
try testing.expect(has);
|
||||
}
|
||||
|
||||
test "get empty cell" {
|
||||
const cell: CCell = @bitCast(Cell.init(0));
|
||||
var has: bool = true;
|
||||
try testing.expectEqual(Result.success, get(cell, .has_text, @ptrCast(&has)));
|
||||
try testing.expect(!has);
|
||||
}
|
||||
|
||||
test "get wide" {
|
||||
var zig_cell = Cell.init('A');
|
||||
zig_cell.wide = .wide;
|
||||
const cell: CCell = @bitCast(zig_cell);
|
||||
var w: Wide = .narrow;
|
||||
try testing.expectEqual(Result.success, get(cell, .wide, @ptrCast(&w)));
|
||||
try testing.expectEqual(Wide.wide, w);
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
pub const cell = @import("cell.zig");
|
||||
pub const color = @import("color.zig");
|
||||
pub const focus = @import("focus.zig");
|
||||
pub const formatter = @import("formatter.zig");
|
||||
@@ -8,6 +9,7 @@ pub const key_encode = @import("key_encode.zig");
|
||||
pub const mouse_event = @import("mouse_event.zig");
|
||||
pub const mouse_encode = @import("mouse_encode.zig");
|
||||
pub const paste = @import("paste.zig");
|
||||
pub const row = @import("row.zig");
|
||||
pub const sgr = @import("sgr.zig");
|
||||
pub const size_report = @import("size_report.zig");
|
||||
pub const style = @import("style.zig");
|
||||
@@ -91,6 +93,10 @@ pub const paste_is_safe = paste.is_safe;
|
||||
|
||||
pub const size_report_encode = size_report.encode;
|
||||
|
||||
pub const cell_get = cell.get;
|
||||
|
||||
pub const row_get = row.get;
|
||||
|
||||
pub const style_default = style.default_style;
|
||||
pub const style_is_default = style.style_is_default;
|
||||
|
||||
@@ -105,7 +111,9 @@ pub const terminal_mode_set = terminal.mode_set;
|
||||
pub const terminal_get = terminal.get;
|
||||
|
||||
test {
|
||||
_ = cell;
|
||||
_ = color;
|
||||
_ = row;
|
||||
_ = focus;
|
||||
_ = formatter;
|
||||
_ = modes;
|
||||
|
||||
130
src/terminal/c/row.zig
Normal file
130
src/terminal/c/row.zig
Normal file
@@ -0,0 +1,130 @@
|
||||
const std = @import("std");
|
||||
const testing = std.testing;
|
||||
const page = @import("../page.zig");
|
||||
const Row = page.Row;
|
||||
const Result = @import("result.zig").Result;
|
||||
|
||||
/// C: GhosttyRow
|
||||
pub const CRow = u64;
|
||||
|
||||
/// C: GhosttyRowSemanticPrompt
|
||||
pub const SemanticPrompt = enum(c_int) {
|
||||
none = 0,
|
||||
prompt = 1,
|
||||
prompt_continuation = 2,
|
||||
};
|
||||
|
||||
/// C: GhosttyRowData
|
||||
pub const RowData = enum(c_int) {
|
||||
invalid = 0,
|
||||
|
||||
/// Whether this row is soft-wrapped.
|
||||
/// Output type: bool *
|
||||
wrap = 1,
|
||||
|
||||
/// Whether this row is a continuation of a soft-wrapped row.
|
||||
/// Output type: bool *
|
||||
wrap_continuation = 2,
|
||||
|
||||
/// Whether any cells in this row have grapheme clusters.
|
||||
/// Output type: bool *
|
||||
grapheme = 3,
|
||||
|
||||
/// Whether any cells in this row have styling (may have false positives).
|
||||
/// Output type: bool *
|
||||
styled = 4,
|
||||
|
||||
/// Whether any cells in this row have hyperlinks (may have false positives).
|
||||
/// Output type: bool *
|
||||
hyperlink = 5,
|
||||
|
||||
/// The semantic prompt state of this row.
|
||||
/// Output type: GhosttyRowSemanticPrompt *
|
||||
semantic_prompt = 6,
|
||||
|
||||
/// Whether this row contains a Kitty virtual placeholder.
|
||||
/// Output type: bool *
|
||||
kitty_virtual_placeholder = 7,
|
||||
|
||||
/// Whether this row is dirty and requires a redraw.
|
||||
/// Output type: bool *
|
||||
dirty = 8,
|
||||
|
||||
/// Output type expected for querying the data of the given kind.
|
||||
pub fn OutType(comptime self: RowData) type {
|
||||
return switch (self) {
|
||||
.invalid => void,
|
||||
.wrap, .wrap_continuation, .grapheme, .styled, .hyperlink => bool,
|
||||
.kitty_virtual_placeholder, .dirty => bool,
|
||||
.semantic_prompt => SemanticPrompt,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn get(
|
||||
row_: CRow,
|
||||
data: RowData,
|
||||
out: ?*anyopaque,
|
||||
) callconv(.c) Result {
|
||||
if (comptime std.debug.runtime_safety) {
|
||||
_ = std.meta.intToEnum(RowData, @intFromEnum(data)) catch {
|
||||
return .invalid_value;
|
||||
};
|
||||
}
|
||||
|
||||
return switch (data) {
|
||||
inline else => |comptime_data| getTyped(
|
||||
row_,
|
||||
comptime_data,
|
||||
@ptrCast(@alignCast(out)),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
fn getTyped(
|
||||
row_: CRow,
|
||||
comptime data: RowData,
|
||||
out: *data.OutType(),
|
||||
) Result {
|
||||
const row: Row = @bitCast(row_);
|
||||
switch (data) {
|
||||
.invalid => return .invalid_value,
|
||||
.wrap => out.* = row.wrap,
|
||||
.wrap_continuation => out.* = row.wrap_continuation,
|
||||
.grapheme => out.* = row.grapheme,
|
||||
.styled => out.* = row.styled,
|
||||
.hyperlink => out.* = row.hyperlink,
|
||||
.semantic_prompt => out.* = @enumFromInt(@intFromEnum(row.semantic_prompt)),
|
||||
.kitty_virtual_placeholder => out.* = row.kitty_virtual_placeholder,
|
||||
.dirty => out.* = row.dirty,
|
||||
}
|
||||
|
||||
return .success;
|
||||
}
|
||||
|
||||
test "get wrap" {
|
||||
var zig_row: Row = @bitCast(@as(u64, 0));
|
||||
zig_row.wrap = true;
|
||||
const row: CRow = @bitCast(zig_row);
|
||||
var wrap: bool = false;
|
||||
try testing.expectEqual(Result.success, get(row, .wrap, @ptrCast(&wrap)));
|
||||
try testing.expect(wrap);
|
||||
}
|
||||
|
||||
test "get semantic_prompt" {
|
||||
var zig_row: Row = @bitCast(@as(u64, 0));
|
||||
zig_row.semantic_prompt = .prompt;
|
||||
const row: CRow = @bitCast(zig_row);
|
||||
var sp: SemanticPrompt = .none;
|
||||
try testing.expectEqual(Result.success, get(row, .semantic_prompt, @ptrCast(&sp)));
|
||||
try testing.expectEqual(SemanticPrompt.prompt, sp);
|
||||
}
|
||||
|
||||
test "get dirty" {
|
||||
var zig_row: Row = @bitCast(@as(u64, 0));
|
||||
zig_row.dirty = true;
|
||||
const row: CRow = @bitCast(zig_row);
|
||||
var dirty: bool = false;
|
||||
try testing.expectEqual(Result.success, get(row, .dirty, @ptrCast(&dirty)));
|
||||
try testing.expect(dirty);
|
||||
}
|
||||
Reference in New Issue
Block a user