lib: add escapeCodeTimeout as an option to createInterface

PR-URL: https://github.com/nodejs/node/pull/19780
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
This commit is contained in:
Raoof 2018-04-04 00:00:35 +04:30 committed by James M Snell
parent 246a6fc107
commit c82920214b
No known key found for this signature in database
GPG Key ID: 7341B15C070877AC
3 changed files with 66 additions and 2 deletions

View File

@ -375,6 +375,11 @@ changes:
* `removeHistoryDuplicates` {boolean} If `true`, when a new input line added * `removeHistoryDuplicates` {boolean} If `true`, when a new input line added
to the history list duplicates an older one, this removes the older line to the history list duplicates an older one, this removes the older line
from the list. **Default:** `false`. from the list. **Default:** `false`.
* `escapeCodeTimeout` {number} The duration `readline` 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`.
The `readline.createInterface()` method creates a new `readline.Interface` The `readline.createInterface()` method creates a new `readline.Interface`
instance. instance.

View File

@ -82,6 +82,7 @@ function Interface(input, output, completer, terminal) {
this.isCompletionEnabled = true; this.isCompletionEnabled = true;
this._sawKeyPress = false; this._sawKeyPress = false;
this._previousKey = null; this._previousKey = null;
this.escapeCodeTimeout = ESCAPE_CODE_TIMEOUT;
EventEmitter.call(this); EventEmitter.call(this);
var historySize; var historySize;
@ -99,6 +100,16 @@ function Interface(input, output, completer, terminal) {
if (input.prompt !== undefined) { if (input.prompt !== undefined) {
prompt = input.prompt; prompt = input.prompt;
} }
if (input.escapeCodeTimeout !== undefined) {
if (Number.isFinite(input.escapeCodeTimeout)) {
this.escapeCodeTimeout = input.escapeCodeTimeout;
} else {
throw new ERR_INVALID_OPT_VALUE(
'escapeCodeTimeout',
this.escapeCodeTimeout
);
}
}
crlfDelay = input.crlfDelay; crlfDelay = input.crlfDelay;
input = input.input; input = input.input;
} }
@ -131,7 +142,6 @@ function Interface(input, output, completer, terminal) {
this.removeHistoryDuplicates = !!removeHistoryDuplicates; this.removeHistoryDuplicates = !!removeHistoryDuplicates;
this.crlfDelay = crlfDelay ? this.crlfDelay = crlfDelay ?
Math.max(kMincrlfDelay, crlfDelay) : kMincrlfDelay; Math.max(kMincrlfDelay, crlfDelay) : kMincrlfDelay;
// Check arity, 2 - for async, 1 for sync // Check arity, 2 - for async, 1 for sync
if (typeof completer === 'function') { if (typeof completer === 'function') {
this.completer = completer.length === 2 ? this.completer = completer.length === 2 ?
@ -1020,7 +1030,10 @@ function emitKeypressEvents(stream, iface) {
stream[ESCAPE_DECODER].next(r[i]); stream[ESCAPE_DECODER].next(r[i]);
// Escape letter at the tail position // Escape letter at the tail position
if (r[i] === kEscape && i + 1 === r.length) { if (r[i] === kEscape && i + 1 === r.length) {
timeoutId = setTimeout(escapeCodeTimeout, ESCAPE_CODE_TIMEOUT); timeoutId = setTimeout(
escapeCodeTimeout,
iface ? iface.escapeCodeTimeout : ESCAPE_CODE_TIMEOUT
);
} }
} catch (err) { } catch (err) {
// if the generator throws (it could happen in the `keypress` // if the generator throws (it could happen in the `keypress`

View File

@ -0,0 +1,46 @@
'use strict';
const common = require('../common');
// This test ensures that the escapeCodeTimeout option set correctly
const assert = require('assert');
const readline = require('readline');
const EventEmitter = require('events').EventEmitter;
class FakeInput extends EventEmitter {
resume() {}
pause() {}
write() {}
end() {}
}
{
const fi = new FakeInput();
const rli = new readline.Interface({
input: fi,
output: fi,
escapeCodeTimeout: 50
});
assert.strictEqual(rli.escapeCodeTimeout, 50);
rli.close();
}
[
null,
{},
NaN,
'50'
].forEach((invalidInput) => {
common.expectsError(() => {
const fi = new FakeInput();
const rli = new readline.Interface({
input: fi,
output: fi,
escapeCodeTimeout: invalidInput
});
rli.close();
}, {
type: TypeError,
code: 'ERR_INVALID_OPT_VALUE'
});
});