Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
readline: add autoCommit option
PR-URL: #37947
Fixes: #37287
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
  • Loading branch information
aduh95 committed Sep 16, 2021
commit 341312d78a8b5b4d5ef03429161242dd9d9b9206
16 changes: 11 additions & 5 deletions doc/api/readline.md
Original file line number Diff line number Diff line change
Expand Up @@ -599,12 +599,14 @@ setTimeout(() => ac.abort(), 10000);
added: REPLACEME
-->

#### `new readlinePromises.Readline(stream)`
#### `new readlinePromises.Readline(stream[, options])`
<!-- YAML
added: REPLACEME
-->

* `stream` {stream.Writable} A [TTY][] stream.
* `options` {Object}
* `autoCommit` {boolean} If `true`, no need to call `rl.commit()`.

#### `rl.clearLine(dir)`
<!-- YAML
Expand All @@ -620,7 +622,8 @@ added: REPLACEME
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.
Call `rl.commit()` to see the effect of this method, unless `autoCommit: true`
was passed to the constructor.

#### `rl.clearScreenDown()`
<!-- YAML
Expand All @@ -632,7 +635,8 @@ added: REPLACEME
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.
Call `rl.commit()` to see the effect of this method, unless `autoCommit: true`
was passed to the constructor.

#### `rl.commit()`
<!-- YAML
Expand All @@ -655,7 +659,8 @@ added: REPLACEME

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.
Call `rl.commit()` to see the effect of this method, unless `autoCommit: true`
was passed to the constructor.

#### `rl.moveCursor(dx, dy)`
<!-- YAML
Expand All @@ -669,7 +674,8 @@ added: REPLACEME
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.
Call `rl.commit()` to see the effect of this method, unless `autoCommit: true`
was passed to the constructor.

#### `rl.rollback()`
<!-- YAML
Expand Down
35 changes: 23 additions & 12 deletions lib/internal/readline/promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const {
} = primordials;

const { CSI } = require('internal/readline/utils');
const { validateInteger } = require('internal/validators');
const { validateBoolean, validateInteger } = require('internal/validators');
const { isWritable } = require('internal/streams/utils');
const { codes: { ERR_INVALID_ARG_TYPE } } = require('internal/errors');

Expand All @@ -19,13 +19,18 @@ const {
} = CSI;

class Readline {
#autoCommit = false;
#stream;
#todo = [];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not blocking but private fields are still very slow in V8. Hidden symbols would probably be a lot more efficient (and consistent with what we do elsewhere)


constructor(stream) {
constructor(stream, options = undefined) {
if (!isWritable(stream))
throw new ERR_INVALID_ARG_TYPE('stream', 'Writable', stream);
this.#stream = stream;
if (options?.autoCommit != null) {
validateBoolean(options.autoCommit, 'options.autoCommit');
this.#autoCommit = options.autoCommit;
}
}

/**
Expand All @@ -38,10 +43,9 @@ class Readline {
validateInteger(x, 'x');
if (y != null) validateInteger(y, 'y');

ArrayPrototypePush(
this.#todo,
y == null ? CSI`${x + 1}G` : CSI`${y + 1};${x + 1}H`
);
const data = y == null ? CSI`${x + 1}G` : CSI`${y + 1};${x + 1}H`;
if (this.#autoCommit) process.nextTick(() => this.#stream.write(data));
else ArrayPrototypePush(this.#todo, data);

return this;
}
Expand Down Expand Up @@ -70,7 +74,8 @@ class Readline {
} else if (dy > 0) {
data += CSI`${dy}B`;
}
ArrayPrototypePush(this.#todo, data);
if (this.#autoCommit) process.nextTick(() => this.#stream.write(data));
else ArrayPrototypePush(this.#todo, data);
}
return this;
}
Expand All @@ -86,10 +91,12 @@ class Readline {
clearLine(dir) {
validateInteger(dir, 'dir', -1, 1);

ArrayPrototypePush(
this.#todo,
dir < 0 ? kClearToLineBeginning : dir > 0 ? kClearToLineEnd : kClearLine
);
const data =
dir < 0 ? kClearToLineBeginning :
dir > 0 ? kClearToLineEnd :
kClearLine;
if (this.#autoCommit) process.nextTick(() => this.#stream.write(data));
else ArrayPrototypePush(this.#todo, data);
return this;
}

Expand All @@ -98,7 +105,11 @@ class Readline {
* @returns {Readline} this
*/
clearScreenDown() {
ArrayPrototypePush(this.#todo, kClearScreenDown);
if (this.#autoCommit) {
process.nextTick(() => this.#stream.write(kClearScreenDown));
} else {
ArrayPrototypePush(this.#todo, kClearScreenDown);
}
return this;
}

Expand Down