summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/api/readline.md5
-rw-r--r--lib/readline.js17
-rw-r--r--test/parallel/test-readline-interface-escapecodetimeout.js46
3 files changed, 66 insertions, 2 deletions
diff --git a/doc/api/readline.md b/doc/api/readline.md
index ccc9ee92fe..3d00e4ec64 100644
--- a/doc/api/readline.md
+++ b/doc/api/readline.md
@@ -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.
diff --git a/lib/readline.js b/lib/readline.js
index cd8240bc26..4eeefb227c 100644
--- a/lib/readline.js
+++ b/lib/readline.js
@@ -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;
@@ -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;
}
@@ -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 ?
@@ -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`
diff --git a/test/parallel/test-readline-interface-escapecodetimeout.js b/test/parallel/test-readline-interface-escapecodetimeout.js
new file mode 100644
index 0000000000..0e25423e85
--- /dev/null
+++ b/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'
+ });
+});