@adhdev/ghostty-vt-node 0.7.35 → 0.7.43
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/index.d.ts +2 -0
- package/index.js +1 -1
- package/package.json +1 -1
- package/prebuilt/darwin-arm64-node115/ghostty_vt_node.node +0 -0
- package/prebuilt/darwin-arm64-node127/ghostty_vt_node.node +0 -0
- package/prebuilt/darwin-arm64-node137/ghostty_vt_node.node +0 -0
- package/prebuilt/linux-x64-node115/ghostty_vt_node.node +0 -0
- package/prebuilt/linux-x64-node127/ghostty_vt_node.node +0 -0
- package/prebuilt/linux-x64-node127/libghostty-vt.so +0 -0
- package/prebuilt/linux-x64-node127/libghostty-vt.so.0.1.0 +0 -0
- package/prebuilt/linux-x64-node137/ghostty_vt_node.node +0 -0
- package/prebuilt/win32-x64-node115/ghostty_vt_node.node +0 -0
- package/prebuilt/win32-x64-node127/ghostty_vt_node.node +0 -0
- package/prebuilt/win32-x64-node137/ghostty-vt.dll +0 -0
- package/prebuilt/win32-x64-node137/ghostty_vt_node.node +0 -0
- package/scripts/build-or-use-prebuilt.mjs +30 -3
- package/src/addon.cc +45 -0
- package/src/ghostty_bridge.c +58 -0
- package/src/ghostty_bridge.h +10 -0
package/index.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export interface GhosttyTerminalHandle {
|
|
|
12
12
|
write(data: string | Uint8Array): void;
|
|
13
13
|
resize(cols: number, rows: number): void;
|
|
14
14
|
formatPlainText(options?: GhosttyPlainTextFormatOptions): string;
|
|
15
|
+
formatVT(): string;
|
|
16
|
+
getCursorPosition(): { col: number; row: number };
|
|
15
17
|
dispose(): void;
|
|
16
18
|
}
|
|
17
19
|
|
package/index.js
CHANGED
|
@@ -12,9 +12,9 @@ function loadBinding() {
|
|
|
12
12
|
const candidates = [
|
|
13
13
|
explicitPrebuiltDir ? path.join(explicitPrebuiltDir, triplet, 'ghostty_vt_node.node') : null,
|
|
14
14
|
explicitPrebuiltDir ? path.join(explicitPrebuiltDir, 'ghostty_vt_node.node') : null,
|
|
15
|
-
path.join(__dirname, 'prebuilt', triplet, 'ghostty_vt_node.node'),
|
|
16
15
|
path.join(__dirname, 'build', 'Release', 'ghostty_vt_node.node'),
|
|
17
16
|
path.join(__dirname, 'build', 'Debug', 'ghostty_vt_node.node'),
|
|
17
|
+
path.join(__dirname, 'prebuilt', triplet, 'ghostty_vt_node.node'),
|
|
18
18
|
].filter(Boolean);
|
|
19
19
|
|
|
20
20
|
const errors = [];
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -8,6 +8,24 @@ const packageDir = path.resolve(scriptDir, '..');
|
|
|
8
8
|
const outputDir = path.join(packageDir, 'build', 'Release');
|
|
9
9
|
const outputFile = path.join(outputDir, 'ghostty_vt_node.node');
|
|
10
10
|
const triplet = `${process.platform}-${process.arch}-node${process.versions.modules}`;
|
|
11
|
+
const sourceInputs = [
|
|
12
|
+
path.join(packageDir, 'CMakeLists.txt'),
|
|
13
|
+
path.join(packageDir, 'src', 'addon.cc'),
|
|
14
|
+
path.join(packageDir, 'src', 'ghostty_bridge.c'),
|
|
15
|
+
path.join(packageDir, 'src', 'ghostty_bridge.h'),
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
function safeMtime(filePath) {
|
|
19
|
+
try {
|
|
20
|
+
return fs.statSync(filePath).mtimeMs;
|
|
21
|
+
} catch {
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function latestSourceMtime() {
|
|
27
|
+
return sourceInputs.reduce((latest, filePath) => Math.max(latest, safeMtime(filePath)), 0);
|
|
28
|
+
}
|
|
11
29
|
|
|
12
30
|
function candidatePrebuiltPaths() {
|
|
13
31
|
const candidates = [];
|
|
@@ -20,9 +38,10 @@ function candidatePrebuiltPaths() {
|
|
|
20
38
|
return candidates;
|
|
21
39
|
}
|
|
22
40
|
|
|
23
|
-
function installPrebuiltIfPresent() {
|
|
41
|
+
function installPrebuiltIfPresent(minMtime = 0) {
|
|
24
42
|
for (const candidate of candidatePrebuiltPaths()) {
|
|
25
43
|
if (!fs.existsSync(candidate)) continue;
|
|
44
|
+
if (safeMtime(candidate) < minMtime) continue;
|
|
26
45
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
27
46
|
fs.copyFileSync(candidate, outputFile);
|
|
28
47
|
console.log(`[ghostty-vt-node] using prebuilt native binding from ${candidate}`);
|
|
@@ -31,12 +50,20 @@ function installPrebuiltIfPresent() {
|
|
|
31
50
|
return false;
|
|
32
51
|
}
|
|
33
52
|
|
|
34
|
-
|
|
53
|
+
const sourceMtime = latestSourceMtime();
|
|
54
|
+
const outputMtime = safeMtime(outputFile);
|
|
55
|
+
|
|
56
|
+
if (outputMtime >= sourceMtime && outputMtime > 0) {
|
|
57
|
+
console.log(`[ghostty-vt-node] keeping existing local build at ${outputFile}`);
|
|
58
|
+
process.exit(0);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!installPrebuiltIfPresent(sourceMtime) && process.env.ADHDEV_SKIP_GHOSTTY_VT_BUILD === '1') {
|
|
35
62
|
console.log(`[ghostty-vt-node] skipping native build for ${triplet} (ADHDEV_SKIP_GHOSTTY_VT_BUILD=1)`);
|
|
36
63
|
process.exit(0);
|
|
37
64
|
}
|
|
38
65
|
|
|
39
|
-
if (installPrebuiltIfPresent()) {
|
|
66
|
+
if (installPrebuiltIfPresent(sourceMtime)) {
|
|
40
67
|
process.exit(0);
|
|
41
68
|
}
|
|
42
69
|
|
package/src/addon.cc
CHANGED
|
@@ -119,6 +119,49 @@ Napi::Value FormatPlainText(const Napi::CallbackInfo& info) {
|
|
|
119
119
|
return Napi::String::New(env, output);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
Napi::Value FormatVT(const Napi::CallbackInfo& info) {
|
|
123
|
+
Napi::Env env = info.Env();
|
|
124
|
+
TerminalBindingState* state = GetState(info);
|
|
125
|
+
if (!EnsureOpen(env, state)) return env.Null();
|
|
126
|
+
|
|
127
|
+
char* text = nullptr;
|
|
128
|
+
size_t text_len = 0;
|
|
129
|
+
const int result = adhdev_ghostty_terminal_format_vt(
|
|
130
|
+
state->terminal,
|
|
131
|
+
&text,
|
|
132
|
+
&text_len);
|
|
133
|
+
if (result != ADHDEV_GHOSTTY_SUCCESS) {
|
|
134
|
+
ThrowGhosttyError(env, "adhdev_ghostty_terminal_format_vt", result);
|
|
135
|
+
return env.Null();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
std::string output(text, text_len);
|
|
139
|
+
adhdev_ghostty_terminal_free_text(text, text_len);
|
|
140
|
+
return Napi::String::New(env, output);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
Napi::Value GetCursorPosition(const Napi::CallbackInfo& info) {
|
|
144
|
+
Napi::Env env = info.Env();
|
|
145
|
+
TerminalBindingState* state = GetState(info);
|
|
146
|
+
if (!EnsureOpen(env, state)) return env.Null();
|
|
147
|
+
|
|
148
|
+
uint16_t col = 0;
|
|
149
|
+
uint16_t row = 0;
|
|
150
|
+
const int result = adhdev_ghostty_terminal_cursor_position(
|
|
151
|
+
state->terminal,
|
|
152
|
+
&col,
|
|
153
|
+
&row);
|
|
154
|
+
if (result != ADHDEV_GHOSTTY_SUCCESS) {
|
|
155
|
+
ThrowGhosttyError(env, "adhdev_ghostty_terminal_cursor_position", result);
|
|
156
|
+
return env.Null();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
Napi::Object output = Napi::Object::New(env);
|
|
160
|
+
output.Set("col", Napi::Number::New(env, col));
|
|
161
|
+
output.Set("row", Napi::Number::New(env, row));
|
|
162
|
+
return output;
|
|
163
|
+
}
|
|
164
|
+
|
|
122
165
|
Napi::Value Dispose(const Napi::CallbackInfo& info) {
|
|
123
166
|
TerminalBindingState* state = GetState(info);
|
|
124
167
|
if (state && state->terminal) {
|
|
@@ -156,6 +199,8 @@ Napi::Value CreateTerminal(const Napi::CallbackInfo& info) {
|
|
|
156
199
|
object.Set("write", Napi::Function::New(env, Write, "write", state));
|
|
157
200
|
object.Set("resize", Napi::Function::New(env, Resize, "resize", state));
|
|
158
201
|
object.Set("formatPlainText", Napi::Function::New(env, FormatPlainText, "formatPlainText", state));
|
|
202
|
+
object.Set("formatVT", Napi::Function::New(env, FormatVT, "formatVT", state));
|
|
203
|
+
object.Set("getCursorPosition", Napi::Function::New(env, GetCursorPosition, "getCursorPosition", state));
|
|
159
204
|
object.Set("dispose", Napi::Function::New(env, Dispose, "dispose", state));
|
|
160
205
|
return object;
|
|
161
206
|
}
|
package/src/ghostty_bridge.c
CHANGED
|
@@ -88,6 +88,64 @@ int adhdev_ghostty_terminal_format_plain_text(
|
|
|
88
88
|
return GHOSTTY_SUCCESS;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
int adhdev_ghostty_terminal_format_vt(
|
|
92
|
+
AdhdevGhosttyTerminal* terminal,
|
|
93
|
+
char** out_text,
|
|
94
|
+
size_t* out_len) {
|
|
95
|
+
if (!terminal || !terminal->handle || !out_text || !out_len) return GHOSTTY_INVALID_VALUE;
|
|
96
|
+
|
|
97
|
+
GhosttyFormatterTerminalOptions options = GHOSTTY_INIT_SIZED(GhosttyFormatterTerminalOptions);
|
|
98
|
+
options.emit = GHOSTTY_FORMATTER_FORMAT_VT;
|
|
99
|
+
options.unwrap = false;
|
|
100
|
+
options.trim = false;
|
|
101
|
+
options.extra.palette = true;
|
|
102
|
+
options.extra.modes = true;
|
|
103
|
+
options.extra.scrolling_region = true;
|
|
104
|
+
options.extra.tabstops = true;
|
|
105
|
+
options.extra.keyboard = true;
|
|
106
|
+
options.extra.screen.cursor = true;
|
|
107
|
+
options.extra.screen.style = true;
|
|
108
|
+
options.extra.screen.hyperlink = true;
|
|
109
|
+
options.extra.screen.protection = true;
|
|
110
|
+
options.extra.screen.kitty_keyboard = true;
|
|
111
|
+
options.extra.screen.charsets = true;
|
|
112
|
+
|
|
113
|
+
GhosttyFormatter formatter = NULL;
|
|
114
|
+
GhosttyResult result = ghostty_formatter_terminal_new(NULL, &formatter, terminal->handle, options);
|
|
115
|
+
if (result != GHOSTTY_SUCCESS) return result;
|
|
116
|
+
|
|
117
|
+
uint8_t* text = NULL;
|
|
118
|
+
size_t text_len = 0;
|
|
119
|
+
result = ghostty_formatter_format_alloc(formatter, NULL, &text, &text_len);
|
|
120
|
+
ghostty_formatter_free(formatter);
|
|
121
|
+
if (result != GHOSTTY_SUCCESS) return result;
|
|
122
|
+
|
|
123
|
+
*out_text = (char*)text;
|
|
124
|
+
*out_len = text_len;
|
|
125
|
+
return GHOSTTY_SUCCESS;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
int adhdev_ghostty_terminal_cursor_position(
|
|
129
|
+
AdhdevGhosttyTerminal* terminal,
|
|
130
|
+
uint16_t* out_col,
|
|
131
|
+
uint16_t* out_row) {
|
|
132
|
+
if (!terminal || !terminal->handle || !out_col || !out_row) return GHOSTTY_INVALID_VALUE;
|
|
133
|
+
|
|
134
|
+
GhosttyResult result = ghostty_terminal_get(
|
|
135
|
+
terminal->handle,
|
|
136
|
+
GHOSTTY_TERMINAL_DATA_CURSOR_X,
|
|
137
|
+
out_col);
|
|
138
|
+
if (result != GHOSTTY_SUCCESS) return result;
|
|
139
|
+
|
|
140
|
+
result = ghostty_terminal_get(
|
|
141
|
+
terminal->handle,
|
|
142
|
+
GHOSTTY_TERMINAL_DATA_CURSOR_Y,
|
|
143
|
+
out_row);
|
|
144
|
+
if (result != GHOSTTY_SUCCESS) return result;
|
|
145
|
+
|
|
146
|
+
return GHOSTTY_SUCCESS;
|
|
147
|
+
}
|
|
148
|
+
|
|
91
149
|
void adhdev_ghostty_terminal_free_text(char* text, size_t len) {
|
|
92
150
|
if (!text) return;
|
|
93
151
|
ghostty_free(NULL, (uint8_t*)text, len);
|
package/src/ghostty_bridge.h
CHANGED
|
@@ -35,6 +35,16 @@ int adhdev_ghostty_terminal_format_plain_text(
|
|
|
35
35
|
char** out_text,
|
|
36
36
|
size_t* out_len);
|
|
37
37
|
|
|
38
|
+
int adhdev_ghostty_terminal_format_vt(
|
|
39
|
+
AdhdevGhosttyTerminal* terminal,
|
|
40
|
+
char** out_text,
|
|
41
|
+
size_t* out_len);
|
|
42
|
+
|
|
43
|
+
int adhdev_ghostty_terminal_cursor_position(
|
|
44
|
+
AdhdevGhosttyTerminal* terminal,
|
|
45
|
+
uint16_t* out_col,
|
|
46
|
+
uint16_t* out_row);
|
|
47
|
+
|
|
38
48
|
void adhdev_ghostty_terminal_free_text(char* text, size_t len);
|
|
39
49
|
void adhdev_ghostty_terminal_destroy(AdhdevGhosttyTerminal* terminal);
|
|
40
50
|
const char* adhdev_ghostty_result_message(int result);
|