Skip to content

Commit 6eda28c

Browse files
BridgeARtargos
authored andcommitted
repl,readline: refactor common code
This renames some variables for clarity and moves the common substring part into a shared file. One algorithm was more efficient than the other but the functionality itself was identical. PR-URL: #30907 Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Rich Trott <[email protected]>
1 parent 0bafe08 commit 6eda28c

File tree

4 files changed

+39
-47
lines changed

4 files changed

+39
-47
lines changed

lib/internal/readline/utils.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ function CSI(strings, ...args) {
3232
}
3333

3434
CSI.kEscape = kEscape;
35-
CSI.kClearToBeginning = CSI`1K`;
36-
CSI.kClearToEnd = CSI`0K`;
35+
CSI.kClearToLineBeginning = CSI`1K`;
36+
CSI.kClearToLineEnd = CSI`0K`;
3737
CSI.kClearLine = CSI`2K`;
3838
CSI.kClearScreenDown = CSI`0J`;
3939

@@ -446,7 +446,27 @@ function* emitKeys(stream) {
446446
}
447447
}
448448

449+
// This runs in O(n log n).
450+
function commonPrefix(strings) {
451+
if (!strings || strings.length === 0) {
452+
return '';
453+
}
454+
if (strings.length === 1) {
455+
return strings[0];
456+
}
457+
const sorted = strings.slice().sort();
458+
const min = sorted[0];
459+
const max = sorted[sorted.length - 1];
460+
for (let i = 0; i < min.length; i++) {
461+
if (min[i] !== max[i]) {
462+
return min.slice(0, i);
463+
}
464+
}
465+
return min;
466+
}
467+
449468
module.exports = {
469+
commonPrefix,
450470
emitKeys,
451471
getStringWidth,
452472
isFullWidthCodePoint,

lib/readline.js

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const { validateString } = require('internal/validators');
4949
const { inspect } = require('internal/util/inspect');
5050
const EventEmitter = require('events');
5151
const {
52+
commonPrefix,
5253
CSI,
5354
emitKeys,
5455
getStringWidth,
@@ -60,8 +61,8 @@ const {
6061
const { clearTimeout, setTimeout } = require('timers');
6162
const {
6263
kEscape,
63-
kClearToBeginning,
64-
kClearToEnd,
64+
kClearToLineBeginning,
65+
kClearToLineEnd,
6566
kClearLine,
6667
kClearScreenDown
6768
} = CSI;
@@ -568,23 +569,6 @@ function handleGroup(self, group, width, maxColumns) {
568569
self._writeToOutput('\r\n');
569570
}
570571

571-
function commonPrefix(strings) {
572-
if (!strings || strings.length === 0) {
573-
return '';
574-
}
575-
if (strings.length === 1) return strings[0];
576-
const sorted = strings.slice().sort();
577-
const min = sorted[0];
578-
const max = sorted[sorted.length - 1];
579-
for (let i = 0, len = min.length; i < len; i++) {
580-
if (min[i] !== max[i]) {
581-
return min.slice(0, i);
582-
}
583-
}
584-
return min;
585-
}
586-
587-
588572
Interface.prototype._wordLeft = function() {
589573
if (this.cursor > 0) {
590574
// Reverse the string and match a word near beginning
@@ -1270,7 +1254,11 @@ function clearLine(stream, dir, callback) {
12701254
return true;
12711255
}
12721256

1273-
const type = dir < 0 ? kClearToBeginning : dir > 0 ? kClearToEnd : kClearLine;
1257+
const type = dir < 0 ?
1258+
kClearToLineBeginning :
1259+
dir > 0 ?
1260+
kClearToLineEnd :
1261+
kClearLine;
12741262
return stream.write(type, callback);
12751263
}
12761264

lib/repl.js

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ const vm = require('vm');
8484
const path = require('path');
8585
const fs = require('fs');
8686
const { Interface } = require('readline');
87+
const {
88+
commonPrefix
89+
} = require('internal/readline/utils');
8790
const { Console } = require('console');
8891
const cjsLoader = require('internal/modules/cjs/loader');
8992
const { Module: CJSModule } = cjsLoader;
@@ -1401,25 +1404,6 @@ function complete(line, callback) {
14011404
}
14021405
}
14031406

1404-
function longestCommonPrefix(arr = []) {
1405-
const cnt = arr.length;
1406-
if (cnt === 0) return '';
1407-
if (cnt === 1) return arr[0];
1408-
1409-
const first = arr[0];
1410-
// complexity: O(m * n)
1411-
for (let m = 0; m < first.length; m++) {
1412-
const c = first[m];
1413-
for (let n = 1; n < cnt; n++) {
1414-
const entry = arr[n];
1415-
if (m >= entry.length || c !== entry[m]) {
1416-
return first.substring(0, m);
1417-
}
1418-
}
1419-
}
1420-
return first;
1421-
}
1422-
14231407
REPLServer.prototype.completeOnEditorMode = (callback) => (err, results) => {
14241408
if (err) return callback(err);
14251409

@@ -1432,7 +1416,7 @@ REPLServer.prototype.completeOnEditorMode = (callback) => (err, results) => {
14321416
const trimCompleteOnPrefix = (v) => v.substring(prefixLength);
14331417
const data = completions.filter(isNotEmpty).map(trimCompleteOnPrefix);
14341418

1435-
callback(null, [[`${completeOn}${longestCommonPrefix(data)}`], completeOn]);
1419+
callback(null, [[`${completeOn}${commonPrefix(data)}`], completeOn]);
14361420
};
14371421

14381422
REPLServer.prototype.defineCommand = function(keyword, cmd) {

test/parallel/test-readline-csi.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ const { CSI } = require('internal/readline/utils');
99

1010
{
1111
assert(CSI);
12-
assert.strictEqual(CSI.kClearToBeginning, '\x1b[1K');
13-
assert.strictEqual(CSI.kClearToEnd, '\x1b[0K');
12+
assert.strictEqual(CSI.kClearToLineBeginning, '\x1b[1K');
13+
assert.strictEqual(CSI.kClearToLineEnd, '\x1b[0K');
1414
assert.strictEqual(CSI.kClearLine, '\x1b[2K');
1515
assert.strictEqual(CSI.kClearScreenDown, '\x1b[0J');
1616
assert.strictEqual(CSI`1${2}3`, '\x1b[123');
@@ -45,19 +45,19 @@ assert.strictEqual(readline.clearScreenDown(undefined, common.mustCall()),
4545

4646
writable.data = '';
4747
assert.strictEqual(readline.clearLine(writable, -1), true);
48-
assert.deepStrictEqual(writable.data, CSI.kClearToBeginning);
48+
assert.deepStrictEqual(writable.data, CSI.kClearToLineBeginning);
4949

5050
writable.data = '';
5151
assert.strictEqual(readline.clearLine(writable, 1), true);
52-
assert.deepStrictEqual(writable.data, CSI.kClearToEnd);
52+
assert.deepStrictEqual(writable.data, CSI.kClearToLineEnd);
5353

5454
writable.data = '';
5555
assert.strictEqual(readline.clearLine(writable, 0), true);
5656
assert.deepStrictEqual(writable.data, CSI.kClearLine);
5757

5858
writable.data = '';
5959
assert.strictEqual(readline.clearLine(writable, -1, common.mustCall()), true);
60-
assert.deepStrictEqual(writable.data, CSI.kClearToBeginning);
60+
assert.deepStrictEqual(writable.data, CSI.kClearToLineBeginning);
6161

6262
// Verify that clearLine() throws on invalid callback.
6363
assert.throws(() => {

0 commit comments

Comments
 (0)