Skip to content

Commit b7365c1

Browse files
ziyunfeibnoordhuis
authored andcommitted
repl: make REPL support multiline template literals
Let REPL enter multiline mode if user's input contains unterminated template literals. PR-URL: #333 Reviewed-By: Ben Noordhuis <[email protected]>
1 parent 2253d30 commit b7365c1

File tree

2 files changed

+32
-6
lines changed

2 files changed

+32
-6
lines changed

lib/repl.js

+21-6
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
8787
self.useGlobal = !!useGlobal;
8888
self.ignoreUndefined = !!ignoreUndefined;
8989

90+
self._inTemplateLiteral = false;
91+
9092
// just for backwards compat, see github.com/joyent/node/pull/7127
9193
self.rli = this;
9294

@@ -102,7 +104,7 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
102104
});
103105
} catch (e) {
104106
debug('parse error %j', code, e);
105-
if (isRecoverableError(e))
107+
if (isRecoverableError(e, self))
106108
err = new Recoverable(e);
107109
else
108110
err = e;
@@ -226,7 +228,13 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
226228
debug('line %j', cmd);
227229
sawSIGINT = false;
228230
var skipCatchall = false;
229-
cmd = trimWhitespace(cmd);
231+
232+
// leading whitespaces in template literals should not be trimmed.
233+
if (self._inTemplateLiteral) {
234+
self._inTemplateLiteral = false;
235+
} else {
236+
cmd = trimWhitespace(cmd);
237+
}
230238

231239
// Check to see if a REPL keyword was used. If it returns true,
232240
// display next prompt and return.
@@ -928,10 +936,17 @@ REPLServer.prototype.convertToContext = function(cmd) {
928936

929937
// If the error is that we've unexpectedly ended the input,
930938
// then let the user try to recover by adding more input.
931-
function isRecoverableError(e) {
932-
return e &&
933-
e.name === 'SyntaxError' &&
934-
/^(Unexpected end of input|Unexpected token :)/.test(e.message);
939+
function isRecoverableError(e, self) {
940+
if (e && e.name === 'SyntaxError') {
941+
var message = e.message;
942+
if (message === 'Unterminated template literal' ||
943+
message === 'Missing } in template expression') {
944+
self._inTemplateLiteral = true;
945+
return true;
946+
}
947+
return /^(Unexpected end of input|Unexpected token :)/.test(message);
948+
}
949+
return false;
935950
}
936951

937952
function Recoverable(err) {

test/parallel/test-repl.js

+11
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,17 @@ function error_test() {
104104
// But passing the same string to eval() should throw
105105
{ client: client_unix, send: 'eval("function test_func() {")',
106106
expect: /^SyntaxError: Unexpected end of input/ },
107+
// Can handle multiline template literals
108+
{ client: client_unix, send: '`io.js',
109+
expect: prompt_multiline },
110+
// Special REPL commands still available
111+
{ client: client_unix, send: '.break',
112+
expect: prompt_unix },
113+
// Template expressions can cross lines
114+
{ client: client_unix, send: '`io.js ${"1.0"',
115+
expect: prompt_multiline },
116+
{ client: client_unix, send: '+ ".2"}`',
117+
expect: `'io.js 1.0.2'\n${prompt_unix}` },
107118
// Floating point numbers are not interpreted as REPL commands.
108119
{ client: client_unix, send: '.1234',
109120
expect: '0.1234' },

0 commit comments

Comments
 (0)