@scelar/nodepod 1.0.4 → 1.0.6
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/dist/{child_process-53fMkug_.js → child_process-4ZrgCVFu.js} +8234 -8233
- package/dist/{child_process-53fMkug_.js.map → child_process-4ZrgCVFu.js.map} +1 -1
- package/dist/{child_process-lxSKECHq.cjs → child_process-Cao4lyrb.cjs} +7435 -7434
- package/dist/{child_process-lxSKECHq.cjs.map → child_process-Cao4lyrb.cjs.map} +1 -1
- package/dist/{index-C-TQIrdG.cjs → index-DuYo2yDs.cjs} +38842 -38005
- package/dist/index-DuYo2yDs.cjs.map +1 -0
- package/dist/{index-B8lyh_ti.js → index-HkVqijtm.js} +36923 -36065
- package/dist/index-HkVqijtm.js.map +1 -0
- package/dist/index.cjs +67 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +61 -59
- package/dist/memory-handler.d.ts +57 -0
- package/dist/memory-volume.d.ts +12 -2
- package/dist/packages/installer.d.ts +3 -0
- package/dist/persistence/idb-cache.d.ts +7 -0
- package/dist/polyfills/readline.d.ts +108 -87
- package/dist/script-engine.d.ts +3 -0
- package/dist/sdk/nodepod-process.d.ts +2 -1
- package/dist/sdk/nodepod.d.ts +20 -1
- package/dist/sdk/types.d.ts +5 -0
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/memory-handler.ts +168 -0
- package/src/memory-volume.ts +72 -8
- package/src/packages/installer.ts +49 -1
- package/src/packages/version-resolver.ts +421 -421
- package/src/persistence/idb-cache.ts +107 -0
- package/src/polyfills/child_process.ts +3 -0
- package/src/polyfills/events.ts +22 -4
- package/src/polyfills/readline.ts +593 -71
- package/src/polyfills/stream.ts +46 -0
- package/src/polyfills/wasi.ts +1306 -1306
- package/src/polyfills/zlib.ts +881 -881
- package/src/script-engine.ts +3722 -3694
- package/src/sdk/nodepod-process.ts +94 -86
- package/src/sdk/nodepod.ts +52 -6
- package/src/sdk/types.ts +82 -77
- package/src/threading/process-manager.ts +11 -0
- package/src/threading/worker-protocol.ts +358 -358
- package/dist/index-B8lyh_ti.js.map +0 -1
- package/dist/index-C-TQIrdG.cjs.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
// readline polyfill
|
|
2
|
-
//
|
|
1
|
+
// readline polyfill — createInterface, emitKeypressEvents, terminal helpers
|
|
2
|
+
// we track line/cursor on every keystroke because @clack reads rl.line directly
|
|
3
3
|
|
|
4
4
|
import { EventEmitter } from "./events";
|
|
5
5
|
import { ref as _elRef, unref as _elUnref } from "../helpers/event-loop";
|
|
6
6
|
|
|
7
|
-
//
|
|
7
|
+
// the wait loop checks this so it doesn't bail while the user is typing
|
|
8
8
|
let _activeInterfaceCount = 0;
|
|
9
9
|
|
|
10
10
|
export function getActiveInterfaceCount(): number {
|
|
@@ -26,17 +26,20 @@ export interface InterfaceConfig {
|
|
|
26
26
|
terminal?: boolean;
|
|
27
27
|
prompt?: string;
|
|
28
28
|
historySize?: number;
|
|
29
|
+
history?: string[];
|
|
30
|
+
removeHistoryDuplicates?: boolean;
|
|
29
31
|
completer?: (line: string) => [string[], string] | void;
|
|
30
32
|
crlfDelay?: number;
|
|
31
33
|
escapeCodeTimeout?: number;
|
|
32
34
|
tabSize?: number;
|
|
35
|
+
signal?: AbortSignal;
|
|
33
36
|
}
|
|
34
37
|
|
|
35
|
-
//
|
|
38
|
+
// turns raw data events into proper keypress events
|
|
36
39
|
|
|
37
40
|
const KEYPRESS_DECODER = Symbol("keypressDecoder");
|
|
38
41
|
|
|
39
|
-
//
|
|
42
|
+
// parses individual chars (including escape sequences) and fires keypress
|
|
40
43
|
function parseAndEmitKeypress(
|
|
41
44
|
stream: any,
|
|
42
45
|
char: string,
|
|
@@ -47,10 +50,11 @@ function parseAndEmitKeypress(
|
|
|
47
50
|
const seq = escapeBuf.join("");
|
|
48
51
|
|
|
49
52
|
if (seq.length >= 3 && seq[1] === "[") {
|
|
50
|
-
// CSI sequence
|
|
53
|
+
// CSI escape sequence (arrows, home, end, etc.)
|
|
51
54
|
const lastChar = seq[seq.length - 1];
|
|
52
55
|
if (/[A-Za-z~]/.test(lastChar)) {
|
|
53
|
-
|
|
56
|
+
let name = "";
|
|
57
|
+
let ctrl = false;
|
|
54
58
|
if (lastChar === "A") name = "up";
|
|
55
59
|
else if (lastChar === "B") name = "down";
|
|
56
60
|
else if (lastChar === "C") name = "right";
|
|
@@ -61,12 +65,14 @@ function parseAndEmitKeypress(
|
|
|
61
65
|
else if (seq === "\x1b[2~") name = "insert";
|
|
62
66
|
else if (seq === "\x1b[5~") name = "pageup";
|
|
63
67
|
else if (seq === "\x1b[6~") name = "pagedown";
|
|
68
|
+
else if (seq === "\x1b[1;5C") { name = "right"; ctrl = true; } // Ctrl+Right
|
|
69
|
+
else if (seq === "\x1b[1;5D") { name = "left"; ctrl = true; } // Ctrl+Left
|
|
64
70
|
else name = lastChar;
|
|
65
71
|
|
|
66
72
|
stream.emit("keypress", seq, {
|
|
67
73
|
sequence: seq,
|
|
68
74
|
name,
|
|
69
|
-
ctrl
|
|
75
|
+
ctrl,
|
|
70
76
|
meta: false,
|
|
71
77
|
shift: false,
|
|
72
78
|
});
|
|
@@ -107,9 +113,15 @@ function parseAndEmitKeypress(
|
|
|
107
113
|
}
|
|
108
114
|
|
|
109
115
|
if (seq.length >= 2 && seq[1] !== "[" && seq[1] !== "O") {
|
|
116
|
+
// Alt+letter combo
|
|
117
|
+
const metaChar = seq[1];
|
|
118
|
+
let name = metaChar;
|
|
119
|
+
if (metaChar.charCodeAt(0) >= 32) {
|
|
120
|
+
name = metaChar.toLowerCase();
|
|
121
|
+
}
|
|
110
122
|
stream.emit("keypress", seq, {
|
|
111
123
|
sequence: seq,
|
|
112
|
-
name
|
|
124
|
+
name,
|
|
113
125
|
ctrl: false,
|
|
114
126
|
meta: true,
|
|
115
127
|
shift: false,
|
|
@@ -131,7 +143,6 @@ function parseAndEmitKeypress(
|
|
|
131
143
|
else if (char === "\t") name = "tab";
|
|
132
144
|
else if (char === " ") name = "space";
|
|
133
145
|
else if (char.charCodeAt(0) < 32) {
|
|
134
|
-
// Ctrl+letter
|
|
135
146
|
ctrl = true;
|
|
136
147
|
name = String.fromCharCode(char.charCodeAt(0) + 96);
|
|
137
148
|
}
|
|
@@ -166,7 +177,7 @@ export function emitKeypressEvents(stream: unknown, _iface?: Interface): void {
|
|
|
166
177
|
}
|
|
167
178
|
escapeBuf = parseAndEmitKeypress(stream as any, char, escapeBuf);
|
|
168
179
|
|
|
169
|
-
//
|
|
180
|
+
// if we're mid-escape, flush it after a short timeout
|
|
170
181
|
if (escapeBuf.length > 0) {
|
|
171
182
|
escapeTimeout = setTimeout(() => {
|
|
172
183
|
if (escapeBuf.length > 0) {
|
|
@@ -186,23 +197,48 @@ export function emitKeypressEvents(stream: unknown, _iface?: Interface): void {
|
|
|
186
197
|
});
|
|
187
198
|
}
|
|
188
199
|
|
|
200
|
+
// word boundary helpers for Ctrl+Left/Right, Ctrl+W, etc.
|
|
201
|
+
|
|
202
|
+
function wordLeft(line: string, cursor: number): number {
|
|
203
|
+
let i = cursor - 1;
|
|
204
|
+
while (i >= 0 && /\s/.test(line[i])) i--;
|
|
205
|
+
while (i >= 0 && !/\s/.test(line[i])) i--;
|
|
206
|
+
return i + 1;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function wordRight(line: string, cursor: number): number {
|
|
210
|
+
let i = cursor;
|
|
211
|
+
while (i < line.length && !/\s/.test(line[i])) i++;
|
|
212
|
+
while (i < line.length && /\s/.test(line[i])) i++;
|
|
213
|
+
return i;
|
|
214
|
+
}
|
|
215
|
+
|
|
189
216
|
|
|
190
217
|
export interface Interface extends EventEmitter {
|
|
191
218
|
_promptStr: string;
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
219
|
+
input: unknown;
|
|
220
|
+
output: unknown;
|
|
221
|
+
closed: boolean;
|
|
195
222
|
_lineBuffer: string;
|
|
196
223
|
_pendingQuestions: Array<{
|
|
197
224
|
query: string;
|
|
198
225
|
handler: (answer: string) => void;
|
|
226
|
+
signal?: AbortSignal;
|
|
227
|
+
abortListener?: () => void;
|
|
199
228
|
}>;
|
|
200
229
|
terminal: boolean;
|
|
201
230
|
line: string;
|
|
202
231
|
cursor: number;
|
|
232
|
+
history: string[];
|
|
233
|
+
_historyIndex: number;
|
|
234
|
+
_historySize: number;
|
|
235
|
+
_removeHistoryDuplicates: boolean;
|
|
236
|
+
_savedLine: string;
|
|
237
|
+
_killRing: string[];
|
|
203
238
|
_refreshLine(): void;
|
|
204
239
|
_onKeypress(char: string | undefined, key: any): void;
|
|
205
240
|
_onData(text: string): void;
|
|
241
|
+
_addToHistory(line: string): void;
|
|
206
242
|
prompt(preserveCursor?: boolean): void;
|
|
207
243
|
setPrompt(text: string): void;
|
|
208
244
|
getPrompt(): string;
|
|
@@ -211,6 +247,7 @@ export interface Interface extends EventEmitter {
|
|
|
211
247
|
resume(): this;
|
|
212
248
|
close(): void;
|
|
213
249
|
write(data: string | null, _key?: { ctrl?: boolean; name?: string; meta?: boolean; shift?: boolean; sequence?: string }): void;
|
|
250
|
+
clearLine(dir?: number): void;
|
|
214
251
|
getCursorPos(): { rows: number; cols: number };
|
|
215
252
|
[Symbol.asyncIterator](): AsyncGenerator<string, void, undefined>;
|
|
216
253
|
}
|
|
@@ -225,38 +262,60 @@ export const Interface = function Interface(this: any, cfg?: InterfaceConfig) {
|
|
|
225
262
|
if (!this) return;
|
|
226
263
|
EventEmitter.call(this);
|
|
227
264
|
this._promptStr = cfg?.prompt ?? "> ";
|
|
228
|
-
this.
|
|
229
|
-
this.
|
|
230
|
-
this.
|
|
265
|
+
this.input = cfg?.input;
|
|
266
|
+
this.output = cfg?.output;
|
|
267
|
+
this.closed = false;
|
|
231
268
|
this._lineBuffer = "";
|
|
232
269
|
this._pendingQuestions = [];
|
|
233
270
|
this.terminal = cfg?.terminal ?? false;
|
|
234
271
|
this.line = "";
|
|
235
272
|
this.cursor = 0;
|
|
236
273
|
|
|
237
|
-
|
|
274
|
+
this._historySize = cfg?.historySize ?? 30;
|
|
275
|
+
this._removeHistoryDuplicates = cfg?.removeHistoryDuplicates ?? false;
|
|
276
|
+
this.history = Array.isArray(cfg?.history) ? cfg!.history.slice(0, this._historySize) : [];
|
|
277
|
+
this._historyIndex = -1;
|
|
278
|
+
this._savedLine = "";
|
|
279
|
+
this._killRing = [];
|
|
280
|
+
|
|
281
|
+
if (cfg?.signal) {
|
|
282
|
+
const signal = cfg.signal;
|
|
283
|
+
if (signal.aborted) {
|
|
284
|
+
queueMicrotask(() => this.close());
|
|
285
|
+
} else {
|
|
286
|
+
const onAbort = () => this.close();
|
|
287
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (this.input && typeof (this.input as any).on === "function") {
|
|
238
292
|
_activeInterfaceCount++;
|
|
239
293
|
_elRef();
|
|
240
|
-
const inputStream = this.
|
|
294
|
+
const inputStream = this.input as EventEmitter;
|
|
241
295
|
const self = this;
|
|
242
296
|
|
|
243
297
|
if (this.terminal) {
|
|
244
|
-
|
|
298
|
+
// raw mode so we get individual keystrokes instead of line-buffered input
|
|
299
|
+
if (typeof (this.input as any).setRawMode === "function") {
|
|
300
|
+
(this.input as any).setRawMode(true);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
emitKeypressEvents(this.input, this);
|
|
245
304
|
|
|
246
305
|
inputStream.on("keypress", (char: string | undefined, key: any) => {
|
|
247
|
-
if (self.
|
|
306
|
+
if (self.closed) return;
|
|
248
307
|
self._onKeypress(char, key);
|
|
249
308
|
});
|
|
250
309
|
} else {
|
|
251
310
|
inputStream.on("data", (data: unknown) => {
|
|
252
|
-
if (self.
|
|
311
|
+
if (self.closed) return;
|
|
253
312
|
const text = typeof data === "string" ? data : String(data);
|
|
254
313
|
self._onData(text);
|
|
255
314
|
});
|
|
256
315
|
}
|
|
257
316
|
|
|
258
317
|
inputStream.on("end", () => {
|
|
259
|
-
if (!self.
|
|
318
|
+
if (!self.closed) self.close();
|
|
260
319
|
});
|
|
261
320
|
}
|
|
262
321
|
} as unknown as InterfaceConstructor;
|
|
@@ -264,26 +323,62 @@ export const Interface = function Interface(this: any, cfg?: InterfaceConfig) {
|
|
|
264
323
|
Object.setPrototypeOf(Interface.prototype, EventEmitter.prototype);
|
|
265
324
|
|
|
266
325
|
Interface.prototype._refreshLine = function _refreshLine(this: any): void {
|
|
267
|
-
if (this.
|
|
268
|
-
(this.
|
|
326
|
+
if (this.output && typeof (this.output as any).write === "function") {
|
|
327
|
+
(this.output as any).write(this.line);
|
|
269
328
|
}
|
|
270
329
|
};
|
|
271
330
|
|
|
331
|
+
Interface.prototype._addToHistory = function _addToHistory(this: any, line: string): void {
|
|
332
|
+
if (this._historySize === 0 || !line) return;
|
|
333
|
+
|
|
334
|
+
if (this._removeHistoryDuplicates) {
|
|
335
|
+
const idx = this.history.indexOf(line);
|
|
336
|
+
if (idx !== -1) this.history.splice(idx, 1);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
this.history.unshift(line);
|
|
340
|
+
if (this.history.length > this._historySize) {
|
|
341
|
+
this.history.length = this._historySize;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
this._historyIndex = -1;
|
|
345
|
+
this.emit("history", this.history);
|
|
346
|
+
};
|
|
347
|
+
|
|
272
348
|
Interface.prototype._onKeypress = function _onKeypress(this: any, char: string | undefined, key: any): void {
|
|
273
349
|
if (!key) return;
|
|
274
350
|
|
|
351
|
+
// Ctrl+C
|
|
275
352
|
if (key.ctrl && key.name === "c") {
|
|
276
|
-
this.
|
|
353
|
+
if (this.listenerCount("SIGINT") > 0) {
|
|
354
|
+
this.emit("SIGINT");
|
|
355
|
+
} else {
|
|
356
|
+
this.close();
|
|
357
|
+
}
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Ctrl+Z
|
|
362
|
+
if (key.ctrl && key.name === "z") {
|
|
363
|
+
if (this.listenerCount("SIGTSTP") > 0) {
|
|
364
|
+
this.emit("SIGTSTP");
|
|
365
|
+
}
|
|
277
366
|
return;
|
|
278
367
|
}
|
|
279
368
|
|
|
369
|
+
// Enter — submit the line
|
|
280
370
|
if (key.name === "return") {
|
|
281
371
|
const line = this._lineBuffer;
|
|
282
372
|
this._lineBuffer = "";
|
|
283
373
|
this.line = line;
|
|
284
374
|
|
|
375
|
+
this._addToHistory(line);
|
|
376
|
+
|
|
285
377
|
if (this._pendingQuestions.length > 0) {
|
|
286
378
|
const q = this._pendingQuestions.shift()!;
|
|
379
|
+
if (q.signal && q.abortListener) {
|
|
380
|
+
q.signal.removeEventListener("abort", q.abortListener);
|
|
381
|
+
}
|
|
287
382
|
q.handler(line);
|
|
288
383
|
}
|
|
289
384
|
|
|
@@ -293,8 +388,10 @@ Interface.prototype._onKeypress = function _onKeypress(this: any, char: string |
|
|
|
293
388
|
return;
|
|
294
389
|
}
|
|
295
390
|
|
|
391
|
+
// Backspace
|
|
296
392
|
if (key.name === "backspace") {
|
|
297
393
|
if (this.cursor > 0) {
|
|
394
|
+
const deleted = this._lineBuffer[this.cursor - 1];
|
|
298
395
|
this._lineBuffer =
|
|
299
396
|
this._lineBuffer.slice(0, this.cursor - 1) +
|
|
300
397
|
this._lineBuffer.slice(this.cursor);
|
|
@@ -305,6 +402,7 @@ Interface.prototype._onKeypress = function _onKeypress(this: any, char: string |
|
|
|
305
402
|
return;
|
|
306
403
|
}
|
|
307
404
|
|
|
405
|
+
// Delete
|
|
308
406
|
if (key.name === "delete") {
|
|
309
407
|
if (this.cursor < this._lineBuffer.length) {
|
|
310
408
|
this._lineBuffer =
|
|
@@ -316,28 +414,111 @@ Interface.prototype._onKeypress = function _onKeypress(this: any, char: string |
|
|
|
316
414
|
return;
|
|
317
415
|
}
|
|
318
416
|
|
|
319
|
-
|
|
417
|
+
// Ctrl+D — delete char or close if empty
|
|
418
|
+
if (key.ctrl && key.name === "d") {
|
|
419
|
+
if (this._lineBuffer.length === 0) {
|
|
420
|
+
this.close();
|
|
421
|
+
} else if (this.cursor < this._lineBuffer.length) {
|
|
422
|
+
this._lineBuffer =
|
|
423
|
+
this._lineBuffer.slice(0, this.cursor) +
|
|
424
|
+
this._lineBuffer.slice(this.cursor + 1);
|
|
425
|
+
this.line = this._lineBuffer;
|
|
426
|
+
this._refreshLine();
|
|
427
|
+
}
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// arrow keys
|
|
432
|
+
if (key.name === "left" && !key.ctrl && !key.meta) {
|
|
320
433
|
this.cursor = Math.max(0, this.cursor - 1);
|
|
321
434
|
this._refreshLine();
|
|
322
435
|
return;
|
|
323
436
|
}
|
|
324
|
-
if (key.name === "right") {
|
|
437
|
+
if (key.name === "right" && !key.ctrl && !key.meta) {
|
|
325
438
|
this.cursor = Math.min(this._lineBuffer.length, this.cursor + 1);
|
|
326
439
|
this._refreshLine();
|
|
327
440
|
return;
|
|
328
441
|
}
|
|
329
|
-
|
|
442
|
+
|
|
443
|
+
// Ctrl+Left / Alt+B — jump word left
|
|
444
|
+
if ((key.ctrl && key.name === "left") || (key.meta && key.name === "b")) {
|
|
445
|
+
this.cursor = wordLeft(this._lineBuffer, this.cursor);
|
|
446
|
+
this._refreshLine();
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Ctrl+Right / Alt+F — jump word right
|
|
451
|
+
if ((key.ctrl && key.name === "right") || (key.meta && key.name === "f")) {
|
|
452
|
+
this.cursor = wordRight(this._lineBuffer, this.cursor);
|
|
453
|
+
this._refreshLine();
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Home / Ctrl+A
|
|
458
|
+
if (key.name === "home" || (key.ctrl && key.name === "a")) {
|
|
330
459
|
this.cursor = 0;
|
|
331
460
|
this._refreshLine();
|
|
332
461
|
return;
|
|
333
462
|
}
|
|
334
|
-
|
|
463
|
+
|
|
464
|
+
// End / Ctrl+E
|
|
465
|
+
if (key.name === "end" || (key.ctrl && key.name === "e")) {
|
|
335
466
|
this.cursor = this._lineBuffer.length;
|
|
336
467
|
this._refreshLine();
|
|
337
468
|
return;
|
|
338
469
|
}
|
|
339
470
|
|
|
471
|
+
// Ctrl+B — back one char
|
|
472
|
+
if (key.ctrl && key.name === "b") {
|
|
473
|
+
this.cursor = Math.max(0, this.cursor - 1);
|
|
474
|
+
this._refreshLine();
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Ctrl+F — forward one char
|
|
479
|
+
if (key.ctrl && key.name === "f") {
|
|
480
|
+
this.cursor = Math.min(this._lineBuffer.length, this.cursor + 1);
|
|
481
|
+
this._refreshLine();
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// Up / Ctrl+P — previous history entry
|
|
486
|
+
if (key.name === "up" || (key.ctrl && key.name === "p")) {
|
|
487
|
+
if (this.history.length > 0 && this._historyIndex < this.history.length - 1) {
|
|
488
|
+
if (this._historyIndex === -1) {
|
|
489
|
+
this._savedLine = this._lineBuffer;
|
|
490
|
+
}
|
|
491
|
+
this._historyIndex++;
|
|
492
|
+
this._lineBuffer = this.history[this._historyIndex];
|
|
493
|
+
this.cursor = this._lineBuffer.length;
|
|
494
|
+
this.line = this._lineBuffer;
|
|
495
|
+
this._refreshLine();
|
|
496
|
+
}
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// Down / Ctrl+N — next history entry
|
|
501
|
+
if (key.name === "down" || (key.ctrl && key.name === "n")) {
|
|
502
|
+
if (this._historyIndex > 0) {
|
|
503
|
+
this._historyIndex--;
|
|
504
|
+
this._lineBuffer = this.history[this._historyIndex];
|
|
505
|
+
this.cursor = this._lineBuffer.length;
|
|
506
|
+
this.line = this._lineBuffer;
|
|
507
|
+
this._refreshLine();
|
|
508
|
+
} else if (this._historyIndex === 0) {
|
|
509
|
+
this._historyIndex = -1;
|
|
510
|
+
this._lineBuffer = this._savedLine;
|
|
511
|
+
this.cursor = this._lineBuffer.length;
|
|
512
|
+
this.line = this._lineBuffer;
|
|
513
|
+
this._refreshLine();
|
|
514
|
+
}
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Ctrl+U — kill everything before cursor
|
|
340
519
|
if (key.ctrl && key.name === "u") {
|
|
520
|
+
const killed = this._lineBuffer.slice(0, this.cursor);
|
|
521
|
+
if (killed) this._killRing.push(killed);
|
|
341
522
|
this._lineBuffer = this._lineBuffer.slice(this.cursor);
|
|
342
523
|
this.cursor = 0;
|
|
343
524
|
this.line = this._lineBuffer;
|
|
@@ -345,13 +526,17 @@ Interface.prototype._onKeypress = function _onKeypress(this: any, char: string |
|
|
|
345
526
|
return;
|
|
346
527
|
}
|
|
347
528
|
|
|
529
|
+
// Ctrl+K — kill everything after cursor
|
|
348
530
|
if (key.ctrl && key.name === "k") {
|
|
531
|
+
const killed = this._lineBuffer.slice(this.cursor);
|
|
532
|
+
if (killed) this._killRing.push(killed);
|
|
349
533
|
this._lineBuffer = this._lineBuffer.slice(0, this.cursor);
|
|
350
534
|
this.line = this._lineBuffer;
|
|
351
535
|
this._refreshLine();
|
|
352
536
|
return;
|
|
353
537
|
}
|
|
354
538
|
|
|
539
|
+
// Ctrl+H — same as backspace
|
|
355
540
|
if (key.ctrl && key.name === "h") {
|
|
356
541
|
if (this.cursor > 0) {
|
|
357
542
|
this._lineBuffer =
|
|
@@ -364,6 +549,58 @@ Interface.prototype._onKeypress = function _onKeypress(this: any, char: string |
|
|
|
364
549
|
return;
|
|
365
550
|
}
|
|
366
551
|
|
|
552
|
+
// Ctrl+W — delete word backward
|
|
553
|
+
if (key.ctrl && key.name === "w") {
|
|
554
|
+
const newPos = wordLeft(this._lineBuffer, this.cursor);
|
|
555
|
+
const killed = this._lineBuffer.slice(newPos, this.cursor);
|
|
556
|
+
if (killed) this._killRing.push(killed);
|
|
557
|
+
this._lineBuffer =
|
|
558
|
+
this._lineBuffer.slice(0, newPos) +
|
|
559
|
+
this._lineBuffer.slice(this.cursor);
|
|
560
|
+
this.cursor = newPos;
|
|
561
|
+
this.line = this._lineBuffer;
|
|
562
|
+
this._refreshLine();
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// Alt+D — delete word forward
|
|
567
|
+
if (key.meta && key.name === "d") {
|
|
568
|
+
const newPos = wordRight(this._lineBuffer, this.cursor);
|
|
569
|
+
const killed = this._lineBuffer.slice(this.cursor, newPos);
|
|
570
|
+
if (killed) this._killRing.push(killed);
|
|
571
|
+
this._lineBuffer =
|
|
572
|
+
this._lineBuffer.slice(0, this.cursor) +
|
|
573
|
+
this._lineBuffer.slice(newPos);
|
|
574
|
+
this.line = this._lineBuffer;
|
|
575
|
+
this._refreshLine();
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// Ctrl+Y — paste last killed text
|
|
580
|
+
if (key.ctrl && key.name === "y") {
|
|
581
|
+
if (this._killRing.length > 0) {
|
|
582
|
+
const text = this._killRing[this._killRing.length - 1];
|
|
583
|
+
this._lineBuffer =
|
|
584
|
+
this._lineBuffer.slice(0, this.cursor) +
|
|
585
|
+
text +
|
|
586
|
+
this._lineBuffer.slice(this.cursor);
|
|
587
|
+
this.cursor += text.length;
|
|
588
|
+
this.line = this._lineBuffer;
|
|
589
|
+
this._refreshLine();
|
|
590
|
+
}
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// Ctrl+L — clear screen
|
|
595
|
+
if (key.ctrl && key.name === "l") {
|
|
596
|
+
if (this.output && typeof (this.output as any).write === "function") {
|
|
597
|
+
(this.output as any).write("\x1b[2J\x1b[H");
|
|
598
|
+
}
|
|
599
|
+
this._refreshLine();
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// regular printable character
|
|
367
604
|
if (
|
|
368
605
|
char &&
|
|
369
606
|
!key.ctrl &&
|
|
@@ -390,8 +627,13 @@ Interface.prototype._onData = function _onData(this: any, text: string): void {
|
|
|
390
627
|
this._lineBuffer = "";
|
|
391
628
|
this.line = line;
|
|
392
629
|
|
|
630
|
+
this._addToHistory(line);
|
|
631
|
+
|
|
393
632
|
if (this._pendingQuestions.length > 0) {
|
|
394
633
|
const q = this._pendingQuestions.shift()!;
|
|
634
|
+
if (q.signal && q.abortListener) {
|
|
635
|
+
q.signal.removeEventListener("abort", q.abortListener);
|
|
636
|
+
}
|
|
395
637
|
q.handler(line);
|
|
396
638
|
}
|
|
397
639
|
|
|
@@ -420,8 +662,8 @@ Interface.prototype._onData = function _onData(this: any, text: string): void {
|
|
|
420
662
|
};
|
|
421
663
|
|
|
422
664
|
Interface.prototype.prompt = function prompt(this: any, preserveCursor?: boolean): void {
|
|
423
|
-
if (this.
|
|
424
|
-
(this.
|
|
665
|
+
if (this.output && typeof (this.output as any).write === "function") {
|
|
666
|
+
(this.output as any).write(this._promptStr);
|
|
425
667
|
}
|
|
426
668
|
if (!preserveCursor) {
|
|
427
669
|
this.cursor = 0;
|
|
@@ -444,53 +686,93 @@ Interface.prototype.question = function question(
|
|
|
444
686
|
optsOrHandler?: unknown,
|
|
445
687
|
handler?: (answer: string) => void,
|
|
446
688
|
): void {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
689
|
+
let actualHandler: ((answer: string) => void) | undefined;
|
|
690
|
+
let signal: AbortSignal | undefined;
|
|
691
|
+
|
|
692
|
+
if (typeof optsOrHandler === "function") {
|
|
693
|
+
actualHandler = optsOrHandler as (answer: string) => void;
|
|
694
|
+
} else if (optsOrHandler && typeof optsOrHandler === "object") {
|
|
695
|
+
signal = (optsOrHandler as any).signal;
|
|
696
|
+
actualHandler = handler;
|
|
697
|
+
} else {
|
|
698
|
+
actualHandler = handler;
|
|
699
|
+
}
|
|
700
|
+
|
|
451
701
|
if (!actualHandler) return;
|
|
452
702
|
|
|
453
|
-
if (
|
|
454
|
-
(
|
|
703
|
+
if (signal?.aborted) {
|
|
704
|
+
const err = new DOMException("The operation was aborted", "AbortError");
|
|
705
|
+
throw err;
|
|
455
706
|
}
|
|
456
707
|
|
|
457
|
-
if (this.
|
|
458
|
-
this.
|
|
708
|
+
if (this.output && typeof (this.output as any).write === "function") {
|
|
709
|
+
(this.output as any).write(query);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
if (this.input && typeof (this.input as any).on === "function") {
|
|
713
|
+
const entry: any = { query, handler: actualHandler, signal };
|
|
714
|
+
|
|
715
|
+
if (signal) {
|
|
716
|
+
const onAbort = () => {
|
|
717
|
+
const idx = this._pendingQuestions.indexOf(entry);
|
|
718
|
+
if (idx !== -1) this._pendingQuestions.splice(idx, 1);
|
|
719
|
+
actualHandler!("");
|
|
720
|
+
};
|
|
721
|
+
entry.abortListener = onAbort;
|
|
722
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
this._pendingQuestions.push(entry);
|
|
459
726
|
} else {
|
|
460
|
-
setTimeout(() => actualHandler(""), 0);
|
|
727
|
+
setTimeout(() => actualHandler!(""), 0);
|
|
461
728
|
}
|
|
462
729
|
};
|
|
463
730
|
|
|
464
731
|
Interface.prototype.pause = function pause(this: any): any {
|
|
465
|
-
if (this.
|
|
466
|
-
(this.
|
|
732
|
+
if (this.input && typeof (this.input as any).pause === "function") {
|
|
733
|
+
(this.input as any).pause();
|
|
467
734
|
}
|
|
468
735
|
this.emit("pause");
|
|
469
736
|
return this;
|
|
470
737
|
};
|
|
471
738
|
|
|
472
739
|
Interface.prototype.resume = function resume(this: any): any {
|
|
473
|
-
if (this.
|
|
474
|
-
(this.
|
|
740
|
+
if (this.input && typeof (this.input as any).resume === "function") {
|
|
741
|
+
(this.input as any).resume();
|
|
475
742
|
}
|
|
476
743
|
this.emit("resume");
|
|
477
744
|
return this;
|
|
478
745
|
};
|
|
479
746
|
|
|
480
747
|
Interface.prototype.close = function close(this: any): void {
|
|
481
|
-
if (this.
|
|
482
|
-
this.
|
|
483
|
-
|
|
748
|
+
if (this.closed) return;
|
|
749
|
+
this.closed = true;
|
|
750
|
+
// put raw mode back how it was
|
|
751
|
+
if (this.terminal && this.input && typeof (this.input as any).setRawMode === "function") {
|
|
752
|
+
(this.input as any).setRawMode(false);
|
|
753
|
+
}
|
|
754
|
+
if (this.input && typeof (this.input as any).on === "function") {
|
|
484
755
|
_activeInterfaceCount = Math.max(0, _activeInterfaceCount - 1);
|
|
485
756
|
_elUnref();
|
|
486
757
|
}
|
|
758
|
+
// answer any pending questions with empty string
|
|
487
759
|
for (const q of this._pendingQuestions) {
|
|
760
|
+
if (q.signal && q.abortListener) {
|
|
761
|
+
q.signal.removeEventListener("abort", q.abortListener);
|
|
762
|
+
}
|
|
488
763
|
q.handler("");
|
|
489
764
|
}
|
|
490
765
|
this._pendingQuestions.length = 0;
|
|
491
766
|
this.emit("close");
|
|
492
767
|
};
|
|
493
768
|
|
|
769
|
+
// `using rl = ...` support
|
|
770
|
+
if (typeof Symbol.dispose !== "undefined") {
|
|
771
|
+
(Interface.prototype as any)[Symbol.dispose] = function (this: any): void {
|
|
772
|
+
this.close();
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
|
|
494
776
|
Interface.prototype.write = function write(
|
|
495
777
|
this: any,
|
|
496
778
|
data: string | null,
|
|
@@ -502,20 +784,23 @@ Interface.prototype.write = function write(
|
|
|
502
784
|
sequence?: string;
|
|
503
785
|
},
|
|
504
786
|
): void {
|
|
505
|
-
if (this.
|
|
787
|
+
if (this.closed) return;
|
|
506
788
|
|
|
507
789
|
if (data === null || data === undefined) {
|
|
508
790
|
if (_key) {
|
|
509
|
-
//
|
|
791
|
+
// fire a keypress on input so things like @clack pick it up
|
|
510
792
|
const emitOnInput =
|
|
511
|
-
this.
|
|
793
|
+
this.input && typeof (this.input as any).emit === "function";
|
|
512
794
|
|
|
513
795
|
if (_key.ctrl && _key.name === "c") {
|
|
514
|
-
this.
|
|
796
|
+
if (this.listenerCount("SIGINT") > 0) {
|
|
797
|
+
this.emit("SIGINT");
|
|
798
|
+
} else {
|
|
799
|
+
this.close();
|
|
800
|
+
}
|
|
515
801
|
return;
|
|
516
802
|
}
|
|
517
803
|
if (_key.ctrl && _key.name === "h") {
|
|
518
|
-
// Backspace
|
|
519
804
|
if (this.cursor > 0) {
|
|
520
805
|
this._lineBuffer =
|
|
521
806
|
this._lineBuffer.slice(0, this.cursor - 1) +
|
|
@@ -524,7 +809,7 @@ Interface.prototype.write = function write(
|
|
|
524
809
|
this.line = this._lineBuffer;
|
|
525
810
|
}
|
|
526
811
|
if (emitOnInput) {
|
|
527
|
-
(this.
|
|
812
|
+
(this.input as any).emit("keypress", "\x7f", {
|
|
528
813
|
sequence: "\x7f",
|
|
529
814
|
name: "backspace",
|
|
530
815
|
ctrl: false,
|
|
@@ -535,24 +820,92 @@ Interface.prototype.write = function write(
|
|
|
535
820
|
return;
|
|
536
821
|
}
|
|
537
822
|
if (_key.ctrl && _key.name === "u") {
|
|
823
|
+
const killed = this._lineBuffer.slice(0, this.cursor);
|
|
824
|
+
if (killed) this._killRing.push(killed);
|
|
538
825
|
this._lineBuffer = this._lineBuffer.slice(this.cursor);
|
|
539
826
|
this.cursor = 0;
|
|
540
827
|
this.line = this._lineBuffer;
|
|
541
828
|
return;
|
|
542
829
|
}
|
|
543
830
|
if (_key.ctrl && _key.name === "k") {
|
|
831
|
+
const killed = this._lineBuffer.slice(this.cursor);
|
|
832
|
+
if (killed) this._killRing.push(killed);
|
|
544
833
|
this._lineBuffer = this._lineBuffer.slice(0, this.cursor);
|
|
545
834
|
this.line = this._lineBuffer;
|
|
546
835
|
return;
|
|
547
836
|
}
|
|
548
|
-
if (_key.name === "
|
|
837
|
+
if (_key.ctrl && _key.name === "w") {
|
|
838
|
+
const newPos = wordLeft(this._lineBuffer, this.cursor);
|
|
839
|
+
const killed = this._lineBuffer.slice(newPos, this.cursor);
|
|
840
|
+
if (killed) this._killRing.push(killed);
|
|
841
|
+
this._lineBuffer =
|
|
842
|
+
this._lineBuffer.slice(0, newPos) +
|
|
843
|
+
this._lineBuffer.slice(this.cursor);
|
|
844
|
+
this.cursor = newPos;
|
|
845
|
+
this.line = this._lineBuffer;
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
if (_key.ctrl && _key.name === "y") {
|
|
849
|
+
if (this._killRing.length > 0) {
|
|
850
|
+
const text = this._killRing[this._killRing.length - 1];
|
|
851
|
+
this._lineBuffer =
|
|
852
|
+
this._lineBuffer.slice(0, this.cursor) +
|
|
853
|
+
text +
|
|
854
|
+
this._lineBuffer.slice(this.cursor);
|
|
855
|
+
this.cursor += text.length;
|
|
856
|
+
this.line = this._lineBuffer;
|
|
857
|
+
}
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
if (_key.ctrl && _key.name === "a") {
|
|
861
|
+
this.cursor = 0;
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
if (_key.ctrl && _key.name === "e") {
|
|
865
|
+
this.cursor = this._lineBuffer.length;
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
if (_key.ctrl && _key.name === "b") {
|
|
549
869
|
this.cursor = Math.max(0, this.cursor - 1);
|
|
550
870
|
return;
|
|
551
871
|
}
|
|
552
|
-
if (_key.name === "
|
|
872
|
+
if (_key.ctrl && _key.name === "f") {
|
|
553
873
|
this.cursor = Math.min(this._lineBuffer.length, this.cursor + 1);
|
|
554
874
|
return;
|
|
555
875
|
}
|
|
876
|
+
if (_key.ctrl && _key.name === "d") {
|
|
877
|
+
if (this._lineBuffer.length === 0) {
|
|
878
|
+
this.close();
|
|
879
|
+
} else if (this.cursor < this._lineBuffer.length) {
|
|
880
|
+
this._lineBuffer =
|
|
881
|
+
this._lineBuffer.slice(0, this.cursor) +
|
|
882
|
+
this._lineBuffer.slice(this.cursor + 1);
|
|
883
|
+
this.line = this._lineBuffer;
|
|
884
|
+
}
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
if (_key.ctrl && _key.name === "l") {
|
|
888
|
+
if (this.output && typeof (this.output as any).write === "function") {
|
|
889
|
+
(this.output as any).write("\x1b[2J\x1b[H");
|
|
890
|
+
}
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
if (_key.name === "left") {
|
|
894
|
+
if (_key.ctrl || _key.meta) {
|
|
895
|
+
this.cursor = wordLeft(this._lineBuffer, this.cursor);
|
|
896
|
+
} else {
|
|
897
|
+
this.cursor = Math.max(0, this.cursor - 1);
|
|
898
|
+
}
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
if (_key.name === "right") {
|
|
902
|
+
if (_key.ctrl || _key.meta) {
|
|
903
|
+
this.cursor = wordRight(this._lineBuffer, this.cursor);
|
|
904
|
+
} else {
|
|
905
|
+
this.cursor = Math.min(this._lineBuffer.length, this.cursor + 1);
|
|
906
|
+
}
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
556
909
|
if (_key.name === "home") {
|
|
557
910
|
this.cursor = 0;
|
|
558
911
|
return;
|
|
@@ -561,27 +914,90 @@ Interface.prototype.write = function write(
|
|
|
561
914
|
this.cursor = this._lineBuffer.length;
|
|
562
915
|
return;
|
|
563
916
|
}
|
|
917
|
+
if (_key.name === "up") {
|
|
918
|
+
if (this.history.length > 0 && this._historyIndex < this.history.length - 1) {
|
|
919
|
+
if (this._historyIndex === -1) this._savedLine = this._lineBuffer;
|
|
920
|
+
this._historyIndex++;
|
|
921
|
+
this._lineBuffer = this.history[this._historyIndex];
|
|
922
|
+
this.cursor = this._lineBuffer.length;
|
|
923
|
+
this.line = this._lineBuffer;
|
|
924
|
+
}
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
if (_key.name === "down") {
|
|
928
|
+
if (this._historyIndex > 0) {
|
|
929
|
+
this._historyIndex--;
|
|
930
|
+
this._lineBuffer = this.history[this._historyIndex];
|
|
931
|
+
this.cursor = this._lineBuffer.length;
|
|
932
|
+
this.line = this._lineBuffer;
|
|
933
|
+
} else if (this._historyIndex === 0) {
|
|
934
|
+
this._historyIndex = -1;
|
|
935
|
+
this._lineBuffer = this._savedLine;
|
|
936
|
+
this.cursor = this._lineBuffer.length;
|
|
937
|
+
this.line = this._lineBuffer;
|
|
938
|
+
}
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
if (_key.meta && _key.name === "b") {
|
|
942
|
+
this.cursor = wordLeft(this._lineBuffer, this.cursor);
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
if (_key.meta && _key.name === "f") {
|
|
946
|
+
this.cursor = wordRight(this._lineBuffer, this.cursor);
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
if (_key.meta && _key.name === "d") {
|
|
950
|
+
const newPos = wordRight(this._lineBuffer, this.cursor);
|
|
951
|
+
const killed = this._lineBuffer.slice(this.cursor, newPos);
|
|
952
|
+
if (killed) this._killRing.push(killed);
|
|
953
|
+
this._lineBuffer =
|
|
954
|
+
this._lineBuffer.slice(0, this.cursor) +
|
|
955
|
+
this._lineBuffer.slice(newPos);
|
|
956
|
+
this.line = this._lineBuffer;
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
564
959
|
}
|
|
565
960
|
return;
|
|
566
961
|
}
|
|
567
962
|
|
|
568
963
|
if (_key?.ctrl && _key?.name === "c") {
|
|
569
|
-
this.
|
|
964
|
+
if (this.listenerCount("SIGINT") > 0) {
|
|
965
|
+
this.emit("SIGINT");
|
|
966
|
+
} else {
|
|
967
|
+
this.close();
|
|
968
|
+
}
|
|
570
969
|
return;
|
|
571
970
|
}
|
|
572
971
|
|
|
573
972
|
this._onData(data);
|
|
574
973
|
};
|
|
575
974
|
|
|
975
|
+
// @inquirer calls rl.clearLine(0) directly so we need this on the interface
|
|
976
|
+
Interface.prototype.clearLine = function clearLine(this: any, dir?: number): void {
|
|
977
|
+
this._lineBuffer = "";
|
|
978
|
+
this.line = "";
|
|
979
|
+
this.cursor = 0;
|
|
980
|
+
if (this.output && typeof (this.output as any).clearLine === "function") {
|
|
981
|
+
(this.output as any).clearLine(dir ?? 0);
|
|
982
|
+
}
|
|
983
|
+
};
|
|
984
|
+
|
|
576
985
|
Interface.prototype.getCursorPos = function getCursorPos(this: any): { rows: number; cols: number } {
|
|
577
|
-
|
|
986
|
+
// cursor position relative to prompt, wrapping at terminal width
|
|
987
|
+
const promptLen = typeof this._promptStr === "string" ? this._promptStr.length : 0;
|
|
988
|
+
const columns = (this.output && (this.output as any).columns) || 80;
|
|
989
|
+
const offset = promptLen + this.cursor;
|
|
990
|
+
return {
|
|
991
|
+
rows: Math.floor(offset / columns),
|
|
992
|
+
cols: offset % columns,
|
|
993
|
+
};
|
|
578
994
|
};
|
|
579
995
|
|
|
580
996
|
Interface.prototype[Symbol.asyncIterator] = async function*(this: any): AsyncGenerator<string, void, undefined> {
|
|
581
997
|
const self = this;
|
|
582
|
-
while (!self.
|
|
998
|
+
while (!self.closed) {
|
|
583
999
|
const line = await new Promise<string | null>((resolve) => {
|
|
584
|
-
if (self.
|
|
1000
|
+
if (self.closed) {
|
|
585
1001
|
resolve(null);
|
|
586
1002
|
return;
|
|
587
1003
|
}
|
|
@@ -662,21 +1078,127 @@ export function moveCursor(
|
|
|
662
1078
|
}
|
|
663
1079
|
|
|
664
1080
|
|
|
1081
|
+
// promises API
|
|
1082
|
+
|
|
1083
|
+
class ReadlineWriter {
|
|
1084
|
+
private _stream: any;
|
|
1085
|
+
private _buffer: string[];
|
|
1086
|
+
private _autoCommit: boolean;
|
|
1087
|
+
|
|
1088
|
+
constructor(stream: any, opts?: { autoCommit?: boolean }) {
|
|
1089
|
+
this._stream = stream;
|
|
1090
|
+
this._buffer = [];
|
|
1091
|
+
this._autoCommit = opts?.autoCommit ?? false;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
clearLine(dir: -1 | 0 | 1): this {
|
|
1095
|
+
let seq: string;
|
|
1096
|
+
if (dir === -1) seq = "\x1b[1K";
|
|
1097
|
+
else if (dir === 1) seq = "\x1b[0K";
|
|
1098
|
+
else seq = "\x1b[2K";
|
|
1099
|
+
if (this._autoCommit) {
|
|
1100
|
+
this._stream.write(seq);
|
|
1101
|
+
} else {
|
|
1102
|
+
this._buffer.push(seq);
|
|
1103
|
+
}
|
|
1104
|
+
return this;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
clearScreenDown(): this {
|
|
1108
|
+
const seq = "\x1b[J";
|
|
1109
|
+
if (this._autoCommit) {
|
|
1110
|
+
this._stream.write(seq);
|
|
1111
|
+
} else {
|
|
1112
|
+
this._buffer.push(seq);
|
|
1113
|
+
}
|
|
1114
|
+
return this;
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
cursorTo(x: number, y?: number): this {
|
|
1118
|
+
let seq: string;
|
|
1119
|
+
if (y !== undefined) {
|
|
1120
|
+
seq = `\x1b[${y + 1};${x + 1}H`;
|
|
1121
|
+
} else {
|
|
1122
|
+
seq = `\x1b[${x + 1}G`;
|
|
1123
|
+
}
|
|
1124
|
+
if (this._autoCommit) {
|
|
1125
|
+
this._stream.write(seq);
|
|
1126
|
+
} else {
|
|
1127
|
+
this._buffer.push(seq);
|
|
1128
|
+
}
|
|
1129
|
+
return this;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
moveCursor(dx: number, dy: number): this {
|
|
1133
|
+
const parts: string[] = [];
|
|
1134
|
+
if (dx > 0) parts.push(`\x1b[${dx}C`);
|
|
1135
|
+
else if (dx < 0) parts.push(`\x1b[${-dx}D`);
|
|
1136
|
+
if (dy > 0) parts.push(`\x1b[${dy}B`);
|
|
1137
|
+
else if (dy < 0) parts.push(`\x1b[${-dy}A`);
|
|
1138
|
+
const seq = parts.join("");
|
|
1139
|
+
if (seq) {
|
|
1140
|
+
if (this._autoCommit) {
|
|
1141
|
+
this._stream.write(seq);
|
|
1142
|
+
} else {
|
|
1143
|
+
this._buffer.push(seq);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
return this;
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
commit(): Promise<void> {
|
|
1150
|
+
if (this._buffer.length > 0) {
|
|
1151
|
+
this._stream.write(this._buffer.join(""));
|
|
1152
|
+
this._buffer.length = 0;
|
|
1153
|
+
}
|
|
1154
|
+
return Promise.resolve();
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
rollback(): this {
|
|
1158
|
+
this._buffer.length = 0;
|
|
1159
|
+
return this;
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
|
|
665
1163
|
export const promises = {
|
|
666
|
-
createInterface(cfg?: InterfaceConfig) {
|
|
1164
|
+
createInterface(cfg?: InterfaceConfig): any {
|
|
667
1165
|
const rl = createInterface(cfg);
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
1166
|
+
const wrapper: any = Object.create(rl);
|
|
1167
|
+
|
|
1168
|
+
wrapper.question = function (
|
|
1169
|
+
query: string,
|
|
1170
|
+
opts?: { signal?: AbortSignal },
|
|
1171
|
+
): Promise<string> {
|
|
1172
|
+
return new Promise((resolve, reject) => {
|
|
1173
|
+
if (opts?.signal?.aborted) {
|
|
1174
|
+
reject(new DOMException("The operation was aborted", "AbortError"));
|
|
1175
|
+
return;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
let onAbort: (() => void) | undefined;
|
|
1179
|
+
|
|
1180
|
+
const handler = (answer: string) => {
|
|
1181
|
+
if (opts?.signal && onAbort) {
|
|
1182
|
+
opts.signal.removeEventListener("abort", onAbort);
|
|
1183
|
+
}
|
|
1184
|
+
resolve(answer);
|
|
1185
|
+
};
|
|
1186
|
+
|
|
1187
|
+
if (opts?.signal) {
|
|
1188
|
+
onAbort = () => {
|
|
1189
|
+
reject(new DOMException("The operation was aborted", "AbortError"));
|
|
1190
|
+
};
|
|
1191
|
+
opts.signal.addEventListener("abort", onAbort, { once: true });
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
rl.question(query, handler);
|
|
1195
|
+
});
|
|
678
1196
|
};
|
|
1197
|
+
|
|
1198
|
+
return wrapper;
|
|
679
1199
|
},
|
|
1200
|
+
|
|
1201
|
+
Readline: ReadlineWriter,
|
|
680
1202
|
};
|
|
681
1203
|
|
|
682
1204
|
|