Skip to content

Commit

Permalink
lib: add escapeCodeTimeout as an option to createInterface
Browse files Browse the repository at this point in the history
PR-URL: #19780
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
  • Loading branch information
raoofha authored and targos committed Oct 26, 2018
1 parent 02d83d4 commit 2e91771
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 2 deletions.
5 changes: 5 additions & 0 deletions doc/api/readline.md
Expand Up @@ -375,6 +375,11 @@ changes:
* `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`.
* `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`
instance.
Expand Down
17 changes: 15 additions & 2 deletions lib/readline.js
Expand Up @@ -82,6 +82,7 @@ function Interface(input, output, completer, terminal) {
this.isCompletionEnabled = true;
this._sawKeyPress = false;
this._previousKey = null;
this.escapeCodeTimeout = ESCAPE_CODE_TIMEOUT;

EventEmitter.call(this);
var historySize;
Expand All @@ -99,6 +100,16 @@ function Interface(input, output, completer, terminal) {
if (input.prompt !== undefined) {
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;
input = input.input;
}
Expand Down Expand Up @@ -131,7 +142,6 @@ function Interface(input, output, completer, terminal) {
this.removeHistoryDuplicates = !!removeHistoryDuplicates;
this.crlfDelay = crlfDelay ?
Math.max(kMincrlfDelay, crlfDelay) : kMincrlfDelay;

// Check arity, 2 - for async, 1 for sync
if (typeof completer === 'function') {
this.completer = completer.length === 2 ?
Expand Down Expand Up @@ -1020,7 +1030,10 @@ function emitKeypressEvents(stream, iface) {
stream[ESCAPE_DECODER].next(r[i]);
// Escape letter at the tail position
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) {
// if the generator throws (it could happen in the `keypress`
Expand Down
46 changes: 46 additions & 0 deletions test/parallel/test-readline-interface-escapecodetimeout.js
@@ -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'
});
});

0 comments on commit 2e91771

Please sign in to comment.