Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
readline: replace quadratic regex with linear one
Simplify regular expression in _wordLeft readline
method.
  • Loading branch information
Hakerh400 committed Mar 19, 2019
commit 0529d790d9cb01b8df0ff0b49a755540bb40562d
10 changes: 8 additions & 2 deletions lib/readline.js
Original file line number Diff line number Diff line change
Expand Up @@ -570,8 +570,11 @@ function commonPrefix(strings) {

Interface.prototype._wordLeft = function() {
if (this.cursor > 0) {
// Reverse the string and match a word near beginning
// to avoid quadratic time complexity
var leading = this.line.slice(0, this.cursor);
var match = leading.match(/(?:[^\w\s]+|\w+|)\s*$/);
Comment thread
BridgeAR marked this conversation as resolved.
Outdated
var reversed = leading.split('').reverse().join('');
var match = reversed.match(/^\s*(?:[^\w\s]+|\w+)?/);
this._moveCursor(-match[0].length);
}
};
Expand Down Expand Up @@ -627,8 +630,11 @@ Interface.prototype._deleteRight = function() {

Interface.prototype._deleteWordLeft = function() {
if (this.cursor > 0) {
// Reverse the string and match a word near beginning
// to avoid quadratic time complexity
var leading = this.line.slice(0, this.cursor);
var match = leading.match(/(?:[^\w\s]+|\w+|)\s*$/);
var reversed = leading.split('').reverse().join('');
var match = reversed.match(/^\s*(?:[^\w\s]+|\w+)?/);
leading = leading.slice(0, leading.length - match[0].length);
this.line = leading + this.line.slice(this.cursor, this.line.length);
this.cursor = leading.length;
Expand Down
23 changes: 23 additions & 0 deletions test/parallel/test-readline-interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -1272,3 +1272,26 @@ const crlfDelay = Infinity;
}), delay);
}
});

// Ensure that the _wordLeft method works even for large input
{
const input = new Readable({
read() {
this.push('\x1B[1;5D'); // CTRL + Left
this.push(null);
},
});
const output = new Writable({
write: common.mustCall((data, encoding, cb) => {
assert.strictEqual(rl.cursor, rl.line.length - 1);
cb();
}),
});
const rl = new readline.createInterface({
input: input,
output: output,
terminal: true,
});
rl.line = `a${' '.repeat(1e6)}a`;
rl.cursor = rl.line.length;
}