mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
362 lines
12 KiB
HTML
362 lines
12 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<html>
|
|
<head>
|
|
<title>repl.coffee</title>
|
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
|
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
|
|
<link rel="stylesheet" media="all" href="docco.css" />
|
|
</head>
|
|
<body>
|
|
<div id="container">
|
|
<div id="background"></div>
|
|
|
|
<ul id="jump_to">
|
|
<li>
|
|
<a class="large" href="javascript:void(0);">Jump To …</a>
|
|
<a class="small" href="javascript:void(0);">+</a>
|
|
<div id="jump_wrapper">
|
|
<div id="jump_page">
|
|
|
|
|
|
<a class="source" href="browser.html">
|
|
browser.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="cake.html">
|
|
cake.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="coffee-script.html">
|
|
coffee-script.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="command.html">
|
|
command.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="grammar.html">
|
|
grammar.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="helpers.html">
|
|
helpers.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="index.html">
|
|
index.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="lexer.html">
|
|
lexer.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="nodes.html">
|
|
nodes.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="optparse.html">
|
|
optparse.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="repl.html">
|
|
repl.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="rewriter.html">
|
|
rewriter.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="scope.html">
|
|
scope.litcoffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="sourcemap.html">
|
|
sourcemap.litcoffee
|
|
</a>
|
|
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
|
|
<ul class="sections">
|
|
|
|
<li id="title">
|
|
<div class="annotation">
|
|
<h1>repl.coffee</h1>
|
|
</div>
|
|
</li>
|
|
|
|
|
|
|
|
<li id="section-1">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-1">¶</a>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre>vm = require <span class="string">'vm'</span>
|
|
nodeREPL = require <span class="string">'repl'</span>
|
|
CoffeeScript = require <span class="string">'./coffee-script'</span>
|
|
{merge, prettyErrorMessage} = require <span class="string">'./helpers'</span>
|
|
|
|
replDefaults =
|
|
prompt: <span class="string">'coffee> '</span>,
|
|
eval: (input, context, filename, cb) -></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-2">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-2">¶</a>
|
|
</div>
|
|
<p>XXX: multiline hack.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> input = input.replace <span class="regexp">/\uFF00/g</span>, <span class="string">'\n'</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-3">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-3">¶</a>
|
|
</div>
|
|
<p>Node's REPL sends the input ending with a newline and then wrapped in
|
|
parens. Unwrap all that.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> input = input.replace <span class="regexp">/^\(([\s\S]*)\n\)$/m</span>, <span class="string">'$1'</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-4">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-4">¶</a>
|
|
</div>
|
|
<p>Require AST nodes to do some AST manipulation.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> {Block, Assign, Value, Literal} = require <span class="string">'./nodes'</span>
|
|
|
|
<span class="keyword">try</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-5">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-5">¶</a>
|
|
</div>
|
|
<p>Generate the AST of the clean input.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> ast = CoffeeScript.nodes input</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-6">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-6">¶</a>
|
|
</div>
|
|
<p>Add assignment to <code>_</code> variable to force the input to be an expression.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> ast = <span class="keyword">new</span> Block [
|
|
<span class="keyword">new</span> Assign (<span class="keyword">new</span> Value <span class="keyword">new</span> Literal <span class="string">'_'</span>), ast, <span class="string">'='</span>
|
|
]
|
|
js = ast.compile bare: <span class="literal">yes</span>, locals: Object.keys(context)
|
|
cb <span class="literal">null</span>, vm.runInContext(js, context, filename)
|
|
<span class="keyword">catch</span> err
|
|
cb prettyErrorMessage(err, filename, input, <span class="literal">yes</span>)
|
|
|
|
<span class="function"><span class="title">addMultilineHandler</span></span> = (repl) ->
|
|
{rli, inputStream, outputStream} = repl
|
|
|
|
multiline =
|
|
enabled: <span class="literal">off</span>
|
|
initialPrompt: repl.prompt.replace(<span class="regexp">/^[^> ]*/, (x) -> x.replace /./g</span>, <span class="string">'-'</span>)
|
|
prompt: repl.prompt.replace(<span class="regexp">/^[^> ]*>?/, (x) -> x.replace /./g</span>, <span class="string">'.'</span>)
|
|
buffer: <span class="string">''</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-7">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-7">¶</a>
|
|
</div>
|
|
<p>Proxy node's line listener
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> nodeLineListener = rli.listeners(<span class="string">'line'</span>)[<span class="number">0</span>]
|
|
rli.removeListener <span class="string">'line'</span>, nodeLineListener
|
|
rli.<span class="literal">on</span> <span class="string">'line'</span>, (cmd) ->
|
|
<span class="keyword">if</span> multiline.enabled
|
|
multiline.buffer += <span class="string">"<span class="subst">#{cmd}</span>\n"</span>
|
|
rli.setPrompt multiline.prompt
|
|
rli.prompt <span class="literal">true</span>
|
|
<span class="keyword">else</span>
|
|
nodeLineListener cmd
|
|
<span class="keyword">return</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-8">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-8">¶</a>
|
|
</div>
|
|
<p>Handle Ctrl-v
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> inputStream.<span class="literal">on</span> <span class="string">'keypress'</span>, (char, key) ->
|
|
<span class="keyword">return</span> <span class="keyword">unless</span> key <span class="keyword">and</span> key.ctrl <span class="keyword">and</span> <span class="keyword">not</span> key.meta <span class="keyword">and</span> <span class="keyword">not</span> key.shift <span class="keyword">and</span> key.name <span class="keyword">is</span> <span class="string">'v'</span>
|
|
<span class="keyword">if</span> multiline.enabled</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-9">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-9">¶</a>
|
|
</div>
|
|
<p>allow arbitrarily switching between modes any time before multiple lines are entered
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> <span class="keyword">unless</span> multiline.buffer.match <span class="regexp">/\n/</span>
|
|
multiline.enabled = <span class="keyword">not</span> multiline.enabled
|
|
rli.setPrompt repl.prompt
|
|
rli.prompt <span class="literal">true</span>
|
|
<span class="keyword">return</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-10">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-10">¶</a>
|
|
</div>
|
|
<p>no-op unless the current line is empty
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="keyword">if</span> rli.line? <span class="keyword">and</span> <span class="keyword">not</span> rli.line.match <span class="regexp">/^\s*$/</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-11">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-11">¶</a>
|
|
</div>
|
|
<p>eval, print, loop
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> multiline.enabled = <span class="keyword">not</span> multiline.enabled
|
|
rli.line = <span class="string">''</span>
|
|
rli.cursor = <span class="number">0</span>
|
|
rli.output.cursorTo <span class="number">0</span>
|
|
rli.output.clearLine <span class="number">1</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-12">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-12">¶</a>
|
|
</div>
|
|
<p>XXX: multiline hack
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre> multiline.buffer = multiline.buffer.replace <span class="regexp">/\n/g</span>, <span class="string">'\uFF00'</span>
|
|
rli.emit <span class="string">'line'</span>, multiline.buffer
|
|
multiline.buffer = <span class="string">''</span>
|
|
<span class="keyword">else</span>
|
|
multiline.enabled = <span class="keyword">not</span> multiline.enabled
|
|
rli.setPrompt multiline.initialPrompt
|
|
rli.prompt <span class="literal">true</span>
|
|
<span class="keyword">return</span>
|
|
|
|
module.exports =
|
|
start: (opts = {}) ->
|
|
[major, minor, build] = process.versions.node.split(<span class="string">'.'</span>).map (n) -> parseInt(n)
|
|
|
|
<span class="keyword">if</span> major <span class="keyword">is</span> <span class="number">0</span> <span class="keyword">and</span> minor < <span class="number">8</span>
|
|
console.warn <span class="string">"Node 0.8.0+ required for CoffeeScript REPL"</span>
|
|
process.exit <span class="number">1</span>
|
|
|
|
opts = merge replDefaults, opts
|
|
repl = nodeREPL.start opts
|
|
repl.<span class="literal">on</span> <span class="string">'exit'</span>, -> repl.outputStream.write <span class="string">'\n'</span>
|
|
addMultilineHandler repl
|
|
repl</pre></div></div>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</div>
|
|
</body>
|
|
</html>
|