Skip to content

Commit

Permalink
repl: make REPL support multiline template literals
Browse files Browse the repository at this point in the history
Let REPL enter multiline mode if user's input contains unterminated
template literals.

PR-URL: #333
Reviewed-By: Ben Noordhuis <[email protected]>
  • Loading branch information
ziyunfei authored and bnoordhuis committed Jan 19, 2015
1 parent 2253d30 commit b7365c1
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
27 changes: 21 additions & 6 deletions lib/repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
self.useGlobal = !!useGlobal;
self.ignoreUndefined = !!ignoreUndefined;

self._inTemplateLiteral = false;

// just for backwards compat, see github.com/joyent/node/pull/7127
self.rli = this;

Expand All @@ -102,7 +104,7 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
});
} catch (e) {
debug('parse error %j', code, e);
if (isRecoverableError(e))
if (isRecoverableError(e, self))
err = new Recoverable(e);
else
err = e;
Expand Down Expand Up @@ -226,7 +228,13 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
debug('line %j', cmd);
sawSIGINT = false;
var skipCatchall = false;
cmd = trimWhitespace(cmd);

// leading whitespaces in template literals should not be trimmed.
if (self._inTemplateLiteral) {
self._inTemplateLiteral = false;
} else {
cmd = trimWhitespace(cmd);
}

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

// If the error is that we've unexpectedly ended the input,
// then let the user try to recover by adding more input.
function isRecoverableError(e) {
return e &&
e.name === 'SyntaxError' &&
/^(Unexpected end of input|Unexpected token :)/.test(e.message);
function isRecoverableError(e, self) {
if (e && e.name === 'SyntaxError') {
var message = e.message;
if (message === 'Unterminated template literal' ||
message === 'Missing } in template expression') {
self._inTemplateLiteral = true;
return true;
}
return /^(Unexpected end of input|Unexpected token :)/.test(message);
}
return false;
}

function Recoverable(err) {
Expand Down
11 changes: 11 additions & 0 deletions test/parallel/test-repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ function error_test() {
// But passing the same string to eval() should throw
{ client: client_unix, send: 'eval("function test_func() {")',
expect: /^SyntaxError: Unexpected end of input/ },
// Can handle multiline template literals
{ client: client_unix, send: '`io.js',
expect: prompt_multiline },
// Special REPL commands still available
{ client: client_unix, send: '.break',
expect: prompt_unix },
// Template expressions can cross lines
{ client: client_unix, send: '`io.js ${"1.0"',
expect: prompt_multiline },
{ client: client_unix, send: '+ ".2"}`',
expect: `'io.js 1.0.2'\n${prompt_unix}` },
// Floating point numbers are not interpreted as REPL commands.
{ client: client_unix, send: '.1234',
expect: '0.1234' },
Expand Down

0 comments on commit b7365c1

Please sign in to comment.