Skip to content

Commit 1c5ffb3

Browse files
raoofhatargos
authored andcommitted
lib: add escapeCodeTimeout as an option to createInterface
PR-URL: #19780 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
1 parent ce106df commit 1c5ffb3

File tree

3 files changed

+66
-2
lines changed

3 files changed

+66
-2
lines changed

doc/api/readline.md

+5
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,11 @@ changes:
375375
* `removeHistoryDuplicates` {boolean} If `true`, when a new input line added
376376
to the history list duplicates an older one, this removes the older line
377377
from the list. **Default:** `false`.
378+
* `escapeCodeTimeout` {number} The duration `readline` will wait for a
379+
character (when reading an ambiguous key sequence in milliseconds one that
380+
can both form a complete key sequence using the input read so far and can
381+
take additional input to complete a longer key sequence).
382+
**Default:** `500`.
378383

379384
The `readline.createInterface()` method creates a new `readline.Interface`
380385
instance.

lib/readline.js

+15-2
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ function Interface(input, output, completer, terminal) {
8282
this.isCompletionEnabled = true;
8383
this._sawKeyPress = false;
8484
this._previousKey = null;
85+
this.escapeCodeTimeout = ESCAPE_CODE_TIMEOUT;
8586

8687
EventEmitter.call(this);
8788
var historySize;
@@ -99,6 +100,16 @@ function Interface(input, output, completer, terminal) {
99100
if (input.prompt !== undefined) {
100101
prompt = input.prompt;
101102
}
103+
if (input.escapeCodeTimeout !== undefined) {
104+
if (Number.isFinite(input.escapeCodeTimeout)) {
105+
this.escapeCodeTimeout = input.escapeCodeTimeout;
106+
} else {
107+
throw new ERR_INVALID_OPT_VALUE(
108+
'escapeCodeTimeout',
109+
this.escapeCodeTimeout
110+
);
111+
}
112+
}
102113
crlfDelay = input.crlfDelay;
103114
input = input.input;
104115
}
@@ -131,7 +142,6 @@ function Interface(input, output, completer, terminal) {
131142
this.removeHistoryDuplicates = !!removeHistoryDuplicates;
132143
this.crlfDelay = crlfDelay ?
133144
Math.max(kMincrlfDelay, crlfDelay) : kMincrlfDelay;
134-
135145
// Check arity, 2 - for async, 1 for sync
136146
if (typeof completer === 'function') {
137147
this.completer = completer.length === 2 ?
@@ -1020,7 +1030,10 @@ function emitKeypressEvents(stream, iface) {
10201030
stream[ESCAPE_DECODER].next(r[i]);
10211031
// Escape letter at the tail position
10221032
if (r[i] === kEscape && i + 1 === r.length) {
1023-
timeoutId = setTimeout(escapeCodeTimeout, ESCAPE_CODE_TIMEOUT);
1033+
timeoutId = setTimeout(
1034+
escapeCodeTimeout,
1035+
iface ? iface.escapeCodeTimeout : ESCAPE_CODE_TIMEOUT
1036+
);
10241037
}
10251038
} catch (err) {
10261039
// if the generator throws (it could happen in the `keypress`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
const common = require('../common');
3+
4+
// This test ensures that the escapeCodeTimeout option set correctly
5+
6+
const assert = require('assert');
7+
const readline = require('readline');
8+
const EventEmitter = require('events').EventEmitter;
9+
10+
class FakeInput extends EventEmitter {
11+
resume() {}
12+
pause() {}
13+
write() {}
14+
end() {}
15+
}
16+
17+
{
18+
const fi = new FakeInput();
19+
const rli = new readline.Interface({
20+
input: fi,
21+
output: fi,
22+
escapeCodeTimeout: 50
23+
});
24+
assert.strictEqual(rli.escapeCodeTimeout, 50);
25+
rli.close();
26+
}
27+
28+
[
29+
null,
30+
{},
31+
NaN,
32+
'50'
33+
].forEach((invalidInput) => {
34+
common.expectsError(() => {
35+
const fi = new FakeInput();
36+
const rli = new readline.Interface({
37+
input: fi,
38+
output: fi,
39+
escapeCodeTimeout: invalidInput
40+
});
41+
rli.close();
42+
}, {
43+
type: TypeError,
44+
code: 'ERR_INVALID_OPT_VALUE'
45+
});
46+
});

0 commit comments

Comments
 (0)