@adhdev/ghostty-vt-node 0.7.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CMakeLists.txt ADDED
@@ -0,0 +1,77 @@
1
+ cmake_minimum_required(VERSION 3.20)
2
+ project(ghostty_vt_node LANGUAGES C CXX)
3
+
4
+ set(CMAKE_CXX_STANDARD 17)
5
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
6
+ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
7
+
8
+ include(FetchContent)
9
+
10
+ execute_process(
11
+ COMMAND node -p "require('node-addon-api').include"
12
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
13
+ OUTPUT_VARIABLE NODE_ADDON_API_DIR
14
+ OUTPUT_STRIP_TRAILING_WHITESPACE
15
+ )
16
+ string(REPLACE "\"" "" NODE_ADDON_API_DIR "${NODE_ADDON_API_DIR}")
17
+
18
+ set(GHOSTTY_GIT_TAG "d4a38c8661453026bd1b1bb022ba2c37b347adce" CACHE STRING "Ghostty git revision for libghostty-vt")
19
+
20
+ if(DEFINED ENV{ZIG_EXECUTABLE} AND NOT DEFINED ZIG_EXECUTABLE)
21
+ set(ZIG_EXECUTABLE "$ENV{ZIG_EXECUTABLE}" CACHE FILEPATH "Path to zig executable")
22
+ endif()
23
+
24
+ FetchContent_Declare(ghostty
25
+ GIT_REPOSITORY https://github.com/ghostty-org/ghostty.git
26
+ GIT_TAG ${GHOSTTY_GIT_TAG}
27
+ )
28
+ FetchContent_MakeAvailable(ghostty)
29
+
30
+ add_library(${PROJECT_NAME} SHARED
31
+ src/addon.cc
32
+ src/ghostty_bridge.c
33
+ )
34
+
35
+ set(GHOSTTY_VT_RUNTIME_ALIAS "${CMAKE_SHARED_LIBRARY_PREFIX}ghostty-vt${CMAKE_SHARED_LIBRARY_SUFFIX}")
36
+
37
+ target_include_directories(${PROJECT_NAME} PRIVATE
38
+ ${CMAKE_JS_INC}
39
+ ${NODE_ADDON_API_DIR}
40
+ )
41
+
42
+ target_compile_definitions(${PROJECT_NAME} PRIVATE
43
+ NAPI_DISABLE_CPP_EXCEPTIONS
44
+ GHOSTTY_STATIC
45
+ )
46
+
47
+ target_link_libraries(${PROJECT_NAME} PRIVATE
48
+ ${CMAKE_JS_LIB}
49
+ ghostty-vt
50
+ )
51
+
52
+ set_target_properties(${PROJECT_NAME} PROPERTIES
53
+ PREFIX ""
54
+ SUFFIX ".node"
55
+ )
56
+
57
+ if(APPLE)
58
+ set_target_properties(${PROJECT_NAME} PROPERTIES
59
+ BUILD_RPATH "@loader_path"
60
+ INSTALL_RPATH "@loader_path"
61
+ )
62
+ target_link_options(${PROJECT_NAME} PRIVATE "-undefined dynamic_lookup")
63
+ elseif(UNIX)
64
+ set_target_properties(${PROJECT_NAME} PROPERTIES
65
+ BUILD_RPATH "$ORIGIN"
66
+ INSTALL_RPATH "$ORIGIN"
67
+ )
68
+ endif()
69
+
70
+ add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
71
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
72
+ $<TARGET_FILE:ghostty-vt>
73
+ $<TARGET_FILE_DIR:${PROJECT_NAME}>/$<TARGET_FILE_NAME:ghostty-vt>
74
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
75
+ $<TARGET_FILE:ghostty-vt>
76
+ $<TARGET_FILE_DIR:${PROJECT_NAME}>/${GHOSTTY_VT_RUNTIME_ALIAS}
77
+ )
package/index.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ export type GhosttyTerminalOptions = {
2
+ cols: number;
3
+ rows: number;
4
+ scrollback: number;
5
+ };
6
+
7
+ export type GhosttyPlainTextFormatOptions = {
8
+ trim?: boolean;
9
+ };
10
+
11
+ export interface GhosttyTerminalHandle {
12
+ write(data: string | Uint8Array): void;
13
+ resize(cols: number, rows: number): void;
14
+ formatPlainText(options?: GhosttyPlainTextFormatOptions): string;
15
+ dispose(): void;
16
+ }
17
+
18
+ export function createTerminal(options: GhosttyTerminalOptions): GhosttyTerminalHandle;
package/index.js ADDED
@@ -0,0 +1,34 @@
1
+ const path = require('node:path');
2
+
3
+ function getTriplet() {
4
+ return `${process.platform}-${process.arch}-node${process.versions.modules}`;
5
+ }
6
+
7
+ function loadBinding() {
8
+ const triplet = getTriplet();
9
+ const explicitPrebuiltDir = process.env.ADHDEV_GHOSTTY_VT_PREBUILT_DIR
10
+ ? path.resolve(process.env.ADHDEV_GHOSTTY_VT_PREBUILT_DIR)
11
+ : null;
12
+ const candidates = [
13
+ explicitPrebuiltDir ? path.join(explicitPrebuiltDir, triplet, 'ghostty_vt_node.node') : null,
14
+ explicitPrebuiltDir ? path.join(explicitPrebuiltDir, 'ghostty_vt_node.node') : null,
15
+ path.join(__dirname, 'prebuilt', triplet, 'ghostty_vt_node.node'),
16
+ path.join(__dirname, 'build', 'Release', 'ghostty_vt_node.node'),
17
+ path.join(__dirname, 'build', 'Debug', 'ghostty_vt_node.node'),
18
+ ].filter(Boolean);
19
+
20
+ const errors = [];
21
+ for (const candidate of candidates) {
22
+ try {
23
+ return require(candidate);
24
+ } catch (error) {
25
+ errors.push(`${candidate}: ${error && error.message ? error.message : String(error)}`);
26
+ }
27
+ }
28
+
29
+ throw new Error(
30
+ `Unable to load @adhdev/ghostty-vt-node native binding for ${triplet}. Provide a prebuilt via ADHDEV_GHOSTTY_VT_PREBUILT_DIR or build it with "npm run build -w packages/ghostty-vt-node". ${errors.join(' | ')}`,
31
+ );
32
+ }
33
+
34
+ module.exports = loadBinding();
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@adhdev/ghostty-vt-node",
3
+ "version": "0.7.31",
4
+ "description": "Native Node binding for libghostty-vt",
5
+ "main": "index.js",
6
+ "types": "index.d.ts",
7
+ "files": [
8
+ "index.js",
9
+ "index.d.ts",
10
+ "prebuilt",
11
+ "scripts",
12
+ "CMakeLists.txt",
13
+ "src"
14
+ ],
15
+ "scripts": {
16
+ "build": "node ./scripts/build-or-use-prebuilt.mjs",
17
+ "rebuild": "cmake-js rebuild",
18
+ "clean": "cmake-js clean"
19
+ },
20
+ "author": "vilmire",
21
+ "dependencies": {
22
+ "node-addon-api": "^8.7.0"
23
+ },
24
+ "devDependencies": {
25
+ "cmake-js": "^8.0.0"
26
+ },
27
+ "license": "AGPL-3.0-or-later",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "https://github.com/vilmire/adhdev.git",
31
+ "directory": "packages/ghostty-vt-node"
32
+ },
33
+ "homepage": "https://github.com/vilmire/adhdev#readme"
34
+ }
@@ -0,0 +1,50 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const scriptDir = path.dirname(fileURLToPath(import.meta.url));
7
+ const packageDir = path.resolve(scriptDir, '..');
8
+ const outputDir = path.join(packageDir, 'build', 'Release');
9
+ const outputFile = path.join(outputDir, 'ghostty_vt_node.node');
10
+ const triplet = `${process.platform}-${process.arch}-node${process.versions.modules}`;
11
+
12
+ function candidatePrebuiltPaths() {
13
+ const candidates = [];
14
+ const explicitDir = process.env.ADHDEV_GHOSTTY_VT_PREBUILT_DIR?.trim();
15
+ if (explicitDir) {
16
+ candidates.push(path.join(explicitDir, triplet, 'ghostty_vt_node.node'));
17
+ candidates.push(path.join(explicitDir, 'ghostty_vt_node.node'));
18
+ }
19
+ candidates.push(path.join(packageDir, 'prebuilt', triplet, 'ghostty_vt_node.node'));
20
+ return candidates;
21
+ }
22
+
23
+ function installPrebuiltIfPresent() {
24
+ for (const candidate of candidatePrebuiltPaths()) {
25
+ if (!fs.existsSync(candidate)) continue;
26
+ fs.mkdirSync(outputDir, { recursive: true });
27
+ fs.copyFileSync(candidate, outputFile);
28
+ console.log(`[ghostty-vt-node] using prebuilt native binding from ${candidate}`);
29
+ return true;
30
+ }
31
+ return false;
32
+ }
33
+
34
+ if (!installPrebuiltIfPresent() && process.env.ADHDEV_SKIP_GHOSTTY_VT_BUILD === '1') {
35
+ console.log(`[ghostty-vt-node] skipping native build for ${triplet} (ADHDEV_SKIP_GHOSTTY_VT_BUILD=1)`);
36
+ process.exit(0);
37
+ }
38
+
39
+ if (installPrebuiltIfPresent()) {
40
+ process.exit(0);
41
+ }
42
+
43
+ const npx = process.platform === 'win32' ? 'npx.cmd' : 'npx';
44
+ const result = spawnSync(npx, ['cmake-js', 'compile'], {
45
+ cwd: packageDir,
46
+ env: process.env,
47
+ stdio: 'inherit',
48
+ });
49
+
50
+ process.exit(result.status ?? 1);
package/src/addon.cc ADDED
@@ -0,0 +1,170 @@
1
+ #include <algorithm>
2
+ #include <string>
3
+
4
+ #include <napi.h>
5
+
6
+ #include "ghostty_bridge.h"
7
+
8
+ namespace {
9
+
10
+ struct TerminalBindingState {
11
+ AdhdevGhosttyTerminal* terminal = nullptr;
12
+ };
13
+
14
+ std::string BuildGhosttyErrorMessage(const char* context, int result) {
15
+ return std::string(context) + ": " + adhdev_ghostty_result_message(result);
16
+ }
17
+
18
+ void ThrowGhosttyError(Napi::Env env, const char* context, int result) {
19
+ Napi::Error::New(env, BuildGhosttyErrorMessage(context, result)).ThrowAsJavaScriptException();
20
+ }
21
+
22
+ TerminalBindingState* GetState(const Napi::CallbackInfo& info) {
23
+ if (!info.Data()) {
24
+ Napi::Error::New(info.Env(), "missing native terminal state").ThrowAsJavaScriptException();
25
+ return nullptr;
26
+ }
27
+ return static_cast<TerminalBindingState*>(info.Data());
28
+ }
29
+
30
+ bool EnsureOpen(Napi::Env env, TerminalBindingState* state) {
31
+ if (!state || !state->terminal) {
32
+ Napi::Error::New(env, "ghostty terminal already disposed").ThrowAsJavaScriptException();
33
+ return false;
34
+ }
35
+ return true;
36
+ }
37
+
38
+ void FinalizeState(Napi::Env, TerminalBindingState* state) {
39
+ if (!state) return;
40
+ if (state->terminal) {
41
+ adhdev_ghostty_terminal_destroy(state->terminal);
42
+ state->terminal = nullptr;
43
+ }
44
+ delete state;
45
+ }
46
+
47
+ Napi::Value Write(const Napi::CallbackInfo& info) {
48
+ Napi::Env env = info.Env();
49
+ TerminalBindingState* state = GetState(info);
50
+ if (!EnsureOpen(env, state)) return env.Undefined();
51
+ if (info.Length() < 1) return env.Undefined();
52
+
53
+ int result = ADHDEV_GHOSTTY_INVALID_VALUE;
54
+ if (info[0].IsBuffer()) {
55
+ Napi::Buffer<uint8_t> buffer = info[0].As<Napi::Buffer<uint8_t>>();
56
+ result = adhdev_ghostty_terminal_write(state->terminal, buffer.Data(), buffer.Length());
57
+ } else if (info[0].IsString()) {
58
+ std::string text = info[0].As<Napi::String>().Utf8Value();
59
+ result = adhdev_ghostty_terminal_write(
60
+ state->terminal,
61
+ reinterpret_cast<const uint8_t*>(text.data()),
62
+ text.size());
63
+ } else {
64
+ Napi::TypeError::New(env, "write expects a string or Uint8Array buffer").ThrowAsJavaScriptException();
65
+ return env.Undefined();
66
+ }
67
+
68
+ if (result != ADHDEV_GHOSTTY_SUCCESS) {
69
+ ThrowGhosttyError(env, "adhdev_ghostty_terminal_write", result);
70
+ }
71
+ return env.Undefined();
72
+ }
73
+
74
+ Napi::Value Resize(const Napi::CallbackInfo& info) {
75
+ Napi::Env env = info.Env();
76
+ TerminalBindingState* state = GetState(info);
77
+ if (!EnsureOpen(env, state)) return env.Undefined();
78
+ if (info.Length() < 2 || !info[0].IsNumber() || !info[1].IsNumber()) {
79
+ Napi::TypeError::New(env, "resize expects cols and rows").ThrowAsJavaScriptException();
80
+ return env.Undefined();
81
+ }
82
+
83
+ const uint16_t cols = static_cast<uint16_t>(std::max(1, info[0].As<Napi::Number>().Int32Value()));
84
+ const uint16_t rows = static_cast<uint16_t>(std::max(1, info[1].As<Napi::Number>().Int32Value()));
85
+ const int result = adhdev_ghostty_terminal_resize(state->terminal, cols, rows);
86
+ if (result != ADHDEV_GHOSTTY_SUCCESS) {
87
+ ThrowGhosttyError(env, "adhdev_ghostty_terminal_resize", result);
88
+ }
89
+ return env.Undefined();
90
+ }
91
+
92
+ Napi::Value FormatPlainText(const Napi::CallbackInfo& info) {
93
+ Napi::Env env = info.Env();
94
+ TerminalBindingState* state = GetState(info);
95
+ if (!EnsureOpen(env, state)) return env.Null();
96
+
97
+ bool trim = false;
98
+ if (info.Length() >= 1 && info[0].IsObject()) {
99
+ Napi::Object options = info[0].As<Napi::Object>();
100
+ if (options.Has("trim")) {
101
+ trim = options.Get("trim").ToBoolean().Value();
102
+ }
103
+ }
104
+
105
+ char* text = nullptr;
106
+ size_t text_len = 0;
107
+ const int result = adhdev_ghostty_terminal_format_plain_text(
108
+ state->terminal,
109
+ trim ? 1 : 0,
110
+ &text,
111
+ &text_len);
112
+ if (result != ADHDEV_GHOSTTY_SUCCESS) {
113
+ ThrowGhosttyError(env, "adhdev_ghostty_terminal_format_plain_text", result);
114
+ return env.Null();
115
+ }
116
+
117
+ std::string output(text, text_len);
118
+ adhdev_ghostty_terminal_free_text(text, text_len);
119
+ return Napi::String::New(env, output);
120
+ }
121
+
122
+ Napi::Value Dispose(const Napi::CallbackInfo& info) {
123
+ TerminalBindingState* state = GetState(info);
124
+ if (state && state->terminal) {
125
+ adhdev_ghostty_terminal_destroy(state->terminal);
126
+ state->terminal = nullptr;
127
+ }
128
+ return info.Env().Undefined();
129
+ }
130
+
131
+ Napi::Value CreateTerminal(const Napi::CallbackInfo& info) {
132
+ Napi::Env env = info.Env();
133
+ if (info.Length() < 1 || !info[0].IsObject()) {
134
+ Napi::TypeError::New(env, "options object is required").ThrowAsJavaScriptException();
135
+ return env.Null();
136
+ }
137
+
138
+ const Napi::Object options = info[0].As<Napi::Object>();
139
+ const uint16_t cols = static_cast<uint16_t>(std::max(1, options.Get("cols").ToNumber().Int32Value()));
140
+ const uint16_t rows = static_cast<uint16_t>(std::max(1, options.Get("rows").ToNumber().Int32Value()));
141
+ const size_t scrollback = options.Has("scrollback")
142
+ ? static_cast<size_t>(std::max<int64_t>(0, options.Get("scrollback").ToNumber().Int64Value()))
143
+ : 2000;
144
+
145
+ auto* state = new TerminalBindingState();
146
+ const int result = adhdev_ghostty_terminal_create(cols, rows, scrollback, &state->terminal);
147
+ if (result != ADHDEV_GHOSTTY_SUCCESS) {
148
+ delete state;
149
+ ThrowGhosttyError(env, "adhdev_ghostty_terminal_create", result);
150
+ return env.Null();
151
+ }
152
+
153
+ Napi::Object object = Napi::Object::New(env);
154
+ Napi::External<TerminalBindingState> external = Napi::External<TerminalBindingState>::New(env, state, FinalizeState);
155
+ object.Set("_native", external);
156
+ object.Set("write", Napi::Function::New(env, Write, "write", state));
157
+ object.Set("resize", Napi::Function::New(env, Resize, "resize", state));
158
+ object.Set("formatPlainText", Napi::Function::New(env, FormatPlainText, "formatPlainText", state));
159
+ object.Set("dispose", Napi::Function::New(env, Dispose, "dispose", state));
160
+ return object;
161
+ }
162
+
163
+ } // namespace
164
+
165
+ Napi::Object InitAddon(Napi::Env env, Napi::Object exports) {
166
+ exports.Set("createTerminal", Napi::Function::New(env, CreateTerminal));
167
+ return exports;
168
+ }
169
+
170
+ NODE_API_MODULE(ghostty_vt_node, InitAddon)
@@ -0,0 +1,118 @@
1
+ #include "ghostty_bridge.h"
2
+
3
+ #include <ghostty/vt.h>
4
+
5
+ struct AdhdevGhosttyTerminal {
6
+ GhosttyTerminal handle;
7
+ uint16_t cols;
8
+ uint16_t rows;
9
+ };
10
+
11
+ static const uint32_t kCellWidthPx = 8;
12
+ static const uint32_t kCellHeightPx = 16;
13
+
14
+ int adhdev_ghostty_terminal_create(
15
+ uint16_t cols,
16
+ uint16_t rows,
17
+ size_t scrollback,
18
+ AdhdevGhosttyTerminal** out_terminal) {
19
+ if (!out_terminal || cols == 0 || rows == 0) return GHOSTTY_INVALID_VALUE;
20
+
21
+ AdhdevGhosttyTerminal* terminal = (AdhdevGhosttyTerminal*)ghostty_alloc(NULL, sizeof(AdhdevGhosttyTerminal));
22
+ if (!terminal) return GHOSTTY_OUT_OF_MEMORY;
23
+
24
+ terminal->cols = cols;
25
+ terminal->rows = rows;
26
+ terminal->handle = NULL;
27
+
28
+ GhosttyTerminalOptions options = {
29
+ .cols = cols,
30
+ .rows = rows,
31
+ .max_scrollback = scrollback,
32
+ };
33
+
34
+ GhosttyResult result = ghostty_terminal_new(NULL, &terminal->handle, options);
35
+ if (result != GHOSTTY_SUCCESS) {
36
+ ghostty_free(NULL, (uint8_t*)terminal, sizeof(AdhdevGhosttyTerminal));
37
+ return result;
38
+ }
39
+
40
+ *out_terminal = terminal;
41
+ return GHOSTTY_SUCCESS;
42
+ }
43
+
44
+ int adhdev_ghostty_terminal_write(
45
+ AdhdevGhosttyTerminal* terminal,
46
+ const uint8_t* data,
47
+ size_t len) {
48
+ if (!terminal || !terminal->handle || (!data && len > 0)) return GHOSTTY_INVALID_VALUE;
49
+ ghostty_terminal_vt_write(terminal->handle, data, len);
50
+ return GHOSTTY_SUCCESS;
51
+ }
52
+
53
+ int adhdev_ghostty_terminal_resize(
54
+ AdhdevGhosttyTerminal* terminal,
55
+ uint16_t cols,
56
+ uint16_t rows) {
57
+ if (!terminal || !terminal->handle || cols == 0 || rows == 0) return GHOSTTY_INVALID_VALUE;
58
+ terminal->cols = cols;
59
+ terminal->rows = rows;
60
+ (void)kCellWidthPx;
61
+ (void)kCellHeightPx;
62
+ return ghostty_terminal_resize(terminal->handle, cols, rows);
63
+ }
64
+
65
+ int adhdev_ghostty_terminal_format_plain_text(
66
+ AdhdevGhosttyTerminal* terminal,
67
+ int trim,
68
+ char** out_text,
69
+ size_t* out_len) {
70
+ if (!terminal || !terminal->handle || !out_text || !out_len) return GHOSTTY_INVALID_VALUE;
71
+
72
+ GhosttyFormatterTerminalOptions options = GHOSTTY_INIT_SIZED(GhosttyFormatterTerminalOptions);
73
+ options.emit = GHOSTTY_FORMATTER_FORMAT_PLAIN;
74
+ options.trim = trim != 0;
75
+
76
+ GhosttyFormatter formatter = NULL;
77
+ GhosttyResult result = ghostty_formatter_terminal_new(NULL, &formatter, terminal->handle, options);
78
+ if (result != GHOSTTY_SUCCESS) return result;
79
+
80
+ uint8_t* text = NULL;
81
+ size_t text_len = 0;
82
+ result = ghostty_formatter_format_alloc(formatter, NULL, &text, &text_len);
83
+ ghostty_formatter_free(formatter);
84
+ if (result != GHOSTTY_SUCCESS) return result;
85
+
86
+ *out_text = (char*)text;
87
+ *out_len = text_len;
88
+ return GHOSTTY_SUCCESS;
89
+ }
90
+
91
+ void adhdev_ghostty_terminal_free_text(char* text, size_t len) {
92
+ if (!text) return;
93
+ ghostty_free(NULL, (uint8_t*)text, len);
94
+ }
95
+
96
+ void adhdev_ghostty_terminal_destroy(AdhdevGhosttyTerminal* terminal) {
97
+ if (!terminal) return;
98
+ if (terminal->handle) {
99
+ ghostty_terminal_free(terminal->handle);
100
+ terminal->handle = NULL;
101
+ }
102
+ ghostty_free(NULL, (uint8_t*)terminal, sizeof(AdhdevGhosttyTerminal));
103
+ }
104
+
105
+ const char* adhdev_ghostty_result_message(int result) {
106
+ switch (result) {
107
+ case GHOSTTY_SUCCESS:
108
+ return "success";
109
+ case GHOSTTY_OUT_OF_MEMORY:
110
+ return "out of memory";
111
+ case GHOSTTY_INVALID_VALUE:
112
+ return "invalid value";
113
+ case GHOSTTY_OUT_OF_SPACE:
114
+ return "out of space";
115
+ default:
116
+ return "unknown error";
117
+ }
118
+ }
@@ -0,0 +1,46 @@
1
+ #ifndef ADHDEV_GHOSTTY_BRIDGE_H
2
+ #define ADHDEV_GHOSTTY_BRIDGE_H
3
+
4
+ #include <stddef.h>
5
+ #include <stdint.h>
6
+
7
+ #ifdef __cplusplus
8
+ extern "C" {
9
+ #endif
10
+
11
+ typedef struct AdhdevGhosttyTerminal AdhdevGhosttyTerminal;
12
+
13
+ #define ADHDEV_GHOSTTY_SUCCESS 0
14
+ #define ADHDEV_GHOSTTY_INVALID_VALUE -2
15
+
16
+ int adhdev_ghostty_terminal_create(
17
+ uint16_t cols,
18
+ uint16_t rows,
19
+ size_t scrollback,
20
+ AdhdevGhosttyTerminal** out_terminal);
21
+
22
+ int adhdev_ghostty_terminal_write(
23
+ AdhdevGhosttyTerminal* terminal,
24
+ const uint8_t* data,
25
+ size_t len);
26
+
27
+ int adhdev_ghostty_terminal_resize(
28
+ AdhdevGhosttyTerminal* terminal,
29
+ uint16_t cols,
30
+ uint16_t rows);
31
+
32
+ int adhdev_ghostty_terminal_format_plain_text(
33
+ AdhdevGhosttyTerminal* terminal,
34
+ int trim,
35
+ char** out_text,
36
+ size_t* out_len);
37
+
38
+ void adhdev_ghostty_terminal_free_text(char* text, size_t len);
39
+ void adhdev_ghostty_terminal_destroy(AdhdevGhosttyTerminal* terminal);
40
+ const char* adhdev_ghostty_result_message(int result);
41
+
42
+ #ifdef __cplusplus
43
+ }
44
+ #endif
45
+
46
+ #endif