UNPKG

23.2 kBTypeScriptView Raw
1/**
2 * The `readline` module provides an interface for reading data from a `Readable` stream (such as `process.stdin`) one line at a time. It can be accessed
3 * using:
4 *
5 * ```js
6 * const readline = require('readline');
7 * ```
8 *
9 * The following simple example illustrates the basic use of the `readline` module.
10 *
11 * ```js
12 * const readline = require('readline');
13 *
14 * const rl = readline.createInterface({
15 * input: process.stdin,
16 * output: process.stdout
17 * });
18 *
19 * rl.question('What do you think of Node.js? ', (answer) => {
20 * // TODO: Log the answer in a database
21 * console.log(`Thank you for your valuable feedback: ${answer}`);
22 *
23 * rl.close();
24 * });
25 * ```
26 *
27 * Once this code is invoked, the Node.js application will not terminate until the`readline.Interface` is closed because the interface waits for data to be
28 * received on the `input` stream.
29 * @see [source](https://github.com/nodejs/node/blob/v16.4.2/lib/readline.js)
30 */
31declare module 'readline' {
32 import { Abortable, EventEmitter } from 'node:events';
33 interface Key {
34 sequence?: string | undefined;
35 name?: string | undefined;
36 ctrl?: boolean | undefined;
37 meta?: boolean | undefined;
38 shift?: boolean | undefined;
39 }
40 /**
41 * Instances of the `readline.Interface` class are constructed using the`readline.createInterface()` method. Every instance is associated with a
42 * single `input` `Readable` stream and a single `output` `Writable` stream.
43 * The `output` stream is used to print prompts for user input that arrives on,
44 * and is read from, the `input` stream.
45 * @since v0.1.104
46 */
47 class Interface extends EventEmitter {
48 readonly terminal: boolean;
49 /**
50 * The current input data being processed by node.
51 *
52 * This can be used when collecting input from a TTY stream to retrieve the
53 * current value that has been processed thus far, prior to the `line` event
54 * being emitted. Once the `line` event has been emitted, this property will
55 * be an empty string.
56 *
57 * Be aware that modifying the value during the instance runtime may have
58 * unintended consequences if `rl.cursor` is not also controlled.
59 *
60 * **If not using a TTY stream for input, use the `'line'` event.**
61 *
62 * One possible use case would be as follows:
63 *
64 * ```js
65 * const values = ['lorem ipsum', 'dolor sit amet'];
66 * const rl = readline.createInterface(process.stdin);
67 * const showResults = debounce(() => {
68 * console.log(
69 * '\n',
70 * values.filter((val) => val.startsWith(rl.line)).join(' ')
71 * );
72 * }, 300);
73 * process.stdin.on('keypress', (c, k) => {
74 * showResults();
75 * });
76 * ```
77 * @since v0.1.98
78 */
79 readonly line: string;
80 /**
81 * The cursor position relative to `rl.line`.
82 *
83 * This will track where the current cursor lands in the input string, when
84 * reading input from a TTY stream. The position of cursor determines the
85 * portion of the input string that will be modified as input is processed,
86 * as well as the column where the terminal caret will be rendered.
87 * @since v0.1.98
88 */
89 readonly cursor: number;
90 /**
91 * NOTE: According to the documentation:
92 *
93 * > Instances of the `readline.Interface` class are constructed using the
94 * > `readline.createInterface()` method.
95 *
96 * @see https://nodejs.org/dist/latest-v10.x/docs/api/readline.html#readline_class_interface
97 */
98 protected constructor(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer | AsyncCompleter, terminal?: boolean);
99 /**
100 * NOTE: According to the documentation:
101 *
102 * > Instances of the `readline.Interface` class are constructed using the
103 * > `readline.createInterface()` method.
104 *
105 * @see https://nodejs.org/dist/latest-v10.x/docs/api/readline.html#readline_class_interface
106 */
107 protected constructor(options: ReadLineOptions);
108 /**
109 * The `rl.getPrompt()` method returns the current prompt used by `rl.prompt()`.
110 * @since v15.3.0
111 * @return the current prompt string
112 */
113 getPrompt(): string;
114 /**
115 * The `rl.setPrompt()` method sets the prompt that will be written to `output`whenever `rl.prompt()` is called.
116 * @since v0.1.98
117 */
118 setPrompt(prompt: string): void;
119 /**
120 * The `rl.prompt()` method writes the `readline.Interface` instances configured`prompt` to a new line in `output` in order to provide a user with a new
121 * location at which to provide input.
122 *
123 * When called, `rl.prompt()` will resume the `input` stream if it has been
124 * paused.
125 *
126 * If the `readline.Interface` was created with `output` set to `null` or`undefined` the prompt is not written.
127 * @since v0.1.98
128 * @param preserveCursor If `true`, prevents the cursor placement from being reset to `0`.
129 */
130 prompt(preserveCursor?: boolean): void;
131 /**
132 * The `rl.question()` method displays the `query` by writing it to the `output`,
133 * waits for user input to be provided on `input`, then invokes the `callback`function passing the provided input as the first argument.
134 *
135 * When called, `rl.question()` will resume the `input` stream if it has been
136 * paused.
137 *
138 * If the `readline.Interface` was created with `output` set to `null` or`undefined` the `query` is not written.
139 *
140 * The `callback` function passed to `rl.question()` does not follow the typical
141 * pattern of accepting an `Error` object or `null` as the first argument.
142 * The `callback` is called with the provided answer as the only argument.
143 *
144 * Example usage:
145 *
146 * ```js
147 * rl.question('What is your favorite food? ', (answer) => {
148 * console.log(`Oh, so your favorite food is ${answer}`);
149 * });
150 * ```
151 *
152 * Using an `AbortController` to cancel a question.
153 *
154 * ```js
155 * const ac = new AbortController();
156 * const signal = ac.signal;
157 *
158 * rl.question('What is your favorite food? ', { signal }, (answer) => {
159 * console.log(`Oh, so your favorite food is ${answer}`);
160 * });
161 *
162 * signal.addEventListener('abort', () => {
163 * console.log('The food question timed out');
164 * }, { once: true });
165 *
166 * setTimeout(() => ac.abort(), 10000);
167 * ```
168 *
169 * If this method is invoked as it's util.promisify()ed version, it returns a
170 * Promise that fulfills with the answer. If the question is canceled using
171 * an `AbortController` it will reject with an `AbortError`.
172 *
173 * ```js
174 * const util = require('util');
175 * const question = util.promisify(rl.question).bind(rl);
176 *
177 * async function questionExample() {
178 * try {
179 * const answer = await question('What is you favorite food? ');
180 * console.log(`Oh, so your favorite food is ${answer}`);
181 * } catch (err) {
182 * console.error('Question rejected', err);
183 * }
184 * }
185 * questionExample();
186 * ```
187 * @since v0.3.3
188 * @param query A statement or query to write to `output`, prepended to the prompt.
189 * @param callback A callback function that is invoked with the user's input in response to the `query`.
190 */
191 question(query: string, callback: (answer: string) => void): void;
192 question(query: string, options: Abortable, callback: (answer: string) => void): void;
193 /**
194 * The `rl.pause()` method pauses the `input` stream, allowing it to be resumed
195 * later if necessary.
196 *
197 * Calling `rl.pause()` does not immediately pause other events (including`'line'`) from being emitted by the `readline.Interface` instance.
198 * @since v0.3.4
199 */
200 pause(): this;
201 /**
202 * The `rl.resume()` method resumes the `input` stream if it has been paused.
203 * @since v0.3.4
204 */
205 resume(): this;
206 /**
207 * The `rl.close()` method closes the `readline.Interface` instance and
208 * relinquishes control over the `input` and `output` streams. When called,
209 * the `'close'` event will be emitted.
210 *
211 * Calling `rl.close()` does not immediately stop other events (including `'line'`)
212 * from being emitted by the `readline.Interface` instance.
213 * @since v0.1.98
214 */
215 close(): void;
216 /**
217 * The `rl.write()` method will write either `data` or a key sequence identified
218 * by `key` to the `output`. The `key` argument is supported only if `output` is
219 * a `TTY` text terminal. See `TTY keybindings` for a list of key
220 * combinations.
221 *
222 * If `key` is specified, `data` is ignored.
223 *
224 * When called, `rl.write()` will resume the `input` stream if it has been
225 * paused.
226 *
227 * If the `readline.Interface` was created with `output` set to `null` or`undefined` the `data` and `key` are not written.
228 *
229 * ```js
230 * rl.write('Delete this!');
231 * // Simulate Ctrl+U to delete the line written previously
232 * rl.write(null, { ctrl: true, name: 'u' });
233 * ```
234 *
235 * The `rl.write()` method will write the data to the `readline` `Interface`'s`input`_as if it were provided by the user_.
236 * @since v0.1.98
237 */
238 write(data: string | Buffer, key?: Key): void;
239 /**
240 * Returns the real position of the cursor in relation to the input
241 * prompt + string. Long input (wrapping) strings, as well as multiple
242 * line prompts are included in the calculations.
243 * @since v13.5.0, v12.16.0
244 */
245 getCursorPos(): CursorPos;
246 /**
247 * events.EventEmitter
248 * 1. close
249 * 2. line
250 * 3. pause
251 * 4. resume
252 * 5. SIGCONT
253 * 6. SIGINT
254 * 7. SIGTSTP
255 * 8. history
256 */
257 addListener(event: string, listener: (...args: any[]) => void): this;
258 addListener(event: 'close', listener: () => void): this;
259 addListener(event: 'line', listener: (input: string) => void): this;
260 addListener(event: 'pause', listener: () => void): this;
261 addListener(event: 'resume', listener: () => void): this;
262 addListener(event: 'SIGCONT', listener: () => void): this;
263 addListener(event: 'SIGINT', listener: () => void): this;
264 addListener(event: 'SIGTSTP', listener: () => void): this;
265 addListener(event: 'history', listener: (history: string[]) => void): this;
266 emit(event: string | symbol, ...args: any[]): boolean;
267 emit(event: 'close'): boolean;
268 emit(event: 'line', input: string): boolean;
269 emit(event: 'pause'): boolean;
270 emit(event: 'resume'): boolean;
271 emit(event: 'SIGCONT'): boolean;
272 emit(event: 'SIGINT'): boolean;
273 emit(event: 'SIGTSTP'): boolean;
274 emit(event: 'history', history: string[]): boolean;
275 on(event: string, listener: (...args: any[]) => void): this;
276 on(event: 'close', listener: () => void): this;
277 on(event: 'line', listener: (input: string) => void): this;
278 on(event: 'pause', listener: () => void): this;
279 on(event: 'resume', listener: () => void): this;
280 on(event: 'SIGCONT', listener: () => void): this;
281 on(event: 'SIGINT', listener: () => void): this;
282 on(event: 'SIGTSTP', listener: () => void): this;
283 on(event: 'history', listener: (history: string[]) => void): this;
284 once(event: string, listener: (...args: any[]) => void): this;
285 once(event: 'close', listener: () => void): this;
286 once(event: 'line', listener: (input: string) => void): this;
287 once(event: 'pause', listener: () => void): this;
288 once(event: 'resume', listener: () => void): this;
289 once(event: 'SIGCONT', listener: () => void): this;
290 once(event: 'SIGINT', listener: () => void): this;
291 once(event: 'SIGTSTP', listener: () => void): this;
292 once(event: 'history', listener: (history: string[]) => void): this;
293 prependListener(event: string, listener: (...args: any[]) => void): this;
294 prependListener(event: 'close', listener: () => void): this;
295 prependListener(event: 'line', listener: (input: string) => void): this;
296 prependListener(event: 'pause', listener: () => void): this;
297 prependListener(event: 'resume', listener: () => void): this;
298 prependListener(event: 'SIGCONT', listener: () => void): this;
299 prependListener(event: 'SIGINT', listener: () => void): this;
300 prependListener(event: 'SIGTSTP', listener: () => void): this;
301 prependListener(event: 'history', listener: (history: string[]) => void): this;
302 prependOnceListener(event: string, listener: (...args: any[]) => void): this;
303 prependOnceListener(event: 'close', listener: () => void): this;
304 prependOnceListener(event: 'line', listener: (input: string) => void): this;
305 prependOnceListener(event: 'pause', listener: () => void): this;
306 prependOnceListener(event: 'resume', listener: () => void): this;
307 prependOnceListener(event: 'SIGCONT', listener: () => void): this;
308 prependOnceListener(event: 'SIGINT', listener: () => void): this;
309 prependOnceListener(event: 'SIGTSTP', listener: () => void): this;
310 prependOnceListener(event: 'history', listener: (history: string[]) => void): this;
311 [Symbol.asyncIterator](): AsyncIterableIterator<string>;
312 }
313 type ReadLine = Interface; // type forwarded for backwards compatibility
314 type Completer = (line: string) => CompleterResult;
315 type AsyncCompleter = (line: string, callback: (err?: null | Error, result?: CompleterResult) => void) => void;
316 type CompleterResult = [string[], string];
317 interface ReadLineOptions {
318 input: NodeJS.ReadableStream;
319 output?: NodeJS.WritableStream | undefined;
320 completer?: Completer | AsyncCompleter | undefined;
321 terminal?: boolean | undefined;
322 /**
323 * Initial list of history lines. This option makes sense
324 * only if `terminal` is set to `true` by the user or by an internal `output`
325 * check, otherwise the history caching mechanism is not initialized at all.
326 * @default []
327 */
328 history?: string[] | undefined;
329 historySize?: number | undefined;
330 prompt?: string | undefined;
331 crlfDelay?: number | undefined;
332 /**
333 * If `true`, when a new input line added
334 * to the history list duplicates an older one, this removes the older line
335 * from the list.
336 * @default false
337 */
338 removeHistoryDuplicates?: boolean | undefined;
339 escapeCodeTimeout?: number | undefined;
340 tabSize?: number | undefined;
341 }
342 /**
343 * The `readline.createInterface()` method creates a new `readline.Interface`instance.
344 *
345 * ```js
346 * const readline = require('readline');
347 * const rl = readline.createInterface({
348 * input: process.stdin,
349 * output: process.stdout
350 * });
351 * ```
352 *
353 * Once the `readline.Interface` instance is created, the most common case is to
354 * listen for the `'line'` event:
355 *
356 * ```js
357 * rl.on('line', (line) => {
358 * console.log(`Received: ${line}`);
359 * });
360 * ```
361 *
362 * If `terminal` is `true` for this instance then the `output` stream will get
363 * the best compatibility if it defines an `output.columns` property and emits
364 * a `'resize'` event on the `output` if or when the columns ever change
365 * (`process.stdout` does this automatically when it is a TTY).
366 *
367 * When creating a `readline.Interface` using `stdin` as input, the program
368 * will not terminate until it receives `EOF` (Ctrl+D on
369 * Linux/macOS, Ctrl+Z followed by Return on
370 * Windows).
371 * If you want your application to exit without waiting for user input, you can `unref()` the standard input stream:
372 *
373 * ```js
374 * process.stdin.unref();
375 * ```
376 * @since v0.1.98
377 */
378 function createInterface(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer | AsyncCompleter, terminal?: boolean): Interface;
379 function createInterface(options: ReadLineOptions): Interface;
380 /**
381 * The `readline.emitKeypressEvents()` method causes the given `Readable` stream to begin emitting `'keypress'` events corresponding to received input.
382 *
383 * Optionally, `interface` specifies a `readline.Interface` instance for which
384 * autocompletion is disabled when copy-pasted input is detected.
385 *
386 * If the `stream` is a `TTY`, then it must be in raw mode.
387 *
388 * This is automatically called by any readline instance on its `input` if the`input` is a terminal. Closing the `readline` instance does not stop
389 * the `input` from emitting `'keypress'` events.
390 *
391 * ```js
392 * readline.emitKeypressEvents(process.stdin);
393 * if (process.stdin.isTTY)
394 * process.stdin.setRawMode(true);
395 * ```
396 * @since v0.7.7
397 */
398 function emitKeypressEvents(stream: NodeJS.ReadableStream, readlineInterface?: Interface): void;
399 type Direction = -1 | 0 | 1;
400 interface CursorPos {
401 rows: number;
402 cols: number;
403 }
404 /**
405 * The `readline.clearLine()` method clears current line of given `TTY` stream
406 * in a specified direction identified by `dir`.
407 * @since v0.7.7
408 * @param callback Invoked once the operation completes.
409 * @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
410 */
411 function clearLine(stream: NodeJS.WritableStream, dir: Direction, callback?: () => void): boolean;
412 /**
413 * The `readline.clearScreenDown()` method clears the given `TTY` stream from
414 * the current position of the cursor down.
415 * @since v0.7.7
416 * @param callback Invoked once the operation completes.
417 * @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
418 */
419 function clearScreenDown(stream: NodeJS.WritableStream, callback?: () => void): boolean;
420 /**
421 * The `readline.cursorTo()` method moves cursor to the specified position in a
422 * given `TTY` `stream`.
423 * @since v0.7.7
424 * @param callback Invoked once the operation completes.
425 * @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
426 */
427 function cursorTo(stream: NodeJS.WritableStream, x: number, y?: number, callback?: () => void): boolean;
428 /**
429 * The `readline.moveCursor()` method moves the cursor _relative_ to its current
430 * position in a given `TTY` `stream`.
431 *
432 * ## Example: Tiny CLI
433 *
434 * The following example illustrates the use of `readline.Interface` class to
435 * implement a small command-line interface:
436 *
437 * ```js
438 * const readline = require('readline');
439 * const rl = readline.createInterface({
440 * input: process.stdin,
441 * output: process.stdout,
442 * prompt: 'OHAI> '
443 * });
444 *
445 * rl.prompt();
446 *
447 * rl.on('line', (line) => {
448 * switch (line.trim()) {
449 * case 'hello':
450 * console.log('world!');
451 * break;
452 * default:
453 * console.log(`Say what? I might have heard '${line.trim()}'`);
454 * break;
455 * }
456 * rl.prompt();
457 * }).on('close', () => {
458 * console.log('Have a great day!');
459 * process.exit(0);
460 * });
461 * ```
462 *
463 * ## Example: Read file stream line-by-Line
464 *
465 * A common use case for `readline` is to consume an input file one line at a
466 * time. The easiest way to do so is leveraging the `fs.ReadStream` API as
467 * well as a `for await...of` loop:
468 *
469 * ```js
470 * const fs = require('fs');
471 * const readline = require('readline');
472 *
473 * async function processLineByLine() {
474 * const fileStream = fs.createReadStream('input.txt');
475 *
476 * const rl = readline.createInterface({
477 * input: fileStream,
478 * crlfDelay: Infinity
479 * });
480 * // Note: we use the crlfDelay option to recognize all instances of CR LF
481 * // ('\r\n') in input.txt as a single line break.
482 *
483 * for await (const line of rl) {
484 * // Each line in input.txt will be successively available here as `line`.
485 * console.log(`Line from file: ${line}`);
486 * }
487 * }
488 *
489 * processLineByLine();
490 * ```
491 *
492 * Alternatively, one could use the `'line'` event:
493 *
494 * ```js
495 * const fs = require('fs');
496 * const readline = require('readline');
497 *
498 * const rl = readline.createInterface({
499 * input: fs.createReadStream('sample.txt'),
500 * crlfDelay: Infinity
501 * });
502 *
503 * rl.on('line', (line) => {
504 * console.log(`Line from file: ${line}`);
505 * });
506 * ```
507 *
508 * Currently, `for await...of` loop can be a bit slower. If `async` / `await`flow and speed are both essential, a mixed approach can be applied:
509 *
510 * ```js
511 * const { once } = require('events');
512 * const { createReadStream } = require('fs');
513 * const { createInterface } = require('readline');
514 *
515 * (async function processLineByLine() {
516 * try {
517 * const rl = createInterface({
518 * input: createReadStream('big-file.txt'),
519 * crlfDelay: Infinity
520 * });
521 *
522 * rl.on('line', (line) => {
523 * // Process the line.
524 * });
525 *
526 * await once(rl, 'close');
527 *
528 * console.log('File processed.');
529 * } catch (err) {
530 * console.error(err);
531 * }
532 * })();
533 * ```
534 * @since v0.7.7
535 * @param callback Invoked once the operation completes.
536 * @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
537 */
538 function moveCursor(stream: NodeJS.WritableStream, dx: number, dy: number, callback?: () => void): boolean;
539}
540declare module 'node:readline' {
541 export * from 'readline';
542}