From dd7a3d246ded89cd0c910231c9adec279e72f9a9 Mon Sep 17 00:00:00 2001 From: Anto Aravinth Date: Thu, 1 Nov 2018 22:16:01 +0530 Subject: [PATCH] lib: repl multiline history support PR-URL: https://github.com/nodejs/node/pull/22153 Reviewed-By: John-David Dalton Reviewed-By: James M Snell --- lib/readline.js | 25 +++++++++++++++++++ lib/repl.js | 2 ++ test/parallel/test-repl-persistent-history.js | 7 ++++++ 3 files changed, 34 insertions(+) diff --git a/lib/readline.js b/lib/readline.js index 4eeefb227ca746..f22d84f1a0df77 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -217,6 +217,7 @@ function Interface(input, output, completer, terminal) { // Current line this.line = ''; + this.multiline = ''; this._setRawMode(true); this.terminal = true; @@ -327,6 +328,7 @@ Interface.prototype._addHistory = function() { if (dupIndex !== -1) this.history.splice(dupIndex, 1); } + this.multiline += this.line; this.history.unshift(this.line); // Only store so many @@ -337,6 +339,29 @@ Interface.prototype._addHistory = function() { return this.history[0]; }; +// Called when a multiline is seen by the repl +Interface.prototype.undoHistory = function() { + if (this.terminal) { + this.history.shift(); + } +}; + +// If it's a multiline code, then add history +// accordingly. +Interface.prototype.multilineHistory = function() { + // check if we got a multiline code + if (this.multiline !== '' && this.terminal) { + const dupIndex = this.history.indexOf(this.multiline); + if (dupIndex !== -1) this.history.splice(dupIndex, 1); + // Remove the last entered line as multiline + // already contains them. + this.history.shift(); + this.history.unshift(this.multiline); + } + + // clear the multiline buffer + this.multiline = ''; +}; Interface.prototype._refreshLine = function() { // line length diff --git a/lib/repl.js b/lib/repl.js index dafbd20d500383..2ecb5abaa4005c 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -779,6 +779,7 @@ exports.start = function(prompt, REPLServer.prototype.clearBufferedCommand = function clearBufferedCommand() { this[kBufferedCommandSymbol] = ''; + REPLServer.super_.prototype.multilineHistory.call(this); }; REPLServer.prototype.close = function close() { @@ -893,6 +894,7 @@ REPLServer.prototype.displayPrompt = function(preserveCursor) { const len = this.lines.level.length ? this.lines.level.length - 1 : 0; const levelInd = '..'.repeat(len); prompt += levelInd + ' '; + REPLServer.super_.prototype.undoHistory.call(this); } // Do not overwrite `_initialPrompt` here diff --git a/test/parallel/test-repl-persistent-history.js b/test/parallel/test-repl-persistent-history.js index bb10085eccfcf6..32bab3c8ed9f83 100644 --- a/test/parallel/test-repl-persistent-history.js +++ b/test/parallel/test-repl-persistent-history.js @@ -111,6 +111,13 @@ const tests = [ test: [UP], expected: [prompt, replFailedRead, prompt, replDisabled, prompt] }, + { // Tests multiline history + env: {}, + test: ['{', '}', UP, CLEAR], + expected: [prompt, '{', '... ', '}', '{}\n', + prompt, `${prompt}{}`, prompt], + clean: false + }, { before: function before() { if (common.isWindows) {