Permalink
Browse files

fixes #1979: add multiline support to the REPL; press Ctrl-v to activate

  • Loading branch information...
1 parent 8eb04cd commit 58bb6725e4b61d3b3df97e924178eee4915887d0 @michaelficarra michaelficarra committed Jan 3, 2012
Showing with 143 additions and 75 deletions.
  1. +76 −41 lib/coffee-script/repl.js
  2. +67 −34 src/repl.coffee
View

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
View
@@ -4,6 +4,10 @@
#
# coffee> console.log "#{num} bottles of beer" for num in [99..1]
+# Start by opening up `stdin` and `stdout`.
+stdin = process.openStdin()
+stdout = process.stdout
+
# Require the **coffee-script** module to get access to the compiler.
CoffeeScript = require './coffee-script'
readline = require 'readline'
@@ -15,26 +19,80 @@ Module = require 'module'
# Config
REPL_PROMPT = 'coffee> '
+REPL_PROMPT_MULTILINE = '------> '
REPL_PROMPT_CONTINUATION = '......> '
enableColours = no
unless process.platform is 'win32'
enableColours = not process.env.NODE_DISABLE_COLORS
-# Start by opening up `stdin` and `stdout`.
-stdin = process.openStdin()
-stdout = process.stdout
-
# Log an error.
error = (err) ->
stdout.write (err.stack or err.toString()) + '\n'
+# Create the REPL by listening to **stdin**.
+if readline.createInterface.length < 3
+ repl = readline.createInterface stdin, autocomplete
+ stdin.on 'data', (buffer) -> repl.write buffer
+else
+ repl = readline.createInterface stdin, stdout, autocomplete
+
+# Make sure that uncaught exceptions don't kill the REPL.
+process.on 'uncaughtException', error
+
# The current backlog of multi-line code.
backlog = ''
+multilineMode = off
+
+# Handle multi-line mode switch
+repl.input.on 'keypress', (char, key) ->
+ # test for Ctrl-v
+ return unless key and key.ctrl and not key.meta and not key.shift and key.name is 'v'
+ cursorPos = repl.cursor
+ repl.output.cursorTo 0
+ repl.output.clearLine 1
+ multilineMode = not multilineMode
+ backlog = ''
+ repl.setPrompt (newPrompt = if multilineMode then REPL_PROMPT_MULTILINE else REPL_PROMPT)
+ repl.prompt()
+ repl.output.cursorTo newPrompt.length + (repl.cursor = cursorPos)
+
+# Handle Ctrl-d press at end of last line in multiline mode
+repl.input.on 'keypress', (char, key) ->
+ return unless multilineMode and repl.line
+ # test for Ctrl-d
+ return unless key and key.ctrl and not key.meta and not key.shift and key.name is 'd'
+ multilineMode = off
+ repl._line()
+
+repl.on 'attemptClose', ->
+ if multilineMode
+ multilineMode = off
+ repl.output.cursorTo 0
+ repl.output.clearLine 1
+ repl._onLine repl.line
+ return
+ if backlog
+ backlog = ''
+ repl.output.write '\n'
+ repl.setPrompt REPL_PROMPT
+ repl.prompt()
+ else
+ repl.close()
+
+repl.on 'close', ->
+ repl.output.write '\n'
+ repl.input.destroy()
+
# The main REPL function. **run** is called every time a line of code is entered.
# Attempt to evaluate the command. If there's an exception, print it out instead
# of exiting.
-run = (buffer) ->
+repl.on 'line', (buffer) ->
+ if multilineMode
+ backlog += "#{buffer}\n"
+ repl.setPrompt REPL_PROMPT_CONTINUATION
+ repl.prompt()
+ return
if !buffer.toString().trim() and !backlog
repl.prompt()
return
@@ -54,11 +112,14 @@ run = (buffer) ->
}
if returnValue is undefined
global._ = _
- process.stdout.write inspect(returnValue, no, 2, enableColours) + '\n'
+ repl.output.write "#{inspect returnValue, no, 2, enableColours}\n"
catch err
error err
repl.prompt()
+repl.setPrompt REPL_PROMPT
+repl.prompt()
+
## Autocompletion
# Regexes to match complete-able bits of text.
@@ -94,31 +155,3 @@ completeVariable = (text) ->
# Return elements of candidates for which `prefix` is a prefix.
getCompletions = (prefix, candidates) ->
(el for el in candidates when el.indexOf(prefix) is 0)
-
-# Make sure that uncaught exceptions don't kill the REPL.
-process.on 'uncaughtException', error
-
-# Create the REPL by listening to **stdin**.
-if readline.createInterface.length < 3
- repl = readline.createInterface stdin, autocomplete
- stdin.on 'data', (buffer) -> repl.write buffer
-else
- repl = readline.createInterface stdin, stdout, autocomplete
-
-repl.on 'attemptClose', ->
- if backlog
- backlog = ''
- process.stdout.write '\n'
- repl.setPrompt REPL_PROMPT
- repl.prompt()
- else
- repl.close()
-
-repl.on 'close', ->
- process.stdout.write '\n'
- stdin.destroy()
-
-repl.on 'line', run
-
-repl.setPrompt REPL_PROMPT
-repl.prompt()

0 comments on commit 58bb672

Please sign in to comment.