@f5-sales-demo/pi-tui 21.24.4 → 21.25.0
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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@f5-sales-demo/pi-tui",
|
|
4
|
-
"version": "21.
|
|
4
|
+
"version": "21.25.0",
|
|
5
5
|
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
|
|
6
6
|
"homepage": "https://github.com/f5-sales-demo/xcsh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"fmt": "biome format --write ."
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@f5-sales-demo/pi-natives": "21.
|
|
41
|
-
"@f5-sales-demo/pi-utils": "21.
|
|
40
|
+
"@f5-sales-demo/pi-natives": "21.25.0",
|
|
41
|
+
"@f5-sales-demo/pi-utils": "21.25.0",
|
|
42
42
|
"marked": "18.0.11"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
import { getKeybindings } from "../keybindings";
|
|
1
|
+
import { getKeybindings, type Keybinding } from "../keybindings";
|
|
2
|
+
import { matchesKey } from "../keys";
|
|
2
3
|
import { Loader } from "./loader";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
* Loader that
|
|
6
|
+
* Loader that requests interruption with the application's interrupt binding (Ctrl+C by default).
|
|
6
7
|
* Extends Loader with an AbortSignal for cancelling async operations.
|
|
7
8
|
*
|
|
8
9
|
* @example
|
|
9
10
|
* const loader = new CancellableLoader(tui, cyan, dim, "Working...");
|
|
10
|
-
* loader.onAbort
|
|
11
|
+
* // Keep tracking work until it acknowledges loader.signal; onAbort is only a request.
|
|
11
12
|
* doWork(loader.signal).then(done);
|
|
12
13
|
*/
|
|
13
14
|
export class CancellableLoader extends Loader {
|
|
14
15
|
#abortController = new AbortController();
|
|
15
16
|
|
|
16
|
-
/** Called when
|
|
17
|
+
/** Called once when interruption is requested, not when work has necessarily stopped. */
|
|
17
18
|
onAbort?: () => void;
|
|
18
19
|
|
|
19
|
-
/** AbortSignal that is aborted when
|
|
20
|
+
/** AbortSignal that is aborted when interruption is requested. */
|
|
20
21
|
get signal(): AbortSignal {
|
|
21
22
|
return this.#abortController.signal;
|
|
22
23
|
}
|
|
@@ -28,7 +29,10 @@ export class CancellableLoader extends Loader {
|
|
|
28
29
|
|
|
29
30
|
handleInput(data: string): void {
|
|
30
31
|
const kb = getKeybindings();
|
|
31
|
-
|
|
32
|
+
// The optional application binding is supplied by downstream registry augmentation.
|
|
33
|
+
const interrupt = "app.interrupt" as Keybinding;
|
|
34
|
+
const requested = kb.getDefinition(interrupt) ? kb.matches(data, interrupt) : matchesKey(data, "ctrl+c");
|
|
35
|
+
if (requested && !this.aborted) {
|
|
32
36
|
this.#abortController.abort();
|
|
33
37
|
this.onAbort?.();
|
|
34
38
|
}
|
package/src/keybindings.ts
CHANGED
|
@@ -139,7 +139,7 @@ export const TUI_KEYBINDINGS = {
|
|
|
139
139
|
},
|
|
140
140
|
"tui.select.confirm": { defaultKeys: "enter", description: "Confirm selection" },
|
|
141
141
|
"tui.select.cancel": {
|
|
142
|
-
defaultKeys:
|
|
142
|
+
defaultKeys: "escape",
|
|
143
143
|
description: "Cancel selection",
|
|
144
144
|
},
|
|
145
145
|
} as const satisfies KeybindingDefinitions;
|
package/src/stdin-buffer.ts
CHANGED
|
@@ -211,6 +211,17 @@ function extractCompleteSequences(buffer: string): { sequences: string[]; remain
|
|
|
211
211
|
|
|
212
212
|
// Try to extract a sequence starting at this position
|
|
213
213
|
if (remaining.startsWith(ESC)) {
|
|
214
|
+
// Two adjacent ESC introducers are two independent sequences. This occurs
|
|
215
|
+
// when a user's Escape key races a terminal capability response such as
|
|
216
|
+
// DA1 (`ESC ESC[?1;2c`). Treating the pair as one Meta-Escape event strips
|
|
217
|
+
// the response introducer and leaks `[?1;2c` into the focused editor.
|
|
218
|
+
// Emitting the first Escape independently lets the next pass retain the
|
|
219
|
+
// complete response for the terminal-level filter.
|
|
220
|
+
if (remaining.startsWith(`${ESC}${ESC}`)) {
|
|
221
|
+
sequences.push(ESC);
|
|
222
|
+
pos++;
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
214
225
|
// Find the end of this escape sequence
|
|
215
226
|
let seqEnd = 1;
|
|
216
227
|
while (seqEnd <= remaining.length) {
|