Skip to content

Commit

Permalink
repl: copying tabs shouldn't trigger completion
Browse files Browse the repository at this point in the history
PR-URL: #5958
Fixes: #5954
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
  • Loading branch information
ghaiklor authored and evanlucas committed May 17, 2016
1 parent 520369d commit 226b966
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 5 deletions.
4 changes: 3 additions & 1 deletion doc/api/readline.md
Original file line number Diff line number Diff line change
Expand Up @@ -357,10 +357,12 @@ a `'resize'` event on the `output` if/when the columns ever change

Move cursor to the specified position in a given TTY stream.

## readline.emitKeypressEvents(stream)
## readline.emitKeypressEvents(stream[, interface])

Causes `stream` to begin emitting `'keypress'` events corresponding to its
input.
Optionally, `interface` specifies a `readline.Interface` instance for which
autocompletion is disabled when copy-pasted input is detected.

Note that the stream, if it is a TTY, needs to be in raw mode:
```js
Expand Down
15 changes: 12 additions & 3 deletions lib/readline.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function Interface(input, output, completer, terminal) {
}

this._sawReturn = false;
this.isCompletionEnabled = true;

EventEmitter.call(this);
var historySize;
Expand Down Expand Up @@ -130,7 +131,7 @@ function Interface(input, output, completer, terminal) {

} else {

emitKeypressEvents(input);
emitKeypressEvents(input, this);

// input usually refers to stdin
input.on('keypress', onkeypress);
Expand Down Expand Up @@ -883,7 +884,7 @@ Interface.prototype._ttyWrite = function(s, key) {

case 'tab':
// If tab completion enabled, do that...
if (typeof this.completer === 'function') {
if (typeof this.completer === 'function' && this.isCompletionEnabled) {
this._tabComplete();
break;
}
Expand Down Expand Up @@ -917,7 +918,7 @@ exports.Interface = Interface;
const KEYPRESS_DECODER = Symbol('keypress-decoder');
const ESCAPE_DECODER = Symbol('escape-decoder');

function emitKeypressEvents(stream) {
function emitKeypressEvents(stream, iface) {
if (stream[KEYPRESS_DECODER]) return;
var StringDecoder = require('string_decoder').StringDecoder; // lazy load
stream[KEYPRESS_DECODER] = new StringDecoder('utf8');
Expand All @@ -930,6 +931,10 @@ function emitKeypressEvents(stream) {
var r = stream[KEYPRESS_DECODER].write(b);
if (r) {
for (var i = 0; i < r.length; i++) {
if (r[i] === '\t' && typeof r[i + 1] === 'string' && iface) {
iface.isCompletionEnabled = false;
}

try {
stream[ESCAPE_DECODER].next(r[i]);
} catch (err) {
Expand All @@ -938,6 +943,10 @@ function emitKeypressEvents(stream) {
stream[ESCAPE_DECODER] = emitKeys(stream);
stream[ESCAPE_DECODER].next();
throw err;
} finally {
if (iface) {
iface.isCompletionEnabled = true;
}
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion test/parallel/test-readline-interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,9 @@ function isWarned(emitter) {
assert.strictEqual(called, false);
called = true;
});
fi.emit('data', '\tfo\to\t');
for (var character of '\tfo\to\t') {
fi.emit('data', character);
}
fi.emit('data', '\n');
assert.ok(called);
rli.close();
Expand Down

0 comments on commit 226b966

Please sign in to comment.