diff options
author | Andy Hayden <andyhayden1@gmail.com> | 2018-11-06 11:19:16 -0800 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2018-11-06 11:19:16 -0800 |
commit | e9327be8318188db0983963e801effe8833e36e3 (patch) | |
tree | 3eeed42a572905988da910882536b7738213cd38 /js | |
parent | 13e1eb2b87c146a8594e7e6f24ba738bff116246 (diff) |
Support repl multiline input (#1165)
Diffstat (limited to 'js')
-rw-r--r-- | js/repl.ts | 75 |
1 files changed, 57 insertions, 18 deletions
diff --git a/js/repl.ts b/js/repl.ts index b7c516110..3139330f6 100644 --- a/js/repl.ts +++ b/js/repl.ts @@ -51,15 +51,12 @@ export function replLoop(): void { window.deno = deno; // FIXME use a new scope (rather than window). const historyFile = "deno_history.txt"; - const prompt = "> "; - const rid = startRepl(historyFile); - let line = ""; + let code = ""; while (true) { try { - line = readline(rid, prompt); - line = line.trim(); + code = readBlock(rid, "> ", " "); } catch (err) { if (err.message === "EOF") { break; @@ -67,23 +64,65 @@ export function replLoop(): void { console.error(err); exit(1); } - if (!line) { + if (!code) { continue; - } - if (line === ".exit") { + } else if (code.trim() === ".exit") { break; } - try { - const result = eval.call(window, line); // FIXME use a new scope. - console.log(result); - } catch (err) { - if (err instanceof Error) { - console.error(`${err.constructor.name}: ${err.message}`); - } else { - console.error("Thrown:", err); - } - } + + evaluate(code); } close(rid); } + +function evaluate(code: string): void { + try { + const result = eval.call(window, code); // FIXME use a new scope. + console.log(result); + } catch (err) { + if (err instanceof Error) { + console.error(`${err.constructor.name}: ${err.message}`); + } else { + console.error("Thrown:", err); + } + } +} + +function readBlock( + rid: number, + prompt: string, + continuedPrompt: string +): string { + let code = ""; + do { + code += readline(rid, prompt); + prompt = continuedPrompt; + } while (parenthesesAreOpen(code)); + return code; +} + +// modified from +// https://codereview.stackexchange.com/a/46039/148556 +function parenthesesAreOpen(code: string): boolean { + const parentheses = "[]{}()"; + const stack = []; + + for (const ch of code) { + const bracePosition = parentheses.indexOf(ch); + + if (bracePosition === -1) { + // not a paren + continue; + } + + if (bracePosition % 2 === 0) { + stack.push(bracePosition + 1); // push next expected brace position + } else { + if (stack.length === 0 || stack.pop() !== bracePosition) { + return false; + } + } + } + return stack.length > 0; +} |