Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRuben Bridgewater <ruben@bridgewater.de>2019-12-11 21:26:47 +0300
committerRuben Bridgewater <ruben@bridgewater.de>2019-12-15 18:24:00 +0300
commit6c542d1c26decd53fa1154a5aa7a53b4199cad1f (patch)
tree51ec6e939011bdfe7191749bf403bf03909e6797 /lib
parentaf5c8af5e9d02532d6a59e2a2544c1ea0c4877f7 (diff)
repl: improve completion
This improves the completion output by removing the nested special handling. It never fully worked as expected and required a lot of hacks to even keep it working halfway reliable. Our tests did not cover syntax errors though and those can not be handled by this implementation. Those break the layout and confuse the REPL. Besides that the completion now also works in case the current line has leading whitespace. Also improve the error output in case the completion fails. PR-URL: https://github.com/nodejs/node/pull/30907 Reviewed-By: Michaƫl Zasso <targos@protonmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/readline.js2
-rw-r--r--lib/repl.js70
2 files changed, 12 insertions, 60 deletions
diff --git a/lib/readline.js b/lib/readline.js
index 0ba30cc04b1..d471d512f48 100644
--- a/lib/readline.js
+++ b/lib/readline.js
@@ -501,7 +501,7 @@ Interface.prototype._tabComplete = function(lastKeypressWasTab) {
self.resume();
if (err) {
- self._writeToOutput(`tab completion error ${inspect(err)}`);
+ self._writeToOutput(`Tab completion error: ${inspect(err)}`);
return;
}
diff --git a/lib/repl.js b/lib/repl.js
index 4f32c9c28ce..cd8240dd743 100644
--- a/lib/repl.js
+++ b/lib/repl.js
@@ -71,7 +71,6 @@ const {
deprecate
} = require('internal/util');
const { inspect } = require('internal/util/inspect');
-const Stream = require('stream');
const vm = require('vm');
const path = require('path');
const fs = require('fs');
@@ -115,7 +114,6 @@ const {
} = internalBinding('contextify');
const history = require('internal/repl/history');
-const { setImmediate } = require('timers');
// Lazy-loaded.
let processTopLevelAwait;
@@ -124,7 +122,6 @@ const globalBuiltins =
new Set(vm.runInNewContext('Object.getOwnPropertyNames(globalThis)'));
const parentModule = module;
-const replMap = new WeakMap();
const domainSet = new WeakSet();
const kBufferedCommandSymbol = Symbol('bufferedCommand');
@@ -550,14 +547,13 @@ function REPLServer(prompt,
self.lastError = e;
}
- const top = replMap.get(self);
if (options[kStandaloneREPL] &&
process.listenerCount('uncaughtException') !== 0) {
process.nextTick(() => {
process.emit('uncaughtException', e);
- top.clearBufferedCommand();
- top.lines.level = [];
- top.displayPrompt();
+ self.clearBufferedCommand();
+ self.lines.level = [];
+ self.displayPrompt();
});
} else {
if (errStack === '') {
@@ -583,10 +579,10 @@ function REPLServer(prompt,
}
// Normalize line endings.
errStack += errStack.endsWith('\n') ? '' : '\n';
- top.outputStream.write(errStack);
- top.clearBufferedCommand();
- top.lines.level = [];
- top.displayPrompt();
+ self.outputStream.write(errStack);
+ self.clearBufferedCommand();
+ self.lines.level = [];
+ self.displayPrompt();
}
});
@@ -897,7 +893,6 @@ exports.start = function(prompt,
ignoreUndefined,
replMode);
if (!exports.repl) exports.repl = repl;
- replMap.set(repl, repl);
return repl;
};
@@ -1034,23 +1029,6 @@ REPLServer.prototype.turnOffEditorMode = deprecate(
'REPLServer.turnOffEditorMode() is deprecated',
'DEP0078');
-// A stream to push an array into a REPL
-// used in REPLServer.complete
-function ArrayStream() {
- Stream.call(this);
-
- this.run = function(data) {
- for (let n = 0; n < data.length; n++)
- this.emit('data', `${data[n]}\n`);
- };
-}
-ObjectSetPrototypeOf(ArrayStream.prototype, Stream.prototype);
-ObjectSetPrototypeOf(ArrayStream, Stream);
-ArrayStream.prototype.readable = true;
-ArrayStream.prototype.writable = true;
-ArrayStream.prototype.resume = function() {};
-ArrayStream.prototype.write = function() {};
-
const requireRE = /\brequire\s*\(['"](([\w@./-]+\/)?(?:[\w@./-]*))/;
const fsAutoCompleteRE = /fs(?:\.promises)?\.\s*[a-z][a-zA-Z]+\(\s*["'](.*)/;
const simpleExpressionRE =
@@ -1110,38 +1088,13 @@ REPLServer.prototype.complete = function() {
// Warning: This eval's code like "foo.bar.baz", so it will run property
// getter code.
function complete(line, callback) {
- // There may be local variables to evaluate, try a nested REPL
- if (this[kBufferedCommandSymbol] !== undefined &&
- this[kBufferedCommandSymbol].length) {
- // Get a new array of inputted lines
- const tmp = this.lines.slice();
- // Kill off all function declarations to push all local variables into
- // global scope
- for (let n = 0; n < this.lines.level.length; n++) {
- const kill = this.lines.level[n];
- if (kill.isFunction)
- tmp[kill.line] = '';
- }
- const flat = new ArrayStream(); // Make a new "input" stream.
- const magic = new REPLServer('', flat); // Make a nested REPL.
- replMap.set(magic, replMap.get(this));
- flat.run(tmp); // `eval` the flattened code.
- // All this is only profitable if the nested REPL does not have a
- // bufferedCommand.
- if (!magic[kBufferedCommandSymbol]) {
- magic._domain.on('error', (err) => {
- setImmediate(() => {
- throw err;
- });
- });
- return magic.complete(line, callback);
- }
- }
-
// List of completion lists, one for each inheritance "level"
let completionGroups = [];
let completeOn, group;
+ // Ignore right whitespace. It could change the outcome.
+ line = line.trimLeft();
+
// REPL commands (e.g. ".break").
let filter;
let match = line.match(/^\s*\.(\w*)$/);
@@ -1465,8 +1418,7 @@ function _memory(cmd) {
// scope will not work for this function.
self.lines.level.push({
line: self.lines.length - 1,
- depth: depth,
- isFunction: /\bfunction\b/.test(cmd)
+ depth: depth
});
} else if (depth < 0) {
// Going... up.