Skip to content

Commit 83119db

Browse files
monkingxueMylesBorins
authored andcommitted
repl: add friendly tips about how to exit repl
Imitate python repl, when the user enters 'exit' or 'quit', no longer prompt 'Reference Error', but prompts 'To exit, press ^D or type .exit'. If the user defines variables named 'exit' or 'quit' , only the value of the variables are output PR-URL: #20617 Fixes: #19021 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]>
1 parent 1ae076b commit 83119db

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

lib/repl.js

+14-4
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,15 @@ function REPLServer(prompt,
215215

216216
function defaultEval(code, context, file, cb) {
217217
var err, result, script, wrappedErr;
218+
var isExitCommand = false;
218219
var wrappedCmd = false;
219220
var awaitPromise = false;
220221
var input = code;
222+
var trimmedCommand = code.trim();
223+
224+
if (trimmedCommand === 'exit' || trimmedCommand === 'quit') {
225+
isExitCommand = true;
226+
}
221227

222228
if (/^\s*\{/.test(code) && /\}\s*$/.test(code)) {
223229
// It's confusing for `{ a : 1 }` to be interpreted as a block
@@ -313,10 +319,16 @@ function REPLServer(prompt,
313319
breakOnSigint: self.breakEvalOnSigint
314320
};
315321

322+
const localContext = self.useGlobal ? global : self.context;
323+
if (isExitCommand && !localContext.hasOwnProperty(trimmedCommand)) {
324+
self.outputStream.write('(To exit, press ^D or type .exit)\n');
325+
return self.displayPrompt();
326+
}
327+
316328
if (self.useGlobal) {
317329
result = script.runInThisContext(scriptOptions);
318330
} else {
319-
result = script.runInContext(context, scriptOptions);
331+
result = script.runInContext(localContext, scriptOptions);
320332
}
321333
} finally {
322334
if (self.breakEvalOnSigint) {
@@ -332,12 +344,10 @@ function REPLServer(prompt,
332344
}
333345
} catch (e) {
334346
err = e;
335-
336347
if (err && err.code === 'ERR_SCRIPT_EXECUTION_INTERRUPTED') {
337-
// The stack trace for this case is not very useful anyway.
348+
// The stack trace for this case is not very useful anyway.
338349
Object.defineProperty(err, 'stack', { value: '' });
339350
}
340-
341351
if (process.domain) {
342352
debug('not recoverable, send to domain');
343353
process.domain.emit('error', err);

test/parallel/test-repl.js

+24
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,29 @@ const strictModeTests = [
132132
}
133133
];
134134

135+
const friendlyExitTests = [
136+
{
137+
send: 'exit',
138+
expect: '(To exit, press ^D or type .exit)'
139+
},
140+
{
141+
send: 'quit',
142+
expect: '(To exit, press ^D or type .exit)'
143+
},
144+
{
145+
send: 'quit = 1',
146+
expect: '1'
147+
},
148+
{
149+
send: 'quit',
150+
expect: '1'
151+
},
152+
{
153+
send: 'exit',
154+
expect: '(To exit, press ^D or type .exit)'
155+
},
156+
];
157+
135158
const errorTests = [
136159
// Uncaught error throws and prints out
137160
{
@@ -742,6 +765,7 @@ const tcpTests = [
742765
const [ socket, replServer ] = await startUnixRepl();
743766

744767
await runReplTests(socket, prompt_unix, unixTests);
768+
await runReplTests(socket, prompt_unix, friendlyExitTests);
745769
await runReplTests(socket, prompt_unix, errorTests);
746770
replServer.replMode = repl.REPL_MODE_STRICT;
747771
await runReplTests(socket, prompt_unix, strictModeTests);

0 commit comments

Comments
 (0)