vm = require 'vm'
nodeREPL = require 'repl'
CoffeeScript = require './coffee-script'
{merge, prettyErrorMessage} = require './helpers'
replDefaults =
prompt: 'coffee> ',
eval: (input, context, filename, cb) ->vm = require 'vm'
nodeREPL = require 'repl'
CoffeeScript = require './coffee-script'
{merge, prettyErrorMessage} = require './helpers'
replDefaults =
prompt: 'coffee> ',
eval: (input, context, filename, cb) ->XXX: multiline hack.
input = input.replace /\uFF00/g, '\n'Node's REPL sends the input ending with a newline and then wrapped in parens. Unwrap all that.
input = input.replace /^\(([\s\S]*)\n\)$/m, '$1'Require AST nodes to do some AST manipulation.
{Block, Assign, Value, Literal} = require './nodes'TODO: fix #1829: pass in-scope vars and avoid accidentally shadowing them by omitting those declarations
tryGenerate the AST of the clean input.
ast = CoffeeScript.nodes inputAdd assignment to _ variable to force the input to be an expression.
ast = new Block [
new Assign (new Value new Literal '_'), ast, '='
]
js = ast.compile bare: yes
catch err
console.log prettyErrorMessage err, filename, input, yes
cb null, vm.runInContext(js, context, filename)
addMultilineHandler = (repl) ->
{rli, inputStream, outputStream} = repl
multiline =
enabled: off
initialPrompt: repl.prompt.replace(/^[^> ]*/, (x) -> x.replace /./g, '-')
prompt: repl.prompt.replace(/^[^> ]*>?/, (x) -> x.replace /./g, '.')
buffer: ''Proxy node's line listener
nodeLineListener = rli.listeners('line')[0]
rli.removeListener 'line', nodeLineListener
rli.on 'line', (cmd) ->
if multiline.enabled
multiline.buffer += "#{cmd}\n"
rli.setPrompt multiline.prompt
rli.prompt true
else
nodeLineListener cmd
returnHandle Ctrl-v
inputStream.on 'keypress', (char, key) ->
return unless key and key.ctrl and not key.meta and not key.shift and key.name is 'v'
if multiline.enabledallow arbitrarily switching between modes any time before multiple lines are entered
unless multiline.buffer.match /\n/
multiline.enabled = not multiline.enabled
rli.setPrompt repl.prompt
rli.prompt true
returnno-op unless the current line is empty
return if rli.line? and not rli.line.match /^\s*$/eval, print, loop
multiline.enabled = not multiline.enabled
rli.line = ''
rli.cursor = 0
rli.output.cursorTo 0
rli.output.clearLine 1XXX: multiline hack
multiline.buffer = multiline.buffer.replace /\n/g, '\uFF00'
rli.emit 'line', multiline.buffer
multiline.buffer = ''
else
multiline.enabled = not multiline.enabled
rli.setPrompt multiline.initialPrompt
rli.prompt true
return
module.exports =
start: (opts = {}) ->
opts = merge replDefaults, opts
repl = nodeREPL.start opts
repl.on 'exit', -> repl.outputStream.write '\n'
addMultilineHandler repl
repl