Skip to content

Commit 429e046

Browse files
committed
repl: REPL enhancements
* Welcome message with version and help guide * `displayWelcomeMessage` flag is used to turn on/off * Differentiate execute & continue actions * ^M or enter key to execute the command * ^J to continue building multiline expression. * `executeOnTimeout` value is used to determine the end of expression when `terminal` is false. * Pretty stack trace. * REPL specific stack frames are removed before emitting to output stream. * Recoverable errors. * No more recoverable errors & no false positives. * Defined commands(like .exit, .load) are meaningful only at the top level. * Remove `.break` command and `.clear`when `useGlobal` is false. Welcome message template ------------------------ ```js $ node Welcome to Node.js <<version>> (<<vm name>> VM, <<vm version>>) Type ^M or enter to execute, ^J to continue, ^C to exit Or try ``` Pretty stack trace ------------------ ```js $ node -i > throw new Error('tiny stack') Error: tiny stack at repl:1:7 > var x y; var x y; ^ SyntaxError: Unexpected identifier > ```
1 parent 24c9e46 commit 429e046

31 files changed

+819
-657
lines changed

doc/api/repl.md

Lines changed: 27 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,7 @@ customizable evaluation functions.
2727

2828
The following special commands are supported by all REPL instances:
2929

30-
* `.break` - When in the process of inputting a multi-line expression, entering
31-
the `.break` command (or pressing the `<ctrl>-C` key combination) will abort
32-
further input or processing of that expression.
33-
* `.clear` - Resets the REPL `context` to an empty object and clears any
34-
multi-line expression currently being input.
30+
* `.clear` - Resets the local REPL `context` to an empty object.
3531
* `.exit` - Close the I/O stream, causing the REPL to exit.
3632
* `.help` - Show this list of special commands.
3733
* `.save` - Save the current REPL session to a file:
@@ -56,7 +52,7 @@ welcome('Node.js User');
5652

5753
The following key combinations in the REPL have these special effects:
5854

59-
* `<ctrl>-C` - When pressed once, has the same effect as the `.break` command.
55+
* `<ctrl>-C` - When pressed once, it will break the current command.
6056
When pressed twice on a blank line, has the same effect as the `.exit`
6157
command.
6258
* `<ctrl>-D` - Has the same effect as the `.exit` command.
@@ -174,34 +170,6 @@ function myEval(cmd, context, filename, callback) {
174170
repl.start({prompt: '> ', eval: myEval});
175171
```
176172

177-
#### Recoverable Errors
178-
179-
As a user is typing input into the REPL prompt, pressing the `<enter>` key will
180-
send the current line of input to the `eval` function. In order to support
181-
multi-line input, the eval function can return an instance of `repl.Recoverable`
182-
to the provided callback function:
183-
184-
```js
185-
function eval(cmd, context, filename, callback) {
186-
var result;
187-
try {
188-
result = vm.runInThisContext(cmd);
189-
} catch (e) {
190-
if (isRecoverableError(e)) {
191-
return callback(new repl.Recoverable(e));
192-
}
193-
}
194-
callback(null, result);
195-
}
196-
197-
function isRecoverableError(error) {
198-
if (error.name === 'SyntaxError') {
199-
return /^(Unexpected end of input|Unexpected token)/.test(error.message);
200-
}
201-
return false;
202-
}
203-
```
204-
205173
### Customizing REPL Output
206174

207175
By default, `repl.REPLServer` instances format output using the
@@ -286,15 +254,15 @@ reset to its initial value using the `.clear` command:
286254

287255
```js
288256
$ ./node example.js
289-
>m
257+
> m
290258
'test'
291-
>m = 1
259+
> m = 1
292260
1
293-
>m
261+
> m
294262
1
295-
>.clear
263+
> .clear
296264
Clearing context...
297-
>m
265+
> m
298266
'test'
299267
>
300268
```
@@ -408,6 +376,18 @@ added: v0.1.91
408376
* `breakEvalOnSigint` - Stop evaluating the current piece of code when
409377
`SIGINT` is received, i.e. `Ctrl+C` is pressed. This cannot be used together
410378
with a custom `eval` function. Defaults to `false`.
379+
* `executeOnTimeout` {number} If `terminal` is false,`executeOnTimeout`
380+
delay is used to determine the end of expression. Defaults to 50ms.
381+
`executeOnTimeout` will be coerced to `[100, 2000]` range.
382+
* `displayWelcomeMessage` {boolean} If `true`, welcome message will be
383+
displayed. Defaults to `false`.
384+
```js
385+
> node
386+
Welcome to Node.js <<version>> (<<vm name>> VM, <<vm version>>)
387+
Type ^M or enter to execute, ^J to continue, ^C to exit
388+
Or try .help for help, more at https://nodejs.org/dist/<<version>>/docs/api/repl.html
389+
>
390+
```
411391

412392
The `repl.start()` method creates and starts a `repl.REPLServer` instance.
413393

@@ -419,11 +399,15 @@ without passing any arguments (or by passing the `-i` argument):
419399

420400
```js
421401
$ node
422-
> a = [1, 2, 3];
402+
Welcome to Node.js v6.5.0 (v8 VM, 5.1.281.81)
403+
Type ^M or enter to execute, ^J to continue, ^C to exit
404+
Or try .help for help, more at https://nodejs.org/dist/v6.5.0/docs/api/repl.html
405+
406+
> a = [1, 2, 3]; // ^M or ⏎
423407
[ 1, 2, 3 ]
424-
> a.forEach((v) => {
425-
... console.log(v);
426-
... });
408+
> a.forEach((v) => { // ^J to continue
409+
console.log(v);
410+
});
427411
1
428412
2
429413
3

lib/_debugger.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -740,7 +740,8 @@ function Interface(stdin, stdout, args) {
740740
output: this.stdout,
741741
eval: (code, ctx, file, cb) => this.controlEval(code, ctx, file, cb),
742742
useGlobal: false,
743-
ignoreUndefined: true
743+
ignoreUndefined: true,
744+
displayWelcomeMessage: false,
744745
};
745746
if (parseInt(process.env['NODE_NO_READLINE'], 10)) {
746747
opts.terminal = false;

lib/internal/repl.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ function createRepl(env, opts, cb) {
2424
ignoreUndefined: false,
2525
terminal: process.stdout.isTTY,
2626
useGlobal: true,
27-
breakEvalOnSigint: true
27+
breakEvalOnSigint: true,
28+
displayWelcomeMessage: process.execArgv.indexOf('-i') === -1,
2829
}, opts);
2930

3031
if (parseInt(env.NODE_NO_READLINE)) {

lib/readline.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ function emitKeypressEvents(stream, iface) {
969969
clearTimeout(timeoutId);
970970

971971
if (iface) {
972-
iface._sawKeyPress = r.length === 1;
972+
iface._sawKeyPress = r.length === 1 || (r[0] === '\x1b');
973973
}
974974

975975
for (var i = 0; i < r.length; i++) {

0 commit comments

Comments
 (0)