/usr/lib/coffee-script/src/repl.coffee is in coffeescript 1.4.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | # A very simple Read-Eval-Print-Loop. Compiles one line at a time to JavaScript
# and evaluates it. Good for simple tests, or poking around the **Node.js** API.
# Using it looks like this:
#
# 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'
{inspect} = require 'util'
{Script} = require 'vm'
Module = require 'module'
# REPL Setup
# Config
REPL_PROMPT = 'coffee> '
REPL_PROMPT_MULTILINE = '------> '
REPL_PROMPT_CONTINUATION = '......> '
enableColours = no
unless process.platform is 'win32'
enableColours = not process.env.NODE_DISABLE_COLORS
# Log an error.
error = (err) ->
stdout.write (err.stack or err.toString()) + '\n'
## Autocompletion
# Regexes to match complete-able bits of text.
ACCESSOR = /\s*([\w\.]+)(?:\.(\w*))$/
SIMPLEVAR = /(\w+)$/i
# Returns a list of completions, and the completed text.
autocomplete = (text) ->
completeAttribute(text) or completeVariable(text) or [[], text]
# Attempt to autocomplete a chained dotted attribute: `one.two.three`.
completeAttribute = (text) ->
if match = text.match ACCESSOR
[all, obj, prefix] = match
try obj = Script.runInThisContext obj
catch e
return
return unless obj?
obj = Object obj
candidates = Object.getOwnPropertyNames obj
while obj = Object.getPrototypeOf obj
for key in Object.getOwnPropertyNames obj when key not in candidates
candidates.push key
completions = getCompletions prefix, candidates
[completions, prefix]
# Attempt to autocomplete an in-scope free variable: `one`.
completeVariable = (text) ->
free = text.match(SIMPLEVAR)?[1]
free = "" if text is ""
if free?
vars = Script.runInThisContext 'Object.getOwnPropertyNames(Object(this))'
keywords = (r for r in CoffeeScript.RESERVED when r[..1] isnt '__')
candidates = vars
for key in keywords when key not in candidates
candidates.push key
completions = getCompletions free, candidates
[completions, free]
# Return elements of candidates for which `prefix` is a prefix.
getCompletions = (prefix, candidates) ->
el for el in candidates when 0 is el.indexOf prefix
# Make sure that uncaught exceptions don't kill the REPL.
process.on 'uncaughtException', error
# The current backlog of multi-line code.
backlog = ''
# 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) ->
# remove single-line comments
buffer = buffer.replace /(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/, "$1$2$3"
# remove trailing newlines
buffer = buffer.replace /[\r\n]+$/, ""
if multilineMode
backlog += "#{buffer}\n"
repl.setPrompt REPL_PROMPT_CONTINUATION
repl.prompt()
return
if !buffer.toString().trim() and !backlog
repl.prompt()
return
code = backlog += buffer
if code[code.length - 1] is '\\'
backlog = "#{backlog[...-1]}\n"
repl.setPrompt REPL_PROMPT_CONTINUATION
repl.prompt()
return
repl.setPrompt REPL_PROMPT
backlog = ''
try
_ = global._
returnValue = CoffeeScript.eval "_=(#{code}\n)", {
filename: 'repl'
modulename: 'repl'
}
if returnValue is undefined
global._ = _
repl.output.write "#{inspect returnValue, no, 2, enableColours}\n"
catch err
error err
repl.prompt()
if stdin.readable and stdin.isRaw
# handle piped input
pipedInput = ''
repl =
prompt: -> stdout.write @_prompt
setPrompt: (p) -> @_prompt = p
input: stdin
output: stdout
on: ->
stdin.on 'data', (chunk) ->
pipedInput += chunk
return unless /\n/.test pipedInput
lines = pipedInput.split "\n"
pipedInput = lines[lines.length - 1]
for line in lines[...-1] when line
stdout.write "#{line}\n"
run line
return
stdin.on 'end', ->
for line in pipedInput.trim().split "\n" when line
stdout.write "#{line}\n"
run line
stdout.write '\n'
process.exit 0
else
# 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
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
repl._line() if not multilineMode and backlog
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 or repl.line
backlog = ''
repl.historyIndex = -1
repl.setPrompt REPL_PROMPT
repl.output.write '\n(^C again to quit)'
repl._line (repl.line = '')
else
repl.close()
repl.on 'close', ->
repl.output.write '\n'
repl.input.destroy()
repl.on 'line', run
repl.setPrompt REPL_PROMPT
repl.prompt()
|