@code-yeongyu/senpi-tui 2026.9.12 → 2026.9.13-2
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/README.md +61 -4
- package/dist/alt-screen-search.d.ts +21 -1
- package/dist/alt-screen-search.d.ts.map +1 -1
- package/dist/alt-screen-search.js +199 -42
- package/dist/alt-screen-search.js.map +1 -1
- package/dist/components/box.d.ts +3 -1
- package/dist/components/box.d.ts.map +1 -1
- package/dist/components/box.js +28 -0
- package/dist/components/box.js.map +1 -1
- package/dist/components/editor.d.ts +6 -1
- package/dist/components/editor.d.ts.map +1 -1
- package/dist/components/editor.js +98 -18
- package/dist/components/editor.js.map +1 -1
- package/dist/components/input.d.ts +12 -1
- package/dist/components/input.d.ts.map +1 -1
- package/dist/components/input.js +40 -6
- package/dist/components/input.js.map +1 -1
- package/dist/components/latex.d.ts.map +1 -1
- package/dist/components/latex.js +7 -0
- package/dist/components/latex.js.map +1 -1
- package/dist/components/loader.d.ts +3 -0
- package/dist/components/loader.d.ts.map +1 -1
- package/dist/components/loader.js +20 -8
- package/dist/components/loader.js.map +1 -1
- package/dist/components/mouse-region.d.ts +12 -0
- package/dist/components/mouse-region.d.ts.map +1 -0
- package/dist/components/mouse-region.js +19 -0
- package/dist/components/mouse-region.js.map +1 -0
- package/dist/components/scroll-view.d.ts +6 -3
- package/dist/components/scroll-view.d.ts.map +1 -1
- package/dist/components/scroll-view.js +6 -1
- package/dist/components/scroll-view.js.map +1 -1
- package/dist/components/select-list.d.ts +4 -1
- package/dist/components/select-list.d.ts.map +1 -1
- package/dist/components/select-list.js +48 -2
- package/dist/components/select-list.js.map +1 -1
- package/dist/components/settings-list.d.ts +5 -1
- package/dist/components/settings-list.d.ts.map +1 -1
- package/dist/components/settings-list.js +54 -5
- package/dist/components/settings-list.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts +3 -1
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +32 -9
- package/dist/layout.js.map +1 -1
- package/dist/mouse-input.d.ts +37 -0
- package/dist/mouse-input.d.ts.map +1 -0
- package/dist/mouse-input.js +97 -0
- package/dist/mouse-input.js.map +1 -0
- package/dist/native-modifiers.d.ts +2 -1
- package/dist/native-modifiers.d.ts.map +1 -1
- package/dist/native-modifiers.js +3 -44
- package/dist/native-modifiers.js.map +1 -1
- package/dist/native-platform.d.ts +18 -0
- package/dist/native-platform.d.ts.map +1 -0
- package/dist/native-platform.js +42 -0
- package/dist/native-platform.js.map +1 -0
- package/dist/stdin-buffer.d.ts +2 -0
- package/dist/stdin-buffer.d.ts.map +1 -1
- package/dist/stdin-buffer.js +38 -0
- package/dist/stdin-buffer.js.map +1 -1
- package/dist/terminal.d.ts +25 -1
- package/dist/terminal.d.ts.map +1 -1
- package/dist/terminal.js +112 -24
- package/dist/terminal.js.map +1 -1
- package/dist/tui-alt-screen.d.ts +31 -1
- package/dist/tui-alt-screen.d.ts.map +1 -1
- package/dist/tui-alt-screen.js +327 -78
- package/dist/tui-alt-screen.js.map +1 -1
- package/dist/tui-main-screen.d.ts +12 -0
- package/dist/tui-main-screen.d.ts.map +1 -1
- package/dist/tui-main-screen.js +129 -3
- package/dist/tui-main-screen.js.map +1 -1
- package/dist/tui.d.ts +111 -5
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +278 -4
- package/dist/tui.js.map +1 -1
- package/dist/utils.d.ts +2 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +9 -0
- package/dist/utils.js.map +1 -1
- package/native/clipboard.h +170 -0
- package/native/darwin/README.md +8 -6
- package/native/darwin/build.sh +12 -5
- package/native/darwin/prebuilds/darwin-arm64/{darwin-modifiers.node → darwin-platform.node} +0 -0
- package/native/darwin/prebuilds/darwin-x64/{darwin-modifiers.node → darwin-platform.node} +0 -0
- package/native/darwin/src/darwin-platform.m +93 -0
- package/native/linux/README.md +23 -0
- package/native/linux/build.sh +65 -0
- package/native/linux/prebuilds/linux-arm64/linux-platform-x11.node +0 -0
- package/native/linux/prebuilds/linux-x64/linux-platform-x11.node +0 -0
- package/native/linux/src/clipboard-worker.h +70 -0
- package/native/linux/src/linux-platform-x11.c +274 -0
- package/native/napi.h +89 -0
- package/native/win32/README.md +18 -7
- package/native/win32/build.mjs +7 -4
- package/native/win32/prebuilds/win32-arm64/win32-platform.node +0 -0
- package/native/win32/prebuilds/win32-x64/win32-platform.node +0 -0
- package/native/win32/src/win32-platform.c +241 -0
- package/package.json +10 -3
- package/native/darwin/src/darwin-modifiers.c +0 -70
- package/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
- package/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
- package/native/win32/src/win32-console-mode.c +0 -119
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { getNativeModuleCandidates } from "./native-module-path.js";
|
|
4
|
+
const cjsRequire = createRequire(import.meta.url);
|
|
5
|
+
// Cache module loading, not display availability: a disconnected display can recover.
|
|
6
|
+
const helpers = new Map();
|
|
7
|
+
function loadNativePlatformHelper(platform, suffix = "") {
|
|
8
|
+
const arch = process.arch;
|
|
9
|
+
if (arch !== "x64" && arch !== "arm64")
|
|
10
|
+
return undefined;
|
|
11
|
+
const nativePath = path.join("native", platform, "prebuilds", `${platform}-${arch}`, `${platform}-platform${suffix}.node`);
|
|
12
|
+
if (helpers.has(nativePath))
|
|
13
|
+
return helpers.get(nativePath);
|
|
14
|
+
for (const modulePath of getNativeModuleCandidates(nativePath)) {
|
|
15
|
+
try {
|
|
16
|
+
const helper = cjsRequire(modulePath);
|
|
17
|
+
if (typeof helper?.getText === "function" && typeof helper.getImage === "function") {
|
|
18
|
+
helpers.set(nativePath, helper);
|
|
19
|
+
return helper;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Try the next possible packaging location.
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
helpers.set(nativePath, undefined);
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
export function getNativePlatformHelper() {
|
|
30
|
+
if (process.platform !== "darwin" && process.platform !== "win32")
|
|
31
|
+
return undefined;
|
|
32
|
+
return loadNativePlatformHelper(process.platform);
|
|
33
|
+
}
|
|
34
|
+
/** Load a clipboard helper without opening the display until a read is requested. */
|
|
35
|
+
export function getNativeClipboard() {
|
|
36
|
+
if (process.platform !== "linux")
|
|
37
|
+
return getNativePlatformHelper();
|
|
38
|
+
if (!process.env.DISPLAY)
|
|
39
|
+
return undefined;
|
|
40
|
+
return loadNativePlatformHelper("linux", "-x11");
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=native-platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-platform.js","sourceRoot":"","sources":["../src/native-platform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAEpE,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAkBlD,sFAAsF;AACtF,MAAM,OAAO,GAAG,IAAI,GAAG,EAA4C,CAAC;AAEpE,SAAS,wBAAwB,CAAC,QAAgB,EAAE,MAAM,GAAG,EAAE;IAC9D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAC1B,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC;IACzD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAC3B,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,GAAG,QAAQ,IAAI,IAAI,EAAE,EACrB,GAAG,QAAQ,YAAY,MAAM,OAAO,CACpC,CAAC;IACF,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAE5D,KAAK,MAAM,UAAU,IAAI,yBAAyB,CAAC,UAAU,CAAC,EAAE,CAAC;QAChE,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,UAAU,CAAC,UAAU,CAAyC,CAAC;YAC9E,IAAI,OAAO,MAAM,EAAE,OAAO,KAAK,UAAU,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;gBACpF,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,MAA8B,CAAC,CAAC;gBACxD,OAAO,MAA8B,CAAC;YACvC,CAAC;QACF,CAAC;QAAC,MAAM,CAAC;YACR,4CAA4C;QAC7C,CAAC;IACF,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACnC,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,uBAAuB;IACtC,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC;IACpF,OAAO,wBAAwB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AACnD,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,kBAAkB;IACjC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,uBAAuB,EAAE,CAAC;IACnE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC3C,OAAO,wBAAwB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC","sourcesContent":["import { createRequire } from \"node:module\";\nimport * as path from \"node:path\";\nimport { getNativeModuleCandidates } from \"./native-module-path.ts\";\n\nconst cjsRequire = createRequire(import.meta.url);\n\nexport type ModifierKey = \"shift\" | \"command\" | \"control\" | \"option\";\n\nexport interface NativeClipboard {\n\t/** Undefined means unavailable, null means no text; transfer failures reject. */\n\tgetText(): Promise<string | null | undefined>;\n\t/** Undefined means unavailable, null means no image; transfer failures reject. */\n\tgetImage(): Promise<Uint8Array | null | undefined>;\n\t/** Linux uses command-line tools to retain clipboard ownership instead. */\n\tsetText?(text: string): Promise<void>;\n}\n\ntype NativePlatformHelper = NativeClipboard & {\n\tenableVirtualTerminalInput?: () => boolean;\n\tisModifierPressed?: (name: ModifierKey) => boolean;\n};\n\n// Cache module loading, not display availability: a disconnected display can recover.\nconst helpers = new Map<string, NativePlatformHelper | undefined>();\n\nfunction loadNativePlatformHelper(platform: string, suffix = \"\"): NativePlatformHelper | undefined {\n\tconst arch = process.arch;\n\tif (arch !== \"x64\" && arch !== \"arm64\") return undefined;\n\tconst nativePath = path.join(\n\t\t\"native\",\n\t\tplatform,\n\t\t\"prebuilds\",\n\t\t`${platform}-${arch}`,\n\t\t`${platform}-platform${suffix}.node`,\n\t);\n\tif (helpers.has(nativePath)) return helpers.get(nativePath);\n\n\tfor (const modulePath of getNativeModuleCandidates(nativePath)) {\n\t\ttry {\n\t\t\tconst helper = cjsRequire(modulePath) as Partial<NativePlatformHelper> | null;\n\t\t\tif (typeof helper?.getText === \"function\" && typeof helper.getImage === \"function\") {\n\t\t\t\thelpers.set(nativePath, helper as NativePlatformHelper);\n\t\t\t\treturn helper as NativePlatformHelper;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Try the next possible packaging location.\n\t\t}\n\t}\n\thelpers.set(nativePath, undefined);\n\treturn undefined;\n}\n\nexport function getNativePlatformHelper(): NativePlatformHelper | undefined {\n\tif (process.platform !== \"darwin\" && process.platform !== \"win32\") return undefined;\n\treturn loadNativePlatformHelper(process.platform);\n}\n\n/** Load a clipboard helper without opening the display until a read is requested. */\nexport function getNativeClipboard(): NativeClipboard | undefined {\n\tif (process.platform !== \"linux\") return getNativePlatformHelper();\n\tif (!process.env.DISPLAY) return undefined;\n\treturn loadNativePlatformHelper(\"linux\", \"-x11\");\n}\n"]}
|
package/dist/stdin-buffer.d.ts
CHANGED
|
@@ -42,6 +42,8 @@ export declare class StdinBuffer extends EventEmitter<StdinBufferEventMap> {
|
|
|
42
42
|
private timeout;
|
|
43
43
|
private readonly timeoutMs;
|
|
44
44
|
private readonly escapeTimeoutMs;
|
|
45
|
+
private mouseFragmentStartedAt?;
|
|
46
|
+
private discardingMouseFragment;
|
|
45
47
|
private pasteMode;
|
|
46
48
|
private pasteBuffer;
|
|
47
49
|
private pendingKittyPrintableCodepoint;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdin-buffer.d.ts","sourceRoot":"","sources":["../src/stdin-buffer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAoPtC,MAAM,MAAM,kBAAkB,GAAG;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC;IACf,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC;CAChB,CAAC;AAEF;;;GAGG;AACH,qBAAa,WAAY,SAAQ,YAAY,CAAC,mBAAmB,CAAC;IACjE,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,OAAO,CAA8C;IAC7D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,8BAA8B,CAAqB;IAC3D,OAAO,CAAC,OAAO,CAAoD;IAEnE,YAAY,OAAO,GAAE,kBAAuB,EAI3C;IAEM,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"stdin-buffer.d.ts","sourceRoot":"","sources":["../src/stdin-buffer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAoPtC,MAAM,MAAM,kBAAkB,GAAG;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC;IACf,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC;CAChB,CAAC;AAEF;;;GAGG;AACH,qBAAa,WAAY,SAAQ,YAAY,CAAC,mBAAmB,CAAC;IACjE,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,OAAO,CAA8C;IAC7D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,sBAAsB,CAAC,CAAS;IACxC,OAAO,CAAC,uBAAuB,CAAS;IACxC,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,8BAA8B,CAAqB;IAC3D,OAAO,CAAC,OAAO,CAAoD;IAEnE,YAAY,OAAO,GAAE,kBAAuB,EAI3C;IAEM,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA4H1C;IAED,OAAO,CAAC,gBAAgB;IAWxB,KAAK,IAAI,MAAM,EAAE,CA0BhB;IAED,KAAK,IAAI,IAAI,CAYZ;IAED,SAAS,IAAI,MAAM,CAElB;IAED,OAAO,IAAI,IAAI,CAEd;CACD"}
|
package/dist/stdin-buffer.js
CHANGED
|
@@ -232,6 +232,7 @@ export class StdinBuffer extends EventEmitter {
|
|
|
232
232
|
super();
|
|
233
233
|
this.buffer = "";
|
|
234
234
|
this.timeout = null;
|
|
235
|
+
this.discardingMouseFragment = false;
|
|
235
236
|
this.pasteMode = false;
|
|
236
237
|
this.pasteBuffer = "";
|
|
237
238
|
this.decoder = new StringDecoder("utf8");
|
|
@@ -266,6 +267,19 @@ export class StdinBuffer extends EventEmitter {
|
|
|
266
267
|
}
|
|
267
268
|
return;
|
|
268
269
|
}
|
|
270
|
+
if (this.discardingMouseFragment) {
|
|
271
|
+
const terminator = str.search(/[\x40-\x7e]/);
|
|
272
|
+
const escapeIndex = str.indexOf(ESC);
|
|
273
|
+
if (escapeIndex !== -1 && (terminator === -1 || escapeIndex < terminator)) {
|
|
274
|
+
str = str.slice(escapeIndex);
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
if (terminator === -1)
|
|
278
|
+
return;
|
|
279
|
+
str = str.slice(terminator + 1);
|
|
280
|
+
}
|
|
281
|
+
this.discardingMouseFragment = false;
|
|
282
|
+
}
|
|
269
283
|
this.buffer += str;
|
|
270
284
|
if (this.pasteMode) {
|
|
271
285
|
this.pasteBuffer += this.buffer;
|
|
@@ -314,6 +328,16 @@ export class StdinBuffer extends EventEmitter {
|
|
|
314
328
|
}
|
|
315
329
|
const result = extractCompleteSequences(this.buffer);
|
|
316
330
|
this.buffer = result.remainder;
|
|
331
|
+
if (this.buffer.startsWith("\x1b[<")) {
|
|
332
|
+
this.mouseFragmentStartedAt ??= Date.now();
|
|
333
|
+
if (this.buffer.length > 64) {
|
|
334
|
+
this.buffer = "";
|
|
335
|
+
this.discardingMouseFragment = true;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
this.mouseFragmentStartedAt = undefined;
|
|
340
|
+
}
|
|
317
341
|
for (const sequence of result.sequences) {
|
|
318
342
|
this.emitDataSequence(sequence);
|
|
319
343
|
}
|
|
@@ -344,6 +368,18 @@ export class StdinBuffer extends EventEmitter {
|
|
|
344
368
|
if (this.buffer.length === 0) {
|
|
345
369
|
return [];
|
|
346
370
|
}
|
|
371
|
+
if (this.buffer.startsWith("\x1b[<")) {
|
|
372
|
+
const remaining = 750 - (Date.now() - (this.mouseFragmentStartedAt ?? Date.now()));
|
|
373
|
+
if (remaining > 0 && this.buffer.length <= 64) {
|
|
374
|
+
this.timeout = setTimeout(() => this.flush(), remaining);
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
this.buffer = "";
|
|
378
|
+
this.mouseFragmentStartedAt = undefined;
|
|
379
|
+
this.discardingMouseFragment = true;
|
|
380
|
+
}
|
|
381
|
+
return [];
|
|
382
|
+
}
|
|
347
383
|
const sequences = [this.buffer];
|
|
348
384
|
this.buffer = "";
|
|
349
385
|
this.pendingKittyPrintableCodepoint = undefined;
|
|
@@ -357,6 +393,8 @@ export class StdinBuffer extends EventEmitter {
|
|
|
357
393
|
this.buffer = "";
|
|
358
394
|
this.pasteMode = false;
|
|
359
395
|
this.pasteBuffer = "";
|
|
396
|
+
this.mouseFragmentStartedAt = undefined;
|
|
397
|
+
this.discardingMouseFragment = false;
|
|
360
398
|
this.pendingKittyPrintableCodepoint = undefined;
|
|
361
399
|
this.decoder = new StringDecoder("utf8");
|
|
362
400
|
}
|
package/dist/stdin-buffer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdin-buffer.js","sourceRoot":"","sources":["../src/stdin-buffer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * StdinBuffer buffers input and emits complete sequences.\n *\n * This is necessary because stdin data events can arrive in partial chunks,\n * especially for escape sequences like mouse events. Without buffering,\n * partial sequences can be misinterpreted as regular keypresses.\n *\n * For example, the mouse SGR sequence `\\x1b[<35;20;5m` might arrive as:\n * - Event 1: `\\x1b`\n * - Event 2: `[<35`\n * - Event 3: `;20;5m`\n *\n * The buffer accumulates these until a complete sequence is detected.\n * Call the `process()` method to feed input data.\n *\n * Based on code from OpenTUI (https://github.com/anomalyco/opentui)\n * MIT License - Copyright (c) 2025 opentui\n */\n\nimport { StringDecoder } from \"node:string_decoder\";\nimport { EventEmitter } from \"events\";\n\nconst ESC = \"\\x1b\";\nconst DEFAULT_SEQUENCE_TIMEOUT_MS = 50;\nconst DEFAULT_ESCAPE_TIMEOUT_MS = 10;\nconst BRACKETED_PASTE_START = \"\\x1b[200~\";\nconst BRACKETED_PASTE_END = \"\\x1b[201~\";\n\ntype StatefulStringDecoder = StringDecoder & {\n\treadonly lastNeed?: number;\n};\n\n/**\n * Check if a string is a complete escape sequence or needs more data\n */\nfunction isCompleteSequence(data: string): \"complete\" | \"incomplete\" | \"not-escape\" {\n\tif (!data.startsWith(ESC)) {\n\t\treturn \"not-escape\";\n\t}\n\n\tif (data.length === 1) {\n\t\treturn \"incomplete\";\n\t}\n\n\tconst afterEsc = data.slice(1);\n\n\t// CSI sequences: ESC [\n\tif (afterEsc.startsWith(\"[\")) {\n\t\t// Check for old-style mouse sequence: ESC[M + 3 bytes\n\t\tif (afterEsc.startsWith(\"[M\")) {\n\t\t\t// Old-style mouse needs ESC[M + 3 bytes = 6 total\n\t\t\treturn data.length >= 6 ? \"complete\" : \"incomplete\";\n\t\t}\n\t\treturn isCompleteCsiSequence(data);\n\t}\n\n\t// OSC sequences: ESC ]\n\tif (afterEsc.startsWith(\"]\")) {\n\t\treturn isCompleteOscSequence(data);\n\t}\n\n\t// DCS sequences: ESC P ... ESC \\ (includes XTVersion responses)\n\tif (afterEsc.startsWith(\"P\")) {\n\t\treturn isCompleteDcsSequence(data);\n\t}\n\n\t// APC sequences: ESC _ ... ESC \\ (includes Kitty graphics responses)\n\tif (afterEsc.startsWith(\"_\")) {\n\t\treturn isCompleteApcSequence(data);\n\t}\n\n\t// SS3 sequences: ESC O\n\tif (afterEsc.startsWith(\"O\")) {\n\t\t// ESC O followed by a single character\n\t\treturn afterEsc.length >= 2 ? \"complete\" : \"incomplete\";\n\t}\n\n\t// Meta key sequences: ESC followed by a single character\n\tif (afterEsc.length === 1) {\n\t\treturn \"complete\";\n\t}\n\n\t// Unknown escape sequence - treat as complete\n\treturn \"complete\";\n}\n\n/**\n * Check if CSI sequence is complete\n * CSI sequences: ESC [ ... followed by a final byte (0x40-0x7E)\n */\nfunction isCompleteCsiSequence(data: string): \"complete\" | \"incomplete\" {\n\tif (!data.startsWith(`${ESC}[`)) {\n\t\treturn \"complete\";\n\t}\n\n\t// Need at least ESC [ and one more character\n\tif (data.length < 3) {\n\t\treturn \"incomplete\";\n\t}\n\n\tconst payload = data.slice(2);\n\n\t// CSI sequences end with a byte in the range 0x40-0x7E (@-~)\n\t// This includes all letters and several special characters\n\tconst lastChar = payload[payload.length - 1];\n\tconst lastCharCode = lastChar.charCodeAt(0);\n\n\tif (lastCharCode >= 0x40 && lastCharCode <= 0x7e) {\n\t\t// Special handling for SGR mouse sequences\n\t\t// Format: ESC[<B;X;Ym or ESC[<B;X;YM\n\t\tif (payload.startsWith(\"<\")) {\n\t\t\t// Must have format: <digits;digits;digits[Mm]\n\t\t\tconst mouseMatch = /^<\\d+;\\d+;\\d+[Mm]$/.test(payload);\n\t\t\tif (mouseMatch) {\n\t\t\t\treturn \"complete\";\n\t\t\t}\n\t\t\t// If it ends with M or m but doesn't match the pattern, still incomplete\n\t\t\tif (lastChar === \"M\" || lastChar === \"m\") {\n\t\t\t\t// Check if we have the right structure\n\t\t\t\tconst parts = payload.slice(1, -1).split(\";\");\n\t\t\t\tif (parts.length === 3 && parts.every((p) => /^\\d+$/.test(p))) {\n\t\t\t\t\treturn \"complete\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn \"incomplete\";\n\t\t}\n\n\t\treturn \"complete\";\n\t}\n\n\treturn \"incomplete\";\n}\n\n/**\n * Check if OSC sequence is complete\n * OSC sequences: ESC ] ... ST (where ST is ESC \\ or BEL)\n */\nfunction isCompleteOscSequence(data: string): \"complete\" | \"incomplete\" {\n\tif (!data.startsWith(`${ESC}]`)) {\n\t\treturn \"complete\";\n\t}\n\n\t// OSC sequences end with ST (ESC \\) or BEL (\\x07)\n\tif (data.endsWith(`${ESC}\\\\`) || data.endsWith(\"\\x07\")) {\n\t\treturn \"complete\";\n\t}\n\n\treturn \"incomplete\";\n}\n\n/**\n * Check if DCS (Device Control String) sequence is complete\n * DCS sequences: ESC P ... ST (where ST is ESC \\)\n * Used for XTVersion responses like ESC P >| ... ESC \\\n */\nfunction isCompleteDcsSequence(data: string): \"complete\" | \"incomplete\" {\n\tif (!data.startsWith(`${ESC}P`)) {\n\t\treturn \"complete\";\n\t}\n\n\t// DCS sequences end with ST (ESC \\)\n\tif (data.endsWith(`${ESC}\\\\`)) {\n\t\treturn \"complete\";\n\t}\n\n\treturn \"incomplete\";\n}\n\n/**\n * Check if APC (Application Program Command) sequence is complete\n * APC sequences: ESC _ ... ST (where ST is ESC \\)\n * Used for Kitty graphics responses like ESC _ G ... ESC \\\n */\nfunction isCompleteApcSequence(data: string): \"complete\" | \"incomplete\" {\n\tif (!data.startsWith(`${ESC}_`)) {\n\t\treturn \"complete\";\n\t}\n\n\t// APC sequences end with ST (ESC \\)\n\tif (data.endsWith(`${ESC}\\\\`)) {\n\t\treturn \"complete\";\n\t}\n\n\treturn \"incomplete\";\n}\n\n/**\n * Split accumulated buffer into complete sequences\n */\nfunction parseUnmodifiedKittyPrintableCodepoint(sequence: string): number | undefined {\n\tconst match = sequence.match(/^\\x1b\\[(\\d+)(?::\\d*)?(?::\\d+)?u$/);\n\tif (!match) return undefined;\n\n\tconst codepoint = parseInt(match[1]!, 10);\n\treturn codepoint >= 32 ? codepoint : undefined;\n}\n\nfunction extractCompleteSequences(buffer: string): { sequences: string[]; remainder: string } {\n\tconst sequences: string[] = [];\n\tlet pos = 0;\n\n\twhile (pos < buffer.length) {\n\t\tconst remaining = buffer.slice(pos);\n\n\t\t// Try to extract a sequence starting at this position\n\t\tif (remaining.startsWith(ESC)) {\n\t\t\t// Find the end of this escape sequence\n\t\t\tlet seqEnd = 1;\n\t\t\twhile (seqEnd <= remaining.length) {\n\t\t\t\tconst candidate = remaining.slice(0, seqEnd);\n\t\t\t\tconst status = isCompleteSequence(candidate);\n\n\t\t\t\tif (status === \"complete\") {\n\t\t\t\t\t// WezTerm with enable_kitty_keyboard sends the Escape key press as a\n\t\t\t\t\t// raw '\\x1b' byte (simple text path in encode_kitty, ignoring\n\t\t\t\t\t// DISAMBIGUATE_ESCAPE_CODES) and the release as a full Kitty CSI-u\n\t\t\t\t\t// sequence. These arrive concatenated as '\\x1b\\x1b[27;...u'.\n\t\t\t\t\t// The buffer would normally treat '\\x1b\\x1b' as a complete meta-key\n\t\t\t\t\t// sequence (ESC + single char), leaving '[27;...u' to be typed as\n\t\t\t\t\t// plain text. If the character immediately following '\\x1b\\x1b'\n\t\t\t\t\t// would begin a new escape sequence, emit only the first ESC and\n\t\t\t\t\t// restart from the second.\n\t\t\t\t\tif (candidate === \"\\x1b\\x1b\") {\n\t\t\t\t\t\tconst nextChar = remaining[seqEnd];\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tnextChar === \"[\" || // CSI\n\t\t\t\t\t\t\tnextChar === \"]\" || // OSC\n\t\t\t\t\t\t\tnextChar === \"O\" || // SS3\n\t\t\t\t\t\t\tnextChar === \"P\" || // DCS\n\t\t\t\t\t\t\tnextChar === \"_\" // APC\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tsequences.push(ESC);\n\t\t\t\t\t\t\tpos += 1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tsequences.push(candidate);\n\t\t\t\t\tpos += seqEnd;\n\t\t\t\t\tbreak;\n\t\t\t\t} else if (status === \"incomplete\") {\n\t\t\t\t\tseqEnd++;\n\t\t\t\t} else {\n\t\t\t\t\t// Should not happen when starting with ESC\n\t\t\t\t\tsequences.push(candidate);\n\t\t\t\t\tpos += seqEnd;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (seqEnd > remaining.length) {\n\t\t\t\treturn { sequences, remainder: remaining };\n\t\t\t}\n\t\t} else {\n\t\t\tconst codepoint = remaining.codePointAt(0)!;\n\t\t\tconst character = String.fromCodePoint(codepoint);\n\t\t\tsequences.push(character);\n\t\t\tpos += character.length;\n\t\t}\n\t}\n\n\treturn { sequences, remainder: \"\" };\n}\n\nexport type StdinBufferOptions = {\n\t/**\n\t * Maximum time to wait for an incomplete sequence such as CSI or mouse\n\t * (default: 50ms).\n\t */\n\ttimeout?: number;\n\t/**\n\t * Maximum time to wait after a lone ESC before treating it as Escape\n\t * (default: 10ms). Increase for high-latency Alt+key input (SSH).\n\t */\n\tescapeTimeout?: number;\n};\n\nexport type StdinBufferEventMap = {\n\tdata: [string];\n\tpaste: [string];\n};\n\n/**\n * Buffers stdin input and emits complete sequences via the 'data' event.\n * Handles partial escape sequences that arrive across multiple chunks.\n */\nexport class StdinBuffer extends EventEmitter<StdinBufferEventMap> {\n\tprivate buffer: string = \"\";\n\tprivate timeout: ReturnType<typeof setTimeout> | null = null;\n\tprivate readonly timeoutMs: number;\n\tprivate readonly escapeTimeoutMs: number;\n\tprivate pasteMode: boolean = false;\n\tprivate pasteBuffer: string = \"\";\n\tprivate pendingKittyPrintableCodepoint: number | undefined;\n\tprivate decoder: StatefulStringDecoder = new StringDecoder(\"utf8\");\n\n\tconstructor(options: StdinBufferOptions = {}) {\n\t\tsuper();\n\t\tthis.timeoutMs = options.timeout ?? DEFAULT_SEQUENCE_TIMEOUT_MS;\n\t\tthis.escapeTimeoutMs = options.escapeTimeout ?? DEFAULT_ESCAPE_TIMEOUT_MS;\n\t}\n\n\tpublic process(data: string | Buffer): void {\n\t\t// Clear any pending timeout\n\t\tif (this.timeout) {\n\t\t\tclearTimeout(this.timeout);\n\t\t\tthis.timeout = null;\n\t\t}\n\n\t\tlet str: string;\n\t\tlet decodedFromBuffer = false;\n\t\tif (Buffer.isBuffer(data)) {\n\t\t\tconst hasPendingUtf8Bytes = (this.decoder.lastNeed ?? 0) > 0;\n\t\t\tif (!hasPendingUtf8Bytes && data.length === 1 && data[0]! >= 0x80 && data[0]! < 0xc2) {\n\t\t\t\tconst byte = data[0]! - 128;\n\t\t\t\tstr = `\\x1b${String.fromCharCode(byte)}`;\n\t\t\t} else {\n\t\t\t\tstr = this.decoder.write(data);\n\t\t\t\tdecodedFromBuffer = true;\n\t\t\t}\n\t\t} else {\n\t\t\tstr = data;\n\t\t}\n\n\t\tif (str.length === 0 && this.buffer.length === 0) {\n\t\t\tif (!decodedFromBuffer) {\n\t\t\t\tthis.emitDataSequence(\"\");\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis.buffer += str;\n\n\t\tif (this.pasteMode) {\n\t\t\tthis.pasteBuffer += this.buffer;\n\t\t\tthis.buffer = \"\";\n\n\t\t\tconst endIndex = this.pasteBuffer.indexOf(BRACKETED_PASTE_END);\n\t\t\tif (endIndex !== -1) {\n\t\t\t\tconst pastedContent = this.pasteBuffer.slice(0, endIndex);\n\t\t\t\tconst remaining = this.pasteBuffer.slice(endIndex + BRACKETED_PASTE_END.length);\n\n\t\t\t\tthis.pasteMode = false;\n\t\t\t\tthis.pasteBuffer = \"\";\n\t\t\t\tthis.pendingKittyPrintableCodepoint = undefined;\n\n\t\t\t\tthis.emit(\"paste\", pastedContent);\n\n\t\t\t\tif (remaining.length > 0) {\n\t\t\t\t\tthis.process(remaining);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst startIndex = this.buffer.indexOf(BRACKETED_PASTE_START);\n\t\tif (startIndex !== -1) {\n\t\t\tif (startIndex > 0) {\n\t\t\t\tconst beforePaste = this.buffer.slice(0, startIndex);\n\t\t\t\tconst result = extractCompleteSequences(beforePaste);\n\t\t\t\tfor (const sequence of result.sequences) {\n\t\t\t\t\tthis.emitDataSequence(sequence);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.pendingKittyPrintableCodepoint = undefined;\n\t\t\tthis.buffer = this.buffer.slice(startIndex + BRACKETED_PASTE_START.length);\n\t\t\tthis.pasteMode = true;\n\t\t\tthis.pasteBuffer = this.buffer;\n\t\t\tthis.buffer = \"\";\n\n\t\t\tconst endIndex = this.pasteBuffer.indexOf(BRACKETED_PASTE_END);\n\t\t\tif (endIndex !== -1) {\n\t\t\t\tconst pastedContent = this.pasteBuffer.slice(0, endIndex);\n\t\t\t\tconst remaining = this.pasteBuffer.slice(endIndex + BRACKETED_PASTE_END.length);\n\n\t\t\t\tthis.pasteMode = false;\n\t\t\t\tthis.pasteBuffer = \"\";\n\t\t\t\tthis.pendingKittyPrintableCodepoint = undefined;\n\n\t\t\t\tthis.emit(\"paste\", pastedContent);\n\n\t\t\t\tif (remaining.length > 0) {\n\t\t\t\t\tthis.process(remaining);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst result = extractCompleteSequences(this.buffer);\n\t\tthis.buffer = result.remainder;\n\n\t\tfor (const sequence of result.sequences) {\n\t\t\tthis.emitDataSequence(sequence);\n\t\t}\n\n\t\tif (this.buffer.length > 0) {\n\t\t\tconst timeoutMs = this.buffer === ESC ? this.escapeTimeoutMs : this.timeoutMs;\n\t\t\tthis.timeout = setTimeout(() => {\n\t\t\t\tconst flushed = this.flush();\n\n\t\t\t\tfor (const sequence of flushed) {\n\t\t\t\t\tthis.emitDataSequence(sequence);\n\t\t\t\t}\n\t\t\t}, timeoutMs);\n\t\t}\n\t}\n\n\tprivate emitDataSequence(sequence: string): void {\n\t\tconst rawCodepoint = sequence.length === 1 ? sequence.codePointAt(0) : undefined;\n\t\tif (rawCodepoint !== undefined && rawCodepoint === this.pendingKittyPrintableCodepoint) {\n\t\t\tthis.pendingKittyPrintableCodepoint = undefined;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.pendingKittyPrintableCodepoint = parseUnmodifiedKittyPrintableCodepoint(sequence);\n\t\tthis.emit(\"data\", sequence);\n\t}\n\n\tflush(): string[] {\n\t\tif (this.timeout) {\n\t\t\tclearTimeout(this.timeout);\n\t\t\tthis.timeout = null;\n\t\t}\n\n\t\tif (this.buffer.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst sequences = [this.buffer];\n\t\tthis.buffer = \"\";\n\t\tthis.pendingKittyPrintableCodepoint = undefined;\n\t\treturn sequences;\n\t}\n\n\tclear(): void {\n\t\tif (this.timeout) {\n\t\t\tclearTimeout(this.timeout);\n\t\t\tthis.timeout = null;\n\t\t}\n\t\tthis.buffer = \"\";\n\t\tthis.pasteMode = false;\n\t\tthis.pasteBuffer = \"\";\n\t\tthis.pendingKittyPrintableCodepoint = undefined;\n\t\tthis.decoder = new StringDecoder(\"utf8\");\n\t}\n\n\tgetBuffer(): string {\n\t\treturn this.buffer;\n\t}\n\n\tdestroy(): void {\n\t\tthis.clear();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"stdin-buffer.js","sourceRoot":"","sources":["../src/stdin-buffer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * StdinBuffer buffers input and emits complete sequences.\n *\n * This is necessary because stdin data events can arrive in partial chunks,\n * especially for escape sequences like mouse events. Without buffering,\n * partial sequences can be misinterpreted as regular keypresses.\n *\n * For example, the mouse SGR sequence `\\x1b[<35;20;5m` might arrive as:\n * - Event 1: `\\x1b`\n * - Event 2: `[<35`\n * - Event 3: `;20;5m`\n *\n * The buffer accumulates these until a complete sequence is detected.\n * Call the `process()` method to feed input data.\n *\n * Based on code from OpenTUI (https://github.com/anomalyco/opentui)\n * MIT License - Copyright (c) 2025 opentui\n */\n\nimport { StringDecoder } from \"node:string_decoder\";\nimport { EventEmitter } from \"events\";\n\nconst ESC = \"\\x1b\";\nconst DEFAULT_SEQUENCE_TIMEOUT_MS = 50;\nconst DEFAULT_ESCAPE_TIMEOUT_MS = 10;\nconst BRACKETED_PASTE_START = \"\\x1b[200~\";\nconst BRACKETED_PASTE_END = \"\\x1b[201~\";\n\ntype StatefulStringDecoder = StringDecoder & {\n\treadonly lastNeed?: number;\n};\n\n/**\n * Check if a string is a complete escape sequence or needs more data\n */\nfunction isCompleteSequence(data: string): \"complete\" | \"incomplete\" | \"not-escape\" {\n\tif (!data.startsWith(ESC)) {\n\t\treturn \"not-escape\";\n\t}\n\n\tif (data.length === 1) {\n\t\treturn \"incomplete\";\n\t}\n\n\tconst afterEsc = data.slice(1);\n\n\t// CSI sequences: ESC [\n\tif (afterEsc.startsWith(\"[\")) {\n\t\t// Check for old-style mouse sequence: ESC[M + 3 bytes\n\t\tif (afterEsc.startsWith(\"[M\")) {\n\t\t\t// Old-style mouse needs ESC[M + 3 bytes = 6 total\n\t\t\treturn data.length >= 6 ? \"complete\" : \"incomplete\";\n\t\t}\n\t\treturn isCompleteCsiSequence(data);\n\t}\n\n\t// OSC sequences: ESC ]\n\tif (afterEsc.startsWith(\"]\")) {\n\t\treturn isCompleteOscSequence(data);\n\t}\n\n\t// DCS sequences: ESC P ... ESC \\ (includes XTVersion responses)\n\tif (afterEsc.startsWith(\"P\")) {\n\t\treturn isCompleteDcsSequence(data);\n\t}\n\n\t// APC sequences: ESC _ ... ESC \\ (includes Kitty graphics responses)\n\tif (afterEsc.startsWith(\"_\")) {\n\t\treturn isCompleteApcSequence(data);\n\t}\n\n\t// SS3 sequences: ESC O\n\tif (afterEsc.startsWith(\"O\")) {\n\t\t// ESC O followed by a single character\n\t\treturn afterEsc.length >= 2 ? \"complete\" : \"incomplete\";\n\t}\n\n\t// Meta key sequences: ESC followed by a single character\n\tif (afterEsc.length === 1) {\n\t\treturn \"complete\";\n\t}\n\n\t// Unknown escape sequence - treat as complete\n\treturn \"complete\";\n}\n\n/**\n * Check if CSI sequence is complete\n * CSI sequences: ESC [ ... followed by a final byte (0x40-0x7E)\n */\nfunction isCompleteCsiSequence(data: string): \"complete\" | \"incomplete\" {\n\tif (!data.startsWith(`${ESC}[`)) {\n\t\treturn \"complete\";\n\t}\n\n\t// Need at least ESC [ and one more character\n\tif (data.length < 3) {\n\t\treturn \"incomplete\";\n\t}\n\n\tconst payload = data.slice(2);\n\n\t// CSI sequences end with a byte in the range 0x40-0x7E (@-~)\n\t// This includes all letters and several special characters\n\tconst lastChar = payload[payload.length - 1];\n\tconst lastCharCode = lastChar.charCodeAt(0);\n\n\tif (lastCharCode >= 0x40 && lastCharCode <= 0x7e) {\n\t\t// Special handling for SGR mouse sequences\n\t\t// Format: ESC[<B;X;Ym or ESC[<B;X;YM\n\t\tif (payload.startsWith(\"<\")) {\n\t\t\t// Must have format: <digits;digits;digits[Mm]\n\t\t\tconst mouseMatch = /^<\\d+;\\d+;\\d+[Mm]$/.test(payload);\n\t\t\tif (mouseMatch) {\n\t\t\t\treturn \"complete\";\n\t\t\t}\n\t\t\t// If it ends with M or m but doesn't match the pattern, still incomplete\n\t\t\tif (lastChar === \"M\" || lastChar === \"m\") {\n\t\t\t\t// Check if we have the right structure\n\t\t\t\tconst parts = payload.slice(1, -1).split(\";\");\n\t\t\t\tif (parts.length === 3 && parts.every((p) => /^\\d+$/.test(p))) {\n\t\t\t\t\treturn \"complete\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn \"incomplete\";\n\t\t}\n\n\t\treturn \"complete\";\n\t}\n\n\treturn \"incomplete\";\n}\n\n/**\n * Check if OSC sequence is complete\n * OSC sequences: ESC ] ... ST (where ST is ESC \\ or BEL)\n */\nfunction isCompleteOscSequence(data: string): \"complete\" | \"incomplete\" {\n\tif (!data.startsWith(`${ESC}]`)) {\n\t\treturn \"complete\";\n\t}\n\n\t// OSC sequences end with ST (ESC \\) or BEL (\\x07)\n\tif (data.endsWith(`${ESC}\\\\`) || data.endsWith(\"\\x07\")) {\n\t\treturn \"complete\";\n\t}\n\n\treturn \"incomplete\";\n}\n\n/**\n * Check if DCS (Device Control String) sequence is complete\n * DCS sequences: ESC P ... ST (where ST is ESC \\)\n * Used for XTVersion responses like ESC P >| ... ESC \\\n */\nfunction isCompleteDcsSequence(data: string): \"complete\" | \"incomplete\" {\n\tif (!data.startsWith(`${ESC}P`)) {\n\t\treturn \"complete\";\n\t}\n\n\t// DCS sequences end with ST (ESC \\)\n\tif (data.endsWith(`${ESC}\\\\`)) {\n\t\treturn \"complete\";\n\t}\n\n\treturn \"incomplete\";\n}\n\n/**\n * Check if APC (Application Program Command) sequence is complete\n * APC sequences: ESC _ ... ST (where ST is ESC \\)\n * Used for Kitty graphics responses like ESC _ G ... ESC \\\n */\nfunction isCompleteApcSequence(data: string): \"complete\" | \"incomplete\" {\n\tif (!data.startsWith(`${ESC}_`)) {\n\t\treturn \"complete\";\n\t}\n\n\t// APC sequences end with ST (ESC \\)\n\tif (data.endsWith(`${ESC}\\\\`)) {\n\t\treturn \"complete\";\n\t}\n\n\treturn \"incomplete\";\n}\n\n/**\n * Split accumulated buffer into complete sequences\n */\nfunction parseUnmodifiedKittyPrintableCodepoint(sequence: string): number | undefined {\n\tconst match = sequence.match(/^\\x1b\\[(\\d+)(?::\\d*)?(?::\\d+)?u$/);\n\tif (!match) return undefined;\n\n\tconst codepoint = parseInt(match[1]!, 10);\n\treturn codepoint >= 32 ? codepoint : undefined;\n}\n\nfunction extractCompleteSequences(buffer: string): { sequences: string[]; remainder: string } {\n\tconst sequences: string[] = [];\n\tlet pos = 0;\n\n\twhile (pos < buffer.length) {\n\t\tconst remaining = buffer.slice(pos);\n\n\t\t// Try to extract a sequence starting at this position\n\t\tif (remaining.startsWith(ESC)) {\n\t\t\t// Find the end of this escape sequence\n\t\t\tlet seqEnd = 1;\n\t\t\twhile (seqEnd <= remaining.length) {\n\t\t\t\tconst candidate = remaining.slice(0, seqEnd);\n\t\t\t\tconst status = isCompleteSequence(candidate);\n\n\t\t\t\tif (status === \"complete\") {\n\t\t\t\t\t// WezTerm with enable_kitty_keyboard sends the Escape key press as a\n\t\t\t\t\t// raw '\\x1b' byte (simple text path in encode_kitty, ignoring\n\t\t\t\t\t// DISAMBIGUATE_ESCAPE_CODES) and the release as a full Kitty CSI-u\n\t\t\t\t\t// sequence. These arrive concatenated as '\\x1b\\x1b[27;...u'.\n\t\t\t\t\t// The buffer would normally treat '\\x1b\\x1b' as a complete meta-key\n\t\t\t\t\t// sequence (ESC + single char), leaving '[27;...u' to be typed as\n\t\t\t\t\t// plain text. If the character immediately following '\\x1b\\x1b'\n\t\t\t\t\t// would begin a new escape sequence, emit only the first ESC and\n\t\t\t\t\t// restart from the second.\n\t\t\t\t\tif (candidate === \"\\x1b\\x1b\") {\n\t\t\t\t\t\tconst nextChar = remaining[seqEnd];\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tnextChar === \"[\" || // CSI\n\t\t\t\t\t\t\tnextChar === \"]\" || // OSC\n\t\t\t\t\t\t\tnextChar === \"O\" || // SS3\n\t\t\t\t\t\t\tnextChar === \"P\" || // DCS\n\t\t\t\t\t\t\tnextChar === \"_\" // APC\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tsequences.push(ESC);\n\t\t\t\t\t\t\tpos += 1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tsequences.push(candidate);\n\t\t\t\t\tpos += seqEnd;\n\t\t\t\t\tbreak;\n\t\t\t\t} else if (status === \"incomplete\") {\n\t\t\t\t\tseqEnd++;\n\t\t\t\t} else {\n\t\t\t\t\t// Should not happen when starting with ESC\n\t\t\t\t\tsequences.push(candidate);\n\t\t\t\t\tpos += seqEnd;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (seqEnd > remaining.length) {\n\t\t\t\treturn { sequences, remainder: remaining };\n\t\t\t}\n\t\t} else {\n\t\t\tconst codepoint = remaining.codePointAt(0)!;\n\t\t\tconst character = String.fromCodePoint(codepoint);\n\t\t\tsequences.push(character);\n\t\t\tpos += character.length;\n\t\t}\n\t}\n\n\treturn { sequences, remainder: \"\" };\n}\n\nexport type StdinBufferOptions = {\n\t/**\n\t * Maximum time to wait for an incomplete sequence such as CSI or mouse\n\t * (default: 50ms).\n\t */\n\ttimeout?: number;\n\t/**\n\t * Maximum time to wait after a lone ESC before treating it as Escape\n\t * (default: 10ms). Increase for high-latency Alt+key input (SSH).\n\t */\n\tescapeTimeout?: number;\n};\n\nexport type StdinBufferEventMap = {\n\tdata: [string];\n\tpaste: [string];\n};\n\n/**\n * Buffers stdin input and emits complete sequences via the 'data' event.\n * Handles partial escape sequences that arrive across multiple chunks.\n */\nexport class StdinBuffer extends EventEmitter<StdinBufferEventMap> {\n\tprivate buffer: string = \"\";\n\tprivate timeout: ReturnType<typeof setTimeout> | null = null;\n\tprivate readonly timeoutMs: number;\n\tprivate readonly escapeTimeoutMs: number;\n\tprivate mouseFragmentStartedAt?: number;\n\tprivate discardingMouseFragment = false;\n\tprivate pasteMode: boolean = false;\n\tprivate pasteBuffer: string = \"\";\n\tprivate pendingKittyPrintableCodepoint: number | undefined;\n\tprivate decoder: StatefulStringDecoder = new StringDecoder(\"utf8\");\n\n\tconstructor(options: StdinBufferOptions = {}) {\n\t\tsuper();\n\t\tthis.timeoutMs = options.timeout ?? DEFAULT_SEQUENCE_TIMEOUT_MS;\n\t\tthis.escapeTimeoutMs = options.escapeTimeout ?? DEFAULT_ESCAPE_TIMEOUT_MS;\n\t}\n\n\tpublic process(data: string | Buffer): void {\n\t\t// Clear any pending timeout\n\t\tif (this.timeout) {\n\t\t\tclearTimeout(this.timeout);\n\t\t\tthis.timeout = null;\n\t\t}\n\n\t\tlet str: string;\n\t\tlet decodedFromBuffer = false;\n\t\tif (Buffer.isBuffer(data)) {\n\t\t\tconst hasPendingUtf8Bytes = (this.decoder.lastNeed ?? 0) > 0;\n\t\t\tif (!hasPendingUtf8Bytes && data.length === 1 && data[0]! >= 0x80 && data[0]! < 0xc2) {\n\t\t\t\tconst byte = data[0]! - 128;\n\t\t\t\tstr = `\\x1b${String.fromCharCode(byte)}`;\n\t\t\t} else {\n\t\t\t\tstr = this.decoder.write(data);\n\t\t\t\tdecodedFromBuffer = true;\n\t\t\t}\n\t\t} else {\n\t\t\tstr = data;\n\t\t}\n\n\t\tif (str.length === 0 && this.buffer.length === 0) {\n\t\t\tif (!decodedFromBuffer) {\n\t\t\t\tthis.emitDataSequence(\"\");\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.discardingMouseFragment) {\n\t\t\tconst terminator = str.search(/[\\x40-\\x7e]/);\n\t\t\tconst escapeIndex = str.indexOf(ESC);\n\t\t\tif (escapeIndex !== -1 && (terminator === -1 || escapeIndex < terminator)) {\n\t\t\t\tstr = str.slice(escapeIndex);\n\t\t\t} else {\n\t\t\t\tif (terminator === -1) return;\n\t\t\t\tstr = str.slice(terminator + 1);\n\t\t\t}\n\t\t\tthis.discardingMouseFragment = false;\n\t\t}\n\t\tthis.buffer += str;\n\n\t\tif (this.pasteMode) {\n\t\t\tthis.pasteBuffer += this.buffer;\n\t\t\tthis.buffer = \"\";\n\n\t\t\tconst endIndex = this.pasteBuffer.indexOf(BRACKETED_PASTE_END);\n\t\t\tif (endIndex !== -1) {\n\t\t\t\tconst pastedContent = this.pasteBuffer.slice(0, endIndex);\n\t\t\t\tconst remaining = this.pasteBuffer.slice(endIndex + BRACKETED_PASTE_END.length);\n\n\t\t\t\tthis.pasteMode = false;\n\t\t\t\tthis.pasteBuffer = \"\";\n\t\t\t\tthis.pendingKittyPrintableCodepoint = undefined;\n\n\t\t\t\tthis.emit(\"paste\", pastedContent);\n\n\t\t\t\tif (remaining.length > 0) {\n\t\t\t\t\tthis.process(remaining);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst startIndex = this.buffer.indexOf(BRACKETED_PASTE_START);\n\t\tif (startIndex !== -1) {\n\t\t\tif (startIndex > 0) {\n\t\t\t\tconst beforePaste = this.buffer.slice(0, startIndex);\n\t\t\t\tconst result = extractCompleteSequences(beforePaste);\n\t\t\t\tfor (const sequence of result.sequences) {\n\t\t\t\t\tthis.emitDataSequence(sequence);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.pendingKittyPrintableCodepoint = undefined;\n\t\t\tthis.buffer = this.buffer.slice(startIndex + BRACKETED_PASTE_START.length);\n\t\t\tthis.pasteMode = true;\n\t\t\tthis.pasteBuffer = this.buffer;\n\t\t\tthis.buffer = \"\";\n\n\t\t\tconst endIndex = this.pasteBuffer.indexOf(BRACKETED_PASTE_END);\n\t\t\tif (endIndex !== -1) {\n\t\t\t\tconst pastedContent = this.pasteBuffer.slice(0, endIndex);\n\t\t\t\tconst remaining = this.pasteBuffer.slice(endIndex + BRACKETED_PASTE_END.length);\n\n\t\t\t\tthis.pasteMode = false;\n\t\t\t\tthis.pasteBuffer = \"\";\n\t\t\t\tthis.pendingKittyPrintableCodepoint = undefined;\n\n\t\t\t\tthis.emit(\"paste\", pastedContent);\n\n\t\t\t\tif (remaining.length > 0) {\n\t\t\t\t\tthis.process(remaining);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst result = extractCompleteSequences(this.buffer);\n\t\tthis.buffer = result.remainder;\n\t\tif (this.buffer.startsWith(\"\\x1b[<\")) {\n\t\t\tthis.mouseFragmentStartedAt ??= Date.now();\n\t\t\tif (this.buffer.length > 64) {\n\t\t\t\tthis.buffer = \"\";\n\t\t\t\tthis.discardingMouseFragment = true;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.mouseFragmentStartedAt = undefined;\n\t\t}\n\n\t\tfor (const sequence of result.sequences) {\n\t\t\tthis.emitDataSequence(sequence);\n\t\t}\n\n\t\tif (this.buffer.length > 0) {\n\t\t\tconst timeoutMs = this.buffer === ESC ? this.escapeTimeoutMs : this.timeoutMs;\n\t\t\tthis.timeout = setTimeout(() => {\n\t\t\t\tconst flushed = this.flush();\n\n\t\t\t\tfor (const sequence of flushed) {\n\t\t\t\t\tthis.emitDataSequence(sequence);\n\t\t\t\t}\n\t\t\t}, timeoutMs);\n\t\t}\n\t}\n\n\tprivate emitDataSequence(sequence: string): void {\n\t\tconst rawCodepoint = sequence.length === 1 ? sequence.codePointAt(0) : undefined;\n\t\tif (rawCodepoint !== undefined && rawCodepoint === this.pendingKittyPrintableCodepoint) {\n\t\t\tthis.pendingKittyPrintableCodepoint = undefined;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.pendingKittyPrintableCodepoint = parseUnmodifiedKittyPrintableCodepoint(sequence);\n\t\tthis.emit(\"data\", sequence);\n\t}\n\n\tflush(): string[] {\n\t\tif (this.timeout) {\n\t\t\tclearTimeout(this.timeout);\n\t\t\tthis.timeout = null;\n\t\t}\n\n\t\tif (this.buffer.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.buffer.startsWith(\"\\x1b[<\")) {\n\t\t\tconst remaining = 750 - (Date.now() - (this.mouseFragmentStartedAt ?? Date.now()));\n\t\t\tif (remaining > 0 && this.buffer.length <= 64) {\n\t\t\t\tthis.timeout = setTimeout(() => this.flush(), remaining);\n\t\t\t} else {\n\t\t\t\tthis.buffer = \"\";\n\t\t\t\tthis.mouseFragmentStartedAt = undefined;\n\t\t\t\tthis.discardingMouseFragment = true;\n\t\t\t}\n\t\t\treturn [];\n\t\t}\n\n\t\tconst sequences = [this.buffer];\n\t\tthis.buffer = \"\";\n\t\tthis.pendingKittyPrintableCodepoint = undefined;\n\t\treturn sequences;\n\t}\n\n\tclear(): void {\n\t\tif (this.timeout) {\n\t\t\tclearTimeout(this.timeout);\n\t\t\tthis.timeout = null;\n\t\t}\n\t\tthis.buffer = \"\";\n\t\tthis.pasteMode = false;\n\t\tthis.pasteBuffer = \"\";\n\t\tthis.mouseFragmentStartedAt = undefined;\n\t\tthis.discardingMouseFragment = false;\n\t\tthis.pendingKittyPrintableCodepoint = undefined;\n\t\tthis.decoder = new StringDecoder(\"utf8\");\n\t}\n\n\tgetBuffer(): string {\n\t\treturn this.buffer;\n\t}\n\n\tdestroy(): void {\n\t\tthis.clear();\n\t}\n}\n"]}
|
package/dist/terminal.d.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
export interface CursorPosition {
|
|
2
|
+
row: number;
|
|
3
|
+
column: number;
|
|
4
|
+
page?: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function parseCursorPositionResponse(sequence: string): CursorPosition | undefined;
|
|
1
7
|
export type KeyboardProtocolNegotiationSequence = {
|
|
2
8
|
type: "kitty-flags";
|
|
3
9
|
flags: number;
|
|
4
10
|
} | {
|
|
5
11
|
type: "device-attributes";
|
|
6
|
-
}
|
|
12
|
+
} | ({
|
|
13
|
+
type: "cursor-position";
|
|
14
|
+
} & CursorPosition);
|
|
7
15
|
export declare function parseKeyboardProtocolNegotiationSequence(sequence: string): KeyboardProtocolNegotiationSequence | undefined;
|
|
8
16
|
export declare function isAppleTerminalSession(): boolean;
|
|
9
17
|
/**
|
|
@@ -31,6 +39,10 @@ export interface Terminal {
|
|
|
31
39
|
* @param idleMs - Exit early if no input arrives within this time (default: 50ms)
|
|
32
40
|
*/
|
|
33
41
|
drainInput(maxMs?: number, idleMs?: number): Promise<void>;
|
|
42
|
+
/** Optional for virtual/custom terminals that cannot answer private DECXCPR. */
|
|
43
|
+
queryCursorPosition?(): Promise<CursorPosition | undefined>;
|
|
44
|
+
/** Observe external writes without changing their output policy. */
|
|
45
|
+
observeExternalWrites?(listener: () => void): () => void;
|
|
34
46
|
write(data: string): void;
|
|
35
47
|
get columns(): number;
|
|
36
48
|
get rows(): number;
|
|
@@ -67,6 +79,11 @@ export declare class ProcessTerminal implements Terminal {
|
|
|
67
79
|
private onExternalStdoutWrite?;
|
|
68
80
|
private originalStdoutWrite?;
|
|
69
81
|
private rawStdoutWrite?;
|
|
82
|
+
private originalStderrWrite?;
|
|
83
|
+
private readonly externalWriteObservers;
|
|
84
|
+
private keyboardNegotiationSettled;
|
|
85
|
+
private cursorQueryTimedOut;
|
|
86
|
+
private cursorQuery?;
|
|
70
87
|
private forwardingExternalWrite;
|
|
71
88
|
private inputHandler?;
|
|
72
89
|
private resizeHandler?;
|
|
@@ -74,6 +91,7 @@ export declare class ProcessTerminal implements Terminal {
|
|
|
74
91
|
private _modifyOtherKeysActive;
|
|
75
92
|
private keyboardProtocolPushed;
|
|
76
93
|
private keyboardProtocolNegotiationBuffer;
|
|
94
|
+
private discardingPrivateResponse;
|
|
77
95
|
private keyboardProtocolBufferFlushTimer?;
|
|
78
96
|
private stdinBuffer?;
|
|
79
97
|
private stdinDataHandler?;
|
|
@@ -83,6 +101,12 @@ export declare class ProcessTerminal implements Terminal {
|
|
|
83
101
|
private writeLogPath;
|
|
84
102
|
constructor(options?: ProcessTerminalOptions);
|
|
85
103
|
get kittyProtocolActive(): boolean;
|
|
104
|
+
queryCursorPosition(): Promise<CursorPosition | undefined>;
|
|
105
|
+
private issueCursorQuery;
|
|
106
|
+
private settleCursorQuery;
|
|
107
|
+
observeExternalWrites(listener: () => void): () => void;
|
|
108
|
+
private noteExternalWrite;
|
|
109
|
+
private installExternalStderrObserver;
|
|
86
110
|
private rawWrite;
|
|
87
111
|
private installExternalStdoutGuard;
|
|
88
112
|
private removeExternalStdoutGuard;
|
package/dist/terminal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"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"}
|
package/dist/terminal.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
|
-
import { createRequire } from "node:module";
|
|
3
2
|
import * as path from "node:path";
|
|
4
3
|
import { setKittyProtocolActive } from "./keys.js";
|
|
5
4
|
import { isMultiplexerSession } from "./mux.js";
|
|
6
5
|
import { isNativeModifierPressed } from "./native-modifiers.js";
|
|
7
|
-
import {
|
|
6
|
+
import { getNativePlatformHelper } from "./native-platform.js";
|
|
8
7
|
import { StdinBuffer } from "./stdin-buffer.js";
|
|
9
|
-
const cjsRequire = createRequire(import.meta.url);
|
|
10
8
|
const TERMINAL_PROGRESS_KEEPALIVE_MS = 1000;
|
|
11
9
|
const TERMINAL_PROGRESS_ACTIVE_SEQUENCE = "\x1b]9;4;3\x07";
|
|
12
10
|
const TERMINAL_PROGRESS_CLEAR_SEQUENCE = "\x1b]9;4;0\x07";
|
|
@@ -25,7 +23,20 @@ const DEAD_TERMINAL_ERRNOS = new Set([EIO_ERRNO, EPIPE_ERRNO]);
|
|
|
25
23
|
const ERRNO_IN_MESSAGE_PATTERN = /errno:\s*(\d+)/;
|
|
26
24
|
const KEYBOARD_PROTOCOL_RESPONSE_FRAGMENT_TIMEOUT_MS = 150;
|
|
27
25
|
const KITTY_KEYBOARD_PROTOCOL_QUERY = `\x1b[>${DESIRED_KITTY_KEYBOARD_PROTOCOL_FLAGS}u\x1b[?u\x1b[c`;
|
|
26
|
+
export function parseCursorPositionResponse(sequence) {
|
|
27
|
+
const match = /^\x1b\[\?(\d+);(\d+)(?:;(\d+))?R$/.exec(sequence);
|
|
28
|
+
return match
|
|
29
|
+
? {
|
|
30
|
+
row: Number(match[1]),
|
|
31
|
+
column: Number(match[2]),
|
|
32
|
+
...(match[3] === undefined ? {} : { page: Number(match[3]) }),
|
|
33
|
+
}
|
|
34
|
+
: undefined;
|
|
35
|
+
}
|
|
28
36
|
export function parseKeyboardProtocolNegotiationSequence(sequence) {
|
|
37
|
+
const cursorPosition = parseCursorPositionResponse(sequence);
|
|
38
|
+
if (cursorPosition)
|
|
39
|
+
return { type: "cursor-position", ...cursorPosition };
|
|
29
40
|
const kittyFlags = sequence.match(/^\x1b\[\?(\d+)u$/);
|
|
30
41
|
if (kittyFlags) {
|
|
31
42
|
return { type: "kitty-flags", flags: Number.parseInt(kittyFlags[1], 10) };
|
|
@@ -168,11 +179,15 @@ export function resolveEscapeTimeoutMs(env = process.env) {
|
|
|
168
179
|
export class ProcessTerminal {
|
|
169
180
|
constructor(options) {
|
|
170
181
|
this.wasRaw = false;
|
|
182
|
+
this.externalWriteObservers = new Set();
|
|
183
|
+
this.keyboardNegotiationSettled = false;
|
|
184
|
+
this.cursorQueryTimedOut = false;
|
|
171
185
|
this.forwardingExternalWrite = false;
|
|
172
186
|
this._kittyProtocolActive = false;
|
|
173
187
|
this._modifyOtherKeysActive = false;
|
|
174
188
|
this.keyboardProtocolPushed = false;
|
|
175
189
|
this.keyboardProtocolNegotiationBuffer = "";
|
|
190
|
+
this.discardingPrivateResponse = false;
|
|
176
191
|
this.writeLogPath = (() => {
|
|
177
192
|
const env = process.env.PI_TUI_WRITE_LOG || "";
|
|
178
193
|
if (!env)
|
|
@@ -194,6 +209,63 @@ export class ProcessTerminal {
|
|
|
194
209
|
get kittyProtocolActive() {
|
|
195
210
|
return this._kittyProtocolActive;
|
|
196
211
|
}
|
|
212
|
+
queryCursorPosition() {
|
|
213
|
+
if (this.cursorQuery)
|
|
214
|
+
return this.cursorQuery.promise;
|
|
215
|
+
if (!this.inputHandler || this.cursorQueryTimedOut)
|
|
216
|
+
return Promise.resolve(undefined);
|
|
217
|
+
let resolve;
|
|
218
|
+
const promise = new Promise((settle) => {
|
|
219
|
+
resolve = settle;
|
|
220
|
+
});
|
|
221
|
+
const timer = setTimeout(() => {
|
|
222
|
+
// CPR has no request id: after a timeout a late reply cannot safely be
|
|
223
|
+
// associated with a newer query. Stay fail-closed until the next start.
|
|
224
|
+
this.cursorQueryTimedOut = true;
|
|
225
|
+
this.settleCursorQuery(undefined);
|
|
226
|
+
}, 750);
|
|
227
|
+
this.cursorQuery = { promise, resolve, timer, issued: false };
|
|
228
|
+
this.issueCursorQuery();
|
|
229
|
+
return promise;
|
|
230
|
+
}
|
|
231
|
+
issueCursorQuery() {
|
|
232
|
+
if (!this.keyboardNegotiationSettled || !this.cursorQuery || this.cursorQuery.issued)
|
|
233
|
+
return;
|
|
234
|
+
this.cursorQuery.issued = true;
|
|
235
|
+
this.rawWrite("\x1b[?6n");
|
|
236
|
+
}
|
|
237
|
+
settleCursorQuery(position) {
|
|
238
|
+
const pending = this.cursorQuery;
|
|
239
|
+
if (!pending)
|
|
240
|
+
return;
|
|
241
|
+
this.cursorQuery = undefined;
|
|
242
|
+
clearTimeout(pending.timer);
|
|
243
|
+
pending.resolve(position);
|
|
244
|
+
}
|
|
245
|
+
observeExternalWrites(listener) {
|
|
246
|
+
this.externalWriteObservers.add(listener);
|
|
247
|
+
if (this.inputHandler) {
|
|
248
|
+
this.installExternalStdoutGuard();
|
|
249
|
+
this.installExternalStderrObserver();
|
|
250
|
+
}
|
|
251
|
+
return () => {
|
|
252
|
+
this.externalWriteObservers.delete(listener);
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
noteExternalWrite() {
|
|
256
|
+
for (const listener of this.externalWriteObservers)
|
|
257
|
+
listener();
|
|
258
|
+
}
|
|
259
|
+
installExternalStderrObserver() {
|
|
260
|
+
if (this.originalStderrWrite || this.externalWriteObservers.size === 0)
|
|
261
|
+
return;
|
|
262
|
+
const original = process.stderr.write;
|
|
263
|
+
this.originalStderrWrite = original;
|
|
264
|
+
process.stderr.write = ((...args) => {
|
|
265
|
+
this.noteExternalWrite();
|
|
266
|
+
return original.apply(process.stderr, args);
|
|
267
|
+
});
|
|
268
|
+
}
|
|
197
269
|
rawWrite(data) {
|
|
198
270
|
if (this.rawStdoutWrite) {
|
|
199
271
|
this.rawStdoutWrite(data);
|
|
@@ -203,7 +275,7 @@ export class ProcessTerminal {
|
|
|
203
275
|
}
|
|
204
276
|
installExternalStdoutGuard() {
|
|
205
277
|
const handler = this.onExternalStdoutWrite;
|
|
206
|
-
if (!handler || this.originalStdoutWrite) {
|
|
278
|
+
if ((!handler && this.externalWriteObservers.size === 0) || this.originalStdoutWrite) {
|
|
207
279
|
return;
|
|
208
280
|
}
|
|
209
281
|
this.originalStdoutWrite = process.stdout.write;
|
|
@@ -213,7 +285,8 @@ export class ProcessTerminal {
|
|
|
213
285
|
const cb = typeof encodingOrCallback === "function" ? encodingOrCallback : callback;
|
|
214
286
|
const encoding = typeof encodingOrCallback === "string" ? encodingOrCallback : undefined;
|
|
215
287
|
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString(encoding);
|
|
216
|
-
|
|
288
|
+
this.noteExternalWrite();
|
|
289
|
+
if (!handler || this.forwardingExternalWrite) {
|
|
217
290
|
rawWrite(text);
|
|
218
291
|
cb?.(null);
|
|
219
292
|
return true;
|
|
@@ -245,6 +318,10 @@ export class ProcessTerminal {
|
|
|
245
318
|
}
|
|
246
319
|
start(onInput, onResize) {
|
|
247
320
|
this.installExternalStdoutGuard();
|
|
321
|
+
this.installExternalStderrObserver();
|
|
322
|
+
this.keyboardNegotiationSettled = !keyboardEnhancementEnabled();
|
|
323
|
+
this.cursorQueryTimedOut = false;
|
|
324
|
+
this.discardingPrivateResponse = false;
|
|
248
325
|
this.inputHandler = onInput;
|
|
249
326
|
this.resizeHandler = onResize;
|
|
250
327
|
// Save previous state and enable raw mode
|
|
@@ -296,6 +373,15 @@ export class ProcessTerminal {
|
|
|
296
373
|
this.stdinBuffer = new StdinBuffer({ escapeTimeout: resolveEscapeTimeoutMs() });
|
|
297
374
|
// Forward individual sequences to the input handler
|
|
298
375
|
this.stdinBuffer.on("data", (sequence) => {
|
|
376
|
+
if (this.discardingPrivateResponse) {
|
|
377
|
+
if (sequence.startsWith("\x1b"))
|
|
378
|
+
this.discardingPrivateResponse = false;
|
|
379
|
+
else {
|
|
380
|
+
if (/[\x40-\x7e]/.test(sequence))
|
|
381
|
+
this.discardingPrivateResponse = false;
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
299
385
|
const negotiationSequence = this.readKeyboardProtocolNegotiationSequence(sequence);
|
|
300
386
|
if (negotiationSequence === "pending") {
|
|
301
387
|
this.scheduleKeyboardProtocolNegotiationBufferFlush();
|
|
@@ -347,6 +433,15 @@ export class ProcessTerminal {
|
|
|
347
433
|
if (!negotiationSequence)
|
|
348
434
|
return false;
|
|
349
435
|
this.clearKeyboardProtocolNegotiationBuffer();
|
|
436
|
+
if (negotiationSequence.type === "cursor-position") {
|
|
437
|
+
if (this.cursorQuery?.issued) {
|
|
438
|
+
const { type: _type, ...position } = negotiationSequence;
|
|
439
|
+
this.settleCursorQuery(position);
|
|
440
|
+
}
|
|
441
|
+
return true;
|
|
442
|
+
}
|
|
443
|
+
this.keyboardNegotiationSettled = true;
|
|
444
|
+
this.issueCursorQuery();
|
|
350
445
|
if (negotiationSequence.type === "kitty-flags") {
|
|
351
446
|
if (negotiationSequence.flags !== 0) {
|
|
352
447
|
this.disableModifyOtherKeys();
|
|
@@ -396,11 +491,15 @@ export class ProcessTerminal {
|
|
|
396
491
|
this.clearKeyboardProtocolNegotiationBufferFlushTimer();
|
|
397
492
|
this.keyboardProtocolNegotiationBuffer = "";
|
|
398
493
|
}
|
|
399
|
-
flushKeyboardProtocolNegotiationBufferAsInput() {
|
|
494
|
+
flushKeyboardProtocolNegotiationBufferAsInput(discardTail = false) {
|
|
400
495
|
if (!this.keyboardProtocolNegotiationBuffer)
|
|
401
496
|
return;
|
|
402
497
|
const sequence = this.keyboardProtocolNegotiationBuffer;
|
|
403
498
|
this.clearKeyboardProtocolNegotiationBuffer();
|
|
499
|
+
if (/^\x1b\[\?[\d;]*$/.test(sequence)) {
|
|
500
|
+
this.discardingPrivateResponse = discardTail;
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
404
503
|
this.forwardInputSequence(sequence);
|
|
405
504
|
}
|
|
406
505
|
scheduleKeyboardProtocolNegotiationBufferFlush() {
|
|
@@ -408,7 +507,7 @@ export class ProcessTerminal {
|
|
|
408
507
|
return;
|
|
409
508
|
this.keyboardProtocolBufferFlushTimer = setTimeout(() => {
|
|
410
509
|
this.keyboardProtocolBufferFlushTimer = undefined;
|
|
411
|
-
this.flushKeyboardProtocolNegotiationBufferAsInput();
|
|
510
|
+
this.flushKeyboardProtocolNegotiationBufferAsInput(true);
|
|
412
511
|
}, KEYBOARD_PROTOCOL_RESPONSE_FRAGMENT_TIMEOUT_MS);
|
|
413
512
|
}
|
|
414
513
|
clearKeyboardProtocolNegotiationBufferFlushTimer() {
|
|
@@ -446,23 +545,7 @@ export class ProcessTerminal {
|
|
|
446
545
|
if (process.platform !== "win32")
|
|
447
546
|
return;
|
|
448
547
|
try {
|
|
449
|
-
|
|
450
|
-
if (arch !== "x64" && arch !== "arm64")
|
|
451
|
-
return;
|
|
452
|
-
// Dynamic require so non-Windows and bundled/browser paths never load the
|
|
453
|
-
// native helper. Installed packages resolve it from pi-tui; standalone
|
|
454
|
-
// binaries resolve the copy next to the executable.
|
|
455
|
-
const nativePath = path.join("native", "win32", "prebuilds", `win32-${arch}`, "win32-console-mode.node");
|
|
456
|
-
for (const modulePath of getNativeModuleCandidates(nativePath)) {
|
|
457
|
-
try {
|
|
458
|
-
const helper = cjsRequire(modulePath);
|
|
459
|
-
helper.enableVirtualTerminalInput?.();
|
|
460
|
-
return;
|
|
461
|
-
}
|
|
462
|
-
catch {
|
|
463
|
-
// Try the next possible packaging location.
|
|
464
|
-
}
|
|
465
|
-
}
|
|
548
|
+
getNativePlatformHelper()?.enableVirtualTerminalInput?.();
|
|
466
549
|
}
|
|
467
550
|
catch {
|
|
468
551
|
// Native helper not available — Shift+Tab won't be distinguishable from Tab.
|
|
@@ -505,6 +588,11 @@ export class ProcessTerminal {
|
|
|
505
588
|
}
|
|
506
589
|
}
|
|
507
590
|
stop() {
|
|
591
|
+
this.settleCursorQuery(undefined);
|
|
592
|
+
if (this.originalStderrWrite) {
|
|
593
|
+
process.stderr.write = this.originalStderrWrite;
|
|
594
|
+
this.originalStderrWrite = undefined;
|
|
595
|
+
}
|
|
508
596
|
if (this.clearProgressInterval()) {
|
|
509
597
|
this.rawWrite(TERMINAL_PROGRESS_CLEAR_SEQUENCE);
|
|
510
598
|
}
|