Skip to content
Permalink
Browse files
readline: allow completer to rewrite existing input
Sometimes, it makes sense for a completer to change the existing
input, e.g. by adjusting the casing (imagine a completer that
corrects `Number.isNan` to `Number.IsNaN`, for example).

This commit allows that in the readline implemention.

PR-URL: #39178
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
  • Loading branch information
addaleax authored and targos committed Jul 11, 2021
1 parent 63f8702 commit 20cc8ec2af295fd84a014843f06f8421aead261e
Showing with 49 additions and 1 deletion.
  1. +13 −1 lib/readline.js
  2. +36 −0 test/parallel/test-readline-tab-complete.js
@@ -705,9 +705,21 @@ Interface.prototype._tabComplete = function(lastKeypressWasTab) {
// If there is a common prefix to all matches, then apply that portion.
const prefix = commonPrefix(ArrayPrototypeFilter(completions,
(e) => e !== ''));
if (prefix.length > completeOn.length) {
if (StringPrototypeStartsWith(prefix, completeOn) &&
prefix.length > completeOn.length) {
this._insertString(StringPrototypeSlice(prefix, completeOn.length));
return;
} else if (!StringPrototypeStartsWith(completeOn, prefix)) {
this.line = StringPrototypeSlice(this.line,
0,
this.cursor - completeOn.length) +
prefix +
StringPrototypeSlice(this.line,
this.cursor,
this.line.length);
this.cursor = this.cursor - completeOn.length + prefix.length;
this._refreshLine();
return;
}

if (!lastKeypressWasTab) {
@@ -100,3 +100,39 @@ common.skipIfDumbTerminal();
});
rli.close();
}

{
let output = '';
class FakeInput extends EventEmitter {
columns = 80

write = common.mustCall((data) => {
output += data;
}, 9)

resume() {}
pause() {}
end() {}
}

const fi = new FakeInput();
const rli = new readline.Interface({
input: fi,
output: fi,
terminal: true,
completer: common.mustCall((input, cb) => {
cb(null, [[input[0].toUpperCase() + input.slice(1)], input]);
}),
});

rli.on('line', common.mustNotCall());
fi.emit('data', 'input');
queueMicrotask(() => {
fi.emit('data', '\t');
queueMicrotask(() => {
assert.match(output, /> Input/);
output = '';
rli.close();
});
});
}

0 comments on commit 20cc8ec

Please sign in to comment.