diff --git a/lib/internal/readline/utils.js b/lib/internal/readline/utils.js index b867dec0cdb338..ffe0cee9d4ba3d 100644 --- a/lib/internal/readline/utils.js +++ b/lib/internal/readline/utils.js @@ -136,8 +136,7 @@ if (internalBinding('config').hasIntl) { (code >= 0x1b000 && code <= 0x1b001) || // Enclosed Ideographic Supplement (code >= 0x1f200 && code <= 0x1f251) || - // Miscellaneous Symbols and Pictographs 0x1f300 - 0x1f5ff - // Emoticons 0x1f600 - 0x1f64f + // Miscellaneous Symbols and Pictographs .. Emoticons (code >= 0x1f300 && code <= 0x1f64f) || // CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane (code >= 0x20000 && code <= 0x3fffd) @@ -459,9 +458,6 @@ function* emitKeys(stream) { // This runs in O(n log n). function commonPrefix(strings) { - if (!strings || strings.length === 0) { - return ''; - } if (strings.length === 1) { return strings[0]; } diff --git a/lib/internal/repl/utils.js b/lib/internal/repl/utils.js index 20904d9d6a2445..826a3364c82ca4 100644 --- a/lib/internal/repl/utils.js +++ b/lib/internal/repl/utils.js @@ -320,10 +320,8 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { // Enter should automatically add the suffix to the current line as long as // escape was not pressed. We might even remove the preview in case any // cursor movement is triggered. - if (typeof repl.completer === 'function') { - const insertPreview = false; - showCompletionPreview(repl.line, insertPreview); - } + const insertPreview = false; + showCompletionPreview(repl.line, insertPreview); // Do not preview if the command is buffered. if (repl[bufferSymbol]) { diff --git a/lib/readline.js b/lib/readline.js index 697c397b1e2b6b..9a8b83834ddc50 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -735,27 +735,13 @@ Interface.prototype._getDisplayPos = function(str) { return { cols, rows }; }; - // Returns current cursor's position and line Interface.prototype.getCursorPos = function() { - const columns = this.columns; const strBeforeCursor = this._prompt + this.line.substring(0, this.cursor); - const dispPos = this._getDisplayPos(strBeforeCursor); - let cols = dispPos.cols; - let rows = dispPos.rows; - // If the cursor is on a full-width character which steps over the line, - // move the cursor to the beginning of the next line. - if (cols + 1 === columns && - this.cursor < this.line.length && - getStringWidth(this.line[this.cursor]) > 1) { - rows++; - cols = 0; - } - return { cols, rows }; + return this._getDisplayPos(strBeforeCursor); }; Interface.prototype._getCursorPos = Interface.prototype.getCursorPos; - // This function moves cursor dx places to the right // (-dx for left) and refreshes the line if it is needed. Interface.prototype._moveCursor = function(dx) { @@ -1119,31 +1105,32 @@ function emitKeypressEvents(stream, iface = {}) { stream[ESCAPE_DECODER] = emitKeys(stream); stream[ESCAPE_DECODER].next(); - const escapeCodeTimeout = () => stream[ESCAPE_DECODER].next(''); + const triggerEscape = () => stream[ESCAPE_DECODER].next(''); + const { escapeCodeTimeout = ESCAPE_CODE_TIMEOUT } = iface; let timeoutId; - function onData(b) { + function onData(input) { if (stream.listenerCount('keypress') > 0) { - const string = stream[KEYPRESS_DECODER].write(b); + const string = stream[KEYPRESS_DECODER].write(input); if (string) { clearTimeout(timeoutId); // This supports characters of length 2. iface._sawKeyPress = charLengthAt(string, 0) === string.length; - const escapeTimeout = iface.escapeCodeTimeout || ESCAPE_CODE_TIMEOUT; + iface.isCompletionEnabled = false; let length = 0; for (const character of string) { length += character.length; - if (character === '\t' && length !== string.length) { - iface.isCompletionEnabled = false; + if (length === string.length) { + iface.isCompletionEnabled = true; } try { stream[ESCAPE_DECODER].next(character); // Escape letter at the tail position - if (character === kEscape && length === string.length) { - timeoutId = setTimeout(escapeCodeTimeout, escapeTimeout); + if (length === string.length && character === kEscape) { + timeoutId = setTimeout(triggerEscape, escapeCodeTimeout); } } catch (err) { // If the generator throws (it could happen in the `keypress` @@ -1151,10 +1138,6 @@ function emitKeypressEvents(stream, iface = {}) { stream[ESCAPE_DECODER] = emitKeys(stream); stream[ESCAPE_DECODER].next(); throw err; - } finally { - if (iface) { - iface.isCompletionEnabled = true; - } } } } diff --git a/lib/repl.js b/lib/repl.js index 001af666d991be..c44d27fd1aec2b 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -1364,15 +1364,13 @@ REPLServer.prototype.completeOnEditorMode = (callback) => (err, results) => { if (err) return callback(err); const [completions, completeOn = ''] = results; - const prefixLength = completeOn.length; + let result = completions.filter((v) => v); - if (prefixLength === 0) return callback(null, [[], completeOn]); - - const isNotEmpty = (v) => v.length > 0; - const trimCompleteOnPrefix = (v) => v.substring(prefixLength); - const data = completions.filter(isNotEmpty).map(trimCompleteOnPrefix); + if (completeOn && result.length !== 0) { + result = [commonPrefix(result)]; + } - callback(null, [[`${completeOn}${commonPrefix(data)}`], completeOn]); + callback(null, [result, completeOn]); }; REPLServer.prototype.defineCommand = function(keyword, cmd) {