Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/doc/api
diff options
context:
space:
mode:
authorAntoine du Hamel <duhamelantoine1995@gmail.com>2021-04-27 17:14:39 +0300
committerAntoine du Hamel <duhamelantoine1995@gmail.com>2021-09-17 00:16:37 +0300
commit8122d243ae010f3a5c1d50e4d0ef6374d4e407b4 (patch)
tree3ab213dec7b55944afcc96ae0c271bcc1276e3a1 /doc/api
parent592d1c3d4442c3b0d6d747a7dc02797e63f97702 (diff)
readline: introduce promise-based API
PR-URL: https://github.com/nodejs/node/pull/37947 Fixes: https://github.com/nodejs/node/issues/37287 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Robert Nagy <ronagy@icloud.com>
Diffstat (limited to 'doc/api')
-rw-r--r--doc/api/readline.md467
1 files changed, 417 insertions, 50 deletions
diff --git a/doc/api/readline.md b/doc/api/readline.md
index 8f056c942e3..b886c5b2bb6 100644
--- a/doc/api/readline.md
+++ b/doc/api/readline.md
@@ -7,22 +7,48 @@
<!-- source_link=lib/readline.js -->
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
-using:
+stream (such as [`process.stdin`][]) one line at a time.
-```js
+To use the promise-based APIs:
+
+```mjs
+import * as readline from 'node:readline/promises';
+```
+
+```cjs
+const readline = require('readline/promises');
+```
+
+To use the callback and sync APIs:
+
+```mjs
+import * as readline from 'node:readline';
+```
+
+```cjs
const readline = require('readline');
```
The following simple example illustrates the basic use of the `readline` module.
-```js
+```mjs
+import * as readline from 'node:readline/promises';
+import { stdin as input, stdout as output } from 'process';
+
+const rl = readline.createInterface({ input, output });
+
+const answer = await rl.question('What do you think of Node.js? ');
+
+console.log(`Thank you for your valuable feedback: ${answer}`);
+
+rl.close();
+```
+
+```cjs
const readline = require('readline');
+const { stdin: input, stdout: output } = require('process');
-const rl = readline.createInterface({
- input: process.stdin,
- output: process.stdout
-});
+const rl = readline.createInterface({ input, output });
rl.question('What do you think of Node.js? ', (answer) => {
// TODO: Log the answer in a database
@@ -36,16 +62,18 @@ 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
received on the `input` stream.
-## Class: `Interface`
+<a id='readline_class_interface'></a>
+## Class: `InterfaceConstructor`
<!-- YAML
added: v0.1.104
-->
* Extends: {EventEmitter}
-Instances of the `readline.Interface` class are constructed using the
-`readline.createInterface()` method. Every instance is associated with a
-single `input` [Readable][] stream and a single `output` [Writable][] stream.
+Instances of the `InterfaceConstructor` class are constructed using the
+`readlinePromises.createInterface()` or `readline.createInterface()` method.
+Every instance is associated with a single `input` [Readable][] stream and a
+single `output` [Writable][] stream.
The `output` stream is used to print prompts for user input that arrives on,
and is read from, the `input` stream.
@@ -56,18 +84,18 @@ added: v0.1.98
The `'close'` event is emitted when one of the following occur:
-* The `rl.close()` method is called and the `readline.Interface` instance has
+* The `rl.close()` method is called and the `InterfaceConstructor` instance has
relinquished control over the `input` and `output` streams;
* The `input` stream receives its `'end'` event;
* The `input` stream receives <kbd>Ctrl</kbd>+<kbd>D</kbd> to signal
end-of-transmission (EOT);
* The `input` stream receives <kbd>Ctrl</kbd>+<kbd>C</kbd> to signal `SIGINT`
and there is no `'SIGINT'` event listener registered on the
- `readline.Interface` instance.
+ `InterfaceConstructor` instance.
The listener function is called without passing any arguments.
-The `readline.Interface` instance is finished once the `'close'` event is
+The `InterfaceConstructor` instance is finished once the `'close'` event is
emitted.
### Event: `'line'`
@@ -220,12 +248,12 @@ The `'SIGTSTP'` event is _not_ supported on Windows.
added: v0.1.98
-->
-The `rl.close()` method closes the `readline.Interface` instance and
+The `rl.close()` method closes the `InterfaceConstructor` instance and
relinquishes control over the `input` and `output` streams. When called,
the `'close'` event will be emitted.
Calling `rl.close()` does not immediately stop other events (including `'line'`)
-from being emitted by the `readline.Interface` instance.
+from being emitted by the `InterfaceConstructor` instance.
### `rl.pause()`
<!-- YAML
@@ -236,7 +264,7 @@ The `rl.pause()` method pauses the `input` stream, allowing it to be resumed
later if necessary.
Calling `rl.pause()` does not immediately pause other events (including
-`'line'`) from being emitted by the `readline.Interface` instance.
+`'line'`) from being emitted by the `InterfaceConstructor` instance.
### `rl.prompt([preserveCursor])`
<!-- YAML
@@ -246,14 +274,14 @@ added: v0.1.98
* `preserveCursor` {boolean} If `true`, prevents the cursor placement from
being reset to `0`.
-The `rl.prompt()` method writes the `readline.Interface` instances configured
+The `rl.prompt()` method writes the `InterfaceConstructor` instances configured
`prompt` to a new line in `output` in order to provide a user with a new
location at which to provide input.
When called, `rl.prompt()` will resume the `input` stream if it has been
paused.
-If the `readline.Interface` was created with `output` set to `null` or
+If the `InterfaceConstructor` was created with `output` set to `null` or
`undefined` the prompt is not written.
### `rl.question(query[, options], callback)`
@@ -276,7 +304,7 @@ function passing the provided input as the first argument.
When called, `rl.question()` will resume the `input` stream if it has been
paused.
-If the `readline.Interface` was created with `output` set to `null` or
+If the `InterfaceConstructor` was created with `output` set to `null` or
`undefined` the `query` is not written.
The `callback` function passed to `rl.question()` does not follow the typical
@@ -377,7 +405,7 @@ If `key` is specified, `data` is ignored.
When called, `rl.write()` will resume the `input` stream if it has been
paused.
-If the `readline.Interface` was created with `output` set to `null` or
+If the `InterfaceConstructor` was created with `output` set to `null` or
`undefined` the `data` and `key` are not written.
```js
@@ -406,13 +434,13 @@ changes:
Create an `AsyncIterator` object that iterates through each line in the input
stream as a string. This method allows asynchronous iteration of
-`readline.Interface` objects through `for await...of` loops.
+`InterfaceConstructor` objects through `for await...of` loops.
Errors in the input stream are not forwarded.
If the loop is terminated with `break`, `throw`, or `return`,
[`rl.close()`][] will be called. In other words, iterating over a
-`readline.Interface` will always consume the input stream fully.
+`InterfaceConstructor` will always consume the input stream fully.
Performance is not on par with the traditional `'line'` event API. Use `'line'`
instead for performance-sensitive applications.
@@ -502,7 +530,346 @@ Returns the real position of the cursor in relation to the input
prompt + string. Long input (wrapping) strings, as well as multiple
line prompts are included in the calculations.
-## `readline.clearLine(stream, dir[, callback])`
+## Promises API
+<!-- YAML
+added: REPLACEME
+-->
+
+### Class: `readlinePromises.Interface`
+<!-- YAML
+added: REPLACEME
+-->
+
+* Extends: {readline.InterfaceConstructor}
+
+Instances of the `readlinePromises.Interface` class are constructed using the
+`readlinePromises.createInterface()` method. Every instance is associated with a
+single `input` [Readable][] stream and a single `output` [Writable][] stream.
+The `output` stream is used to print prompts for user input that arrives on,
+and is read from, the `input` stream.
+
+#### `rl.question(query[, options])`
+<!-- YAML
+added: REPLACEME
+-->
+
+* `query` {string} A statement or query to write to `output`, prepended to the
+ prompt.
+* `options` {Object}
+ * `signal` {AbortSignal} Optionally allows the `question()` to be canceled
+ using an `AbortController`.
+* Returns: {Promise} A promise that is fulfilled with the user's
+ input in response to the `query`.
+
+The `rl.question()` method displays the `query` by writing it to the `output`,
+waits for user input to be provided on `input`, then invokes the `callback`
+function passing the provided input as the first argument.
+
+When called, `rl.question()` will resume the `input` stream if it has been
+paused.
+
+If the `readlinePromises.Interface` was created with `output` set to `null` or
+`undefined` the `query` is not written.
+
+Example usage:
+
+```mjs
+const answer = await rl.question('What is your favorite food? ');
+console.log(`Oh, so your favorite food is ${answer}`);
+```
+
+Using an `AbortController` to cancel a question.
+
+```mjs
+const ac = new AbortController();
+const signal = ac.signal;
+
+const answer = await rl.question('What is your favorite food? ', { signal });
+console.log(`Oh, so your favorite food is ${answer}`);
+
+signal.addEventListener('abort', () => {
+ console.log('The food question timed out');
+}, { once: true });
+
+setTimeout(() => ac.abort(), 10000);
+```
+
+### Class: `readlinePromises.Readline`
+<!-- YAML
+added: REPLACEME
+-->
+
+#### `new readlinePromises.Readline(stream)`
+<!-- YAML
+added: REPLACEME
+-->
+
+* `stream` {stream.Writable} A [TTY][] stream.
+
+#### `rl.clearLine(dir)`
+<!-- YAML
+added: REPLACEME
+-->
+
+* `dir` {integer}
+ * `-1`: to the left from cursor
+ * `1`: to the right from cursor
+ * `0`: the entire line
+* Returns: this
+
+The `rl.clearLine()` method adds to the internal list of pending action an
+action that clears current line of the associated `stream` in a specified
+direction identified by `dir`.
+You need to call `rl.commit()` to see the effect of this method.
+
+#### `rl.clearScreenDown()`
+<!-- YAML
+added: REPLACEME
+-->
+
+* Returns: this
+
+The `rl.clearScreenDown()` method adds to the internal list of pending action an
+action that clears the associated stream from the current position of the
+cursor down.
+You need to call `rl.commit()` to see the effect of this method.
+
+#### `rl.commit()`
+<!-- YAML
+added: REPLACEME
+-->
+
+* Returns: {Promise}
+
+The `rl.commit()` method sends all the pending actions to the associated
+`stream` and clears the internal list of pending actions.
+
+#### `rl.cursorTo(x[, y])`
+<!-- YAML
+added: REPLACEME
+-->
+
+* `x` {integer}
+* `y` {integer}
+* Returns: this
+
+The `rl.cursorTo()` method adds to the internal list of pending action an action
+that moves cursor to the specified position in the associated `stream`.
+You need to call `rl.commit()` to see the effect of this method.
+
+#### `rl.moveCursor(dx, dy)`
+<!-- YAML
+added: REPLACEME
+-->
+
+* `dx` {integer}
+* `dy` {integer}
+* Returns: this
+
+The `rl.moveCursor()` method adds to the internal list of pending action an
+action that moves the cursor *relative* to its current position in the
+associated `stream`.
+You need to call `rl.commit()` to see the effect of this method.
+
+#### `rl.rollback()`
+<!-- YAML
+added: REPLACEME
+-->
+
+* Returns: this
+
+The `rl.rollback` methods clears the internal list of pending actions without
+sending it to the associated `stream`.
+
+### `readlinePromises.createInterface(options)`
+<!-- YAML
+added: REPLACEME
+-->
+
+* `options` {Object}
+ * `input` {stream.Readable} The [Readable][] stream to listen to. This option
+ is *required*.
+ * `output` {stream.Writable} The [Writable][] stream to write readline data
+ to.
+ * `completer` {Function} An optional function used for Tab autocompletion.
+ * `terminal` {boolean} `true` if the `input` and `output` streams should be
+ treated like a TTY, and have ANSI/VT100 escape codes written to it.
+ **Default:** checking `isTTY` on the `output` stream upon instantiation.
+ * `history` {string[]} Initial list of history lines. This option makes sense
+ only if `terminal` is set to `true` by the user or by an internal `output`
+ check, otherwise the history caching mechanism is not initialized at all.
+ **Default:** `[]`.
+ * `historySize` {number} Maximum number of history lines retained. To disable
+ the history set this value to `0`. This option makes sense only if
+ `terminal` is set to `true` by the user or by an internal `output` check,
+ otherwise the history caching mechanism is not initialized at all.
+ **Default:** `30`.
+ * `removeHistoryDuplicates` {boolean} If `true`, when a new input line added
+ to the history list duplicates an older one, this removes the older line
+ from the list. **Default:** `false`.
+ * `prompt` {string} The prompt string to use. **Default:** `'> '`.
+ * `crlfDelay` {number} If the delay between `\r` and `\n` exceeds
+ `crlfDelay` milliseconds, both `\r` and `\n` will be treated as separate
+ end-of-line input. `crlfDelay` will be coerced to a number no less than
+ `100`. It can be set to `Infinity`, in which case `\r` followed by `\n`
+ will always be considered a single newline (which may be reasonable for
+ [reading files][] with `\r\n` line delimiter). **Default:** `100`.
+ * `escapeCodeTimeout` {number} The duration `readlinePromises` will wait for a
+ character (when reading an ambiguous key sequence in milliseconds one that
+ can both form a complete key sequence using the input read so far and can
+ take additional input to complete a longer key sequence).
+ **Default:** `500`.
+ * `tabSize` {integer} The number of spaces a tab is equal to (minimum 1).
+ **Default:** `8`.
+* Returns: {readlinePromises.Interface}
+
+The `readlinePromises.createInterface()` method creates a new `readlinePromises.Interface`
+instance.
+
+```js
+const readlinePromises = require('readline/promises');
+const rl = readlinePromises.createInterface({
+ input: process.stdin,
+ output: process.stdout
+});
+```
+
+Once the `readlinePromises.Interface` instance is created, the most common case
+is to listen for the `'line'` event:
+
+```js
+rl.on('line', (line) => {
+ console.log(`Received: ${line}`);
+});
+```
+
+If `terminal` is `true` for this instance then the `output` stream will get
+the best compatibility if it defines an `output.columns` property and emits
+a `'resize'` event on the `output` if or when the columns ever change
+([`process.stdout`][] does this automatically when it is a TTY).
+
+#### Use of the `completer` function
+
+The `completer` function takes the current line entered by the user
+as an argument, and returns an `Array` with 2 entries:
+
+* An `Array` with matching entries for the completion.
+* The substring that was used for the matching.
+
+For instance: `[[substr1, substr2, ...], originalsubstring]`.
+
+```js
+function completer(line) {
+ const completions = '.help .error .exit .quit .q'.split(' ');
+ const hits = completions.filter((c) => c.startsWith(line));
+ // Show all completions if none found
+ return [hits.length ? hits : completions, line];
+}
+```
+
+The `completer` function can also returns a {Promise}, or be asynchronous:
+
+```js
+async function completer(linePartial) {
+ await someAsyncWork();
+ return [['123'], linePartial];
+}
+```
+
+## Callback API
+<!-- YAML
+added: v0.1.104
+-->
+
+### Class: `readline.Interface`
+<!-- YAML
+added: v0.1.104
+changes:
+ - version: REPLACEME
+ pr-url: https://github.com/nodejs/node/pull/37947
+ description: The class `readline.Interface` now inherits from `Interface`.
+-->
+
+* Extends: {readline.InterfaceConstructor}
+
+Instances of the `readline.Interface` class are constructed using the
+`readline.createInterface()` method. Every instance is associated with a
+single `input` [Readable][] stream and a single `output` [Writable][] stream.
+The `output` stream is used to print prompts for user input that arrives on,
+and is read from, the `input` stream.
+
+#### `rl.question(query[, options], callback)`
+<!-- YAML
+added: v0.3.3
+-->
+
+* `query` {string} A statement or query to write to `output`, prepended to the
+ prompt.
+* `options` {Object}
+ * `signal` {AbortSignal} Optionally allows the `question()` to be canceled
+ using an `AbortController`.
+* `callback` {Function} A callback function that is invoked with the user's
+ input in response to the `query`.
+
+The `rl.question()` method displays the `query` by writing it to the `output`,
+waits for user input to be provided on `input`, then invokes the `callback`
+function passing the provided input as the first argument.
+
+When called, `rl.question()` will resume the `input` stream if it has been
+paused.
+
+If the `readline.Interface` was created with `output` set to `null` or
+`undefined` the `query` is not written.
+
+The `callback` function passed to `rl.question()` does not follow the typical
+pattern of accepting an `Error` object or `null` as the first argument.
+The `callback` is called with the provided answer as the only argument.
+
+Example usage:
+
+```js
+rl.question('What is your favorite food? ', (answer) => {
+ console.log(`Oh, so your favorite food is ${answer}`);
+});
+```
+
+Using an `AbortController` to cancel a question.
+
+```js
+const ac = new AbortController();
+const signal = ac.signal;
+
+rl.question('What is your favorite food? ', { signal }, (answer) => {
+ console.log(`Oh, so your favorite food is ${answer}`);
+});
+
+signal.addEventListener('abort', () => {
+ console.log('The food question timed out');
+}, { once: true });
+
+setTimeout(() => ac.abort(), 10000);
+```
+
+If this method is invoked as it's util.promisify()ed version, it returns a
+Promise that fulfills with the answer. If the question is canceled using
+an `AbortController` it will reject with an `AbortError`.
+
+```js
+const util = require('util');
+const question = util.promisify(rl.question).bind(rl);
+
+async function questionExample() {
+ try {
+ const answer = await question('What is you favorite food? ');
+ console.log(`Oh, so your favorite food is ${answer}`);
+ } catch (err) {
+ console.error('Question rejected', err);
+ }
+}
+questionExample();
+```
+
+### `readline.clearLine(stream, dir[, callback])`
<!-- YAML
added: v0.7.7
changes:
@@ -524,7 +891,7 @@ changes:
The `readline.clearLine()` method clears current line of given [TTY][] stream
in a specified direction identified by `dir`.
-## `readline.clearScreenDown(stream[, callback])`
+### `readline.clearScreenDown(stream[, callback])`
<!-- YAML
added: v0.7.7
changes:
@@ -542,7 +909,7 @@ changes:
The `readline.clearScreenDown()` method clears the given [TTY][] stream from
the current position of the cursor down.
-## `readline.createInterface(options)`
+### `readline.createInterface(options)`
<!-- YAML
added: v0.1.98
changes:
@@ -646,7 +1013,7 @@ If you want your application to exit without waiting for user input, you can
process.stdin.unref();
```
-### Use of the `completer` function
+#### Use of the `completer` function
The `completer` function takes the current line entered by the user
as an argument, and returns an `Array` with 2 entries:
@@ -674,7 +1041,7 @@ function completer(linePartial, callback) {
}
```
-## `readline.cursorTo(stream, x[, y][, callback])`
+### `readline.cursorTo(stream, x[, y][, callback])`
<!-- YAML
added: v0.7.7
changes:
@@ -694,13 +1061,33 @@ changes:
The `readline.cursorTo()` method moves cursor to the specified position in a
given [TTY][] `stream`.
+### `readline.moveCursor(stream, dx, dy[, callback])`
+<!-- YAML
+added: v0.7.7
+changes:
+ - version: v12.7.0
+ pr-url: https://github.com/nodejs/node/pull/28674
+ description: The stream's write() callback and return value are exposed.
+-->
+
+* `stream` {stream.Writable}
+* `dx` {number}
+* `dy` {number}
+* `callback` {Function} Invoked once the operation completes.
+* Returns: {boolean} `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`.
+
+The `readline.moveCursor()` method moves the cursor *relative* to its current
+position in a given [TTY][] `stream`.
+
## `readline.emitKeypressEvents(stream[, interface])`
<!-- YAML
added: v0.7.7
-->
* `stream` {stream.Readable}
-* `interface` {readline.Interface}
+* `interface` {readline.InterfaceConstructor}
The `readline.emitKeypressEvents()` method causes the given [Readable][]
stream to begin emitting `'keypress'` events corresponding to received input.
@@ -720,26 +1107,6 @@ if (process.stdin.isTTY)
process.stdin.setRawMode(true);
```
-## `readline.moveCursor(stream, dx, dy[, callback])`
-<!-- YAML
-added: v0.7.7
-changes:
- - version: v12.7.0
- pr-url: https://github.com/nodejs/node/pull/28674
- description: The stream's write() callback and return value are exposed.
--->
-
-* `stream` {stream.Writable}
-* `dx` {number}
-* `dy` {number}
-* `callback` {Function} Invoked once the operation completes.
-* Returns: {boolean} `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`.
-
-The `readline.moveCursor()` method moves the cursor *relative* to its current
-position in a given [TTY][] `stream`.
-
## Example: Tiny CLI
The following example illustrates the use of `readline.Interface` class to