UNPKG

2.43 kBtext/coffeescriptView Raw
1vm = require 'vm'
2nodeREPL = require 'repl'
3CoffeeScript = require './module'
4{merge} = require './helpers'
5
6addMultilineHandler = (repl) ->
7 {rli, inputStream, outputStream} = repl
8 initialPrompt = repl.prompt.replace /^[^> ]*/, (x) -> x.replace /./g, '-'
9 continuationPrompt = repl.prompt.replace /^[^> ]*>?/, (x) -> x.replace /./g, '.'
10
11 enabled = no
12 buffer = ''
13
14 # Proxy node's line listener
15 nodeLineListener = (rli.listeners 'line')[0]
16 rli.removeListener 'line', nodeLineListener
17 rli.on 'line', (cmd) ->
18 if enabled
19 buffer += "#{cmd}\n"
20 rli.setPrompt continuationPrompt
21 rli.prompt true
22 else
23 nodeLineListener cmd
24 return
25
26 # Handle Ctrl-v
27 inputStream.on 'keypress', (char, key) ->
28 return unless key and key.ctrl and not key.meta and not key.shift and key.name is 'v'
29 if enabled
30 # allow arbitrarily switching between modes any time before multiple lines are entered
31 unless buffer.match /\n/
32 enabled = not enabled
33 rli.setPrompt repl.prompt
34 rli.prompt true
35 return
36 # no-op unless the current line is empty
37 return if rli.line? and not rli.line.match /^\s*$/
38 # eval, print, loop
39 enabled = not enabled
40 rli.line = ''
41 rli.cursor = 0
42 rli.output.cursorTo 0
43 rli.output.clearLine 1
44 # XXX: multiline hack
45 buffer = buffer.replace /\n/g, '\uFF00'
46 rli.emit 'line', buffer
47 buffer = ''
48 else
49 enabled = not enabled
50 rli.setPrompt initialPrompt
51 rli.prompt true
52 return
53
54module.exports =
55 start: (opts = {}) ->
56 # REPL defaults
57 opts.prompt or= 'coffee> '
58 opts.eval or= (input, context, filename, cb) ->
59 # XXX: multiline hack
60 input = input.replace /\uFF00/g, '\n'
61 # strip single-line comments
62 input = input.replace /(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/, '$1$2$3'
63 # empty command
64 return cb null if /^(\s*|\(\s*\))$/.test input
65 # TODO: fix #1829: pass in-scope vars and avoid accidentally shadowing them by omitting those declarations
66 try
67 js = CoffeeScript.cs2js "_=(#{input}\n)", {filename, bare: yes}
68 cb null, vm.runInContext js, context, filename
69 catch err
70 cb "\x1B[0;31m#{err.constructor.name}: #{err.message}\x1B[0m"
71
72 repl = nodeREPL.start opts
73 repl.on 'exit', -> repl.outputStream.write '\n'
74 addMultilineHandler repl
75 repl