mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00

* Fix #4775: Remove no-longer-correct mention of the docs using text/coffeescript * 2.0.3 changelog * Update output for 2.0.3 * Bump date
767 lines
32 KiB
HTML
767 lines
32 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_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="coffeescript.html">
|
||
coffeescript.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="register.html">
|
||
register.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>
|
||
</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>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
|
||
path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
|
||
vm = <span class="hljs-built_in">require</span> <span class="hljs-string">'vm'</span>
|
||
nodeREPL = <span class="hljs-built_in">require</span> <span class="hljs-string">'repl'</span>
|
||
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./'</span>
|
||
{merge, updateSyntaxError} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
|
||
|
||
sawSIGINT = <span class="hljs-literal">no</span>
|
||
transpile = <span class="hljs-literal">no</span>
|
||
|
||
replDefaults =
|
||
prompt: <span class="hljs-string">'coffee> '</span>,
|
||
historyFile: <span class="hljs-keyword">do</span> ->
|
||
historyPath = process.env.XDG_CACHE_HOME <span class="hljs-keyword">or</span> process.env.HOME
|
||
path.join historyPath, <span class="hljs-string">'.coffee_history'</span> <span class="hljs-keyword">if</span> historyPath
|
||
historyMaxInputSize: <span class="hljs-number">10240</span>
|
||
eval: <span class="hljs-function"><span class="hljs-params">(input, context, filename, cb)</span> -></span></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="hljs-regexp">/\uFF00/g</span>, <span class="hljs-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="hljs-regexp">/^\(([\s\S]*)\n\)$/m</span>, <span class="hljs-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>Node’s REPL v6.9.1+ sends the input wrapped in a try/catch statement.
|
||
Unwrap that too.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> input = input.replace <span class="hljs-regexp">/^\s*try\s*{([\s\S]*)}\s*catch.*$/m</span>, <span class="hljs-string">'$1'</span></pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-5">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-5">¶</a>
|
||
</div>
|
||
<p>Require AST nodes to do some AST manipulation.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> {Block, Assign, Value, Literal, Call, Code} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./nodes'</span>
|
||
|
||
<span class="hljs-keyword">try</span></pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-6">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-6">¶</a>
|
||
</div>
|
||
<p>Tokenize the clean input.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> tokens = CoffeeScript.tokens input</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-7">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-7">¶</a>
|
||
</div>
|
||
<p>Filter out tokens generated just to hold comments.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> tokens.length >= <span class="hljs-number">2</span> <span class="hljs-keyword">and</span> tokens[<span class="hljs-number">0</span>].generated <span class="hljs-keyword">and</span>
|
||
tokens[<span class="hljs-number">0</span>].comments?.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> tokens[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span> <span class="hljs-keyword">and</span>
|
||
tokens[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'TERMINATOR'</span>
|
||
tokens = tokens[<span class="hljs-number">2.</span>..]
|
||
<span class="hljs-keyword">if</span> tokens.length >= <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> tokens[tokens.length - <span class="hljs-number">1</span>].generated <span class="hljs-keyword">and</span>
|
||
tokens[tokens.length - <span class="hljs-number">1</span>].comments?.length <span class="hljs-keyword">isnt</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> tokens[tokens.length - <span class="hljs-number">1</span>][<span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span>
|
||
tokens.pop()</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-8">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-8">¶</a>
|
||
</div>
|
||
<p>Collect referenced variable names just like in <code>CoffeeScript.compile</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> referencedVars = (token[<span class="hljs-number">1</span>] <span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'IDENTIFIER'</span>)</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-9">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-9">¶</a>
|
||
</div>
|
||
<p>Generate the AST of the tokens.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> ast = CoffeeScript.nodes tokens</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-10">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-10">¶</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="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Assign (<span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal <span class="hljs-string">'__'</span>), ast, <span class="hljs-string">'='</span>]</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-11">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-11">¶</a>
|
||
</div>
|
||
<p>Wrap the expression in a closure to support top-level <code>await</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Code [], ast
|
||
isAsync = ast.isAsync</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-12">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-12">¶</a>
|
||
</div>
|
||
<p>Invoke the wrapping closure.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Block [<span class="hljs-keyword">new</span> Call ast]
|
||
js = ast.compile {bare: <span class="hljs-literal">yes</span>, locals: Object.keys(context), referencedVars, sharedScope: <span class="hljs-literal">yes</span>}
|
||
<span class="hljs-keyword">if</span> transpile
|
||
js = transpile.transpile(js, transpile.options).code</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-13">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-13">¶</a>
|
||
</div>
|
||
<p>Strip <code>"use strict"</code>, to avoid an exception on assigning to
|
||
undeclared variable <code>__</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> js = js.replace <span class="hljs-regexp">/^"use strict"|^'use strict'/</span>, <span class="hljs-string">''</span>
|
||
result = runInContext js, context, filename</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-14">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-14">¶</a>
|
||
</div>
|
||
<p>Await an async result, if necessary.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> isAsync
|
||
result.<span class="hljs-keyword">then</span> (resolvedResult) ->
|
||
cb <span class="hljs-literal">null</span>, resolvedResult <span class="hljs-keyword">unless</span> sawSIGINT
|
||
sawSIGINT = <span class="hljs-literal">no</span>
|
||
<span class="hljs-keyword">else</span>
|
||
cb <span class="hljs-literal">null</span>, result
|
||
<span class="hljs-keyword">catch</span> err</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-15">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-15">¶</a>
|
||
</div>
|
||
<p>AST’s <code>compile</code> does not add source code information to syntax errors.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> updateSyntaxError err, input
|
||
cb err
|
||
<span class="hljs-function">
|
||
<span class="hljs-title">runInContext</span> = <span class="hljs-params">(js, context, filename)</span> -></span>
|
||
<span class="hljs-keyword">if</span> context <span class="hljs-keyword">is</span> <span class="hljs-built_in">global</span>
|
||
vm.runInThisContext js, filename
|
||
<span class="hljs-keyword">else</span>
|
||
vm.runInContext js, context, filename
|
||
<span class="hljs-function">
|
||
<span class="hljs-title">addMultilineHandler</span> = <span class="hljs-params">(repl)</span> -></span>
|
||
{rli, inputStream, outputStream} = repl</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-16">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-16">¶</a>
|
||
</div>
|
||
<p>Node 0.11.12 changed API, prompt is now _prompt.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> origPrompt = repl._prompt ? repl.prompt
|
||
|
||
multiline =
|
||
enabled: <span class="hljs-literal">off</span>
|
||
initialPrompt: origPrompt.replace <span class="hljs-regexp">/^[^> ]*/</span>, <span class="hljs-function"><span class="hljs-params">(x)</span> -></span> x.replace <span class="hljs-regexp">/./g</span>, <span class="hljs-string">'-'</span>
|
||
prompt: origPrompt.replace <span class="hljs-regexp">/^[^> ]*>?/</span>, <span class="hljs-function"><span class="hljs-params">(x)</span> -></span> x.replace <span class="hljs-regexp">/./g</span>, <span class="hljs-string">'.'</span>
|
||
buffer: <span class="hljs-string">''</span></pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-17">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-17">¶</a>
|
||
</div>
|
||
<p>Proxy node’s line listener</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> nodeLineListener = rli.listeners(<span class="hljs-string">'line'</span>)[<span class="hljs-number">0</span>]
|
||
rli.removeListener <span class="hljs-string">'line'</span>, nodeLineListener
|
||
rli.<span class="hljs-literal">on</span> <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(cmd)</span> -></span>
|
||
<span class="hljs-keyword">if</span> multiline.enabled
|
||
multiline.buffer += <span class="hljs-string">"<span class="hljs-subst">#{cmd}</span>\n"</span>
|
||
rli.setPrompt multiline.prompt
|
||
rli.prompt <span class="hljs-literal">true</span>
|
||
<span class="hljs-keyword">else</span>
|
||
rli.setPrompt origPrompt
|
||
nodeLineListener cmd
|
||
<span class="hljs-keyword">return</span></pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-18">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-18">¶</a>
|
||
</div>
|
||
<p>Handle Ctrl-v</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> inputStream.<span class="hljs-literal">on</span> <span class="hljs-string">'keypress'</span>, <span class="hljs-function"><span class="hljs-params">(char, key)</span> -></span>
|
||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> key <span class="hljs-keyword">and</span> key.ctrl <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> key.meta <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> key.shift <span class="hljs-keyword">and</span> key.name <span class="hljs-keyword">is</span> <span class="hljs-string">'v'</span>
|
||
<span class="hljs-keyword">if</span> multiline.enabled</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-19">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-19">¶</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="hljs-keyword">unless</span> multiline.buffer.match <span class="hljs-regexp">/\n/</span>
|
||
multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
|
||
rli.setPrompt origPrompt
|
||
rli.prompt <span class="hljs-literal">true</span>
|
||
<span class="hljs-keyword">return</span></pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-20">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-20">¶</a>
|
||
</div>
|
||
<p>no-op unless the current line is empty</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> rli.line? <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> rli.line.match <span class="hljs-regexp">/^\s*$/</span></pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-21">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-21">¶</a>
|
||
</div>
|
||
<p>eval, print, loop</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
|
||
rli.line = <span class="hljs-string">''</span>
|
||
rli.cursor = <span class="hljs-number">0</span>
|
||
rli.output.cursorTo <span class="hljs-number">0</span>
|
||
rli.output.clearLine <span class="hljs-number">1</span></pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-22">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-22">¶</a>
|
||
</div>
|
||
<p>XXX: multiline hack</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> multiline.buffer = multiline.buffer.replace <span class="hljs-regexp">/\n/g</span>, <span class="hljs-string">'\uFF00'</span>
|
||
rli.emit <span class="hljs-string">'line'</span>, multiline.buffer
|
||
multiline.buffer = <span class="hljs-string">''</span>
|
||
<span class="hljs-keyword">else</span>
|
||
multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
|
||
rli.setPrompt multiline.initialPrompt
|
||
rli.prompt <span class="hljs-literal">true</span>
|
||
<span class="hljs-keyword">return</span></pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-23">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-23">¶</a>
|
||
</div>
|
||
<p>Store and load command history from a file</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">addHistory</span> = <span class="hljs-params">(repl, filename, maxSize)</span> -></span>
|
||
lastLine = <span class="hljs-literal">null</span>
|
||
<span class="hljs-keyword">try</span></pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-24">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-24">¶</a>
|
||
</div>
|
||
<p>Get file info and at most maxSize of command history</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> stat = fs.statSync filename
|
||
size = Math.min maxSize, stat.size</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-25">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-25">¶</a>
|
||
</div>
|
||
<p>Read last <code>size</code> bytes from the file</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> readFd = fs.openSync filename, <span class="hljs-string">'r'</span>
|
||
buffer = Buffer.alloc size
|
||
fs.readSync readFd, buffer, <span class="hljs-number">0</span>, size, stat.size - size
|
||
fs.closeSync readFd</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-26">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-26">¶</a>
|
||
</div>
|
||
<p>Set the history on the interpreter</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> repl.rli.history = buffer.toString().split(<span class="hljs-string">'\n'</span>).reverse()</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-27">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-27">¶</a>
|
||
</div>
|
||
<p>If the history file was truncated we should pop off a potential partial line</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> repl.rli.history.pop() <span class="hljs-keyword">if</span> stat.size > maxSize</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-28">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-28">¶</a>
|
||
</div>
|
||
<p>Shift off the final blank newline</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> repl.rli.history.shift() <span class="hljs-keyword">if</span> repl.rli.history[<span class="hljs-number">0</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">''</span>
|
||
repl.rli.historyIndex = <span class="hljs-number">-1</span>
|
||
lastLine = repl.rli.history[<span class="hljs-number">0</span>]
|
||
|
||
fd = fs.openSync filename, <span class="hljs-string">'a'</span>
|
||
|
||
repl.rli.addListener <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(code)</span> -></span>
|
||
<span class="hljs-keyword">if</span> code <span class="hljs-keyword">and</span> code.length <span class="hljs-keyword">and</span> code <span class="hljs-keyword">isnt</span> <span class="hljs-string">'.history'</span> <span class="hljs-keyword">and</span> code <span class="hljs-keyword">isnt</span> <span class="hljs-string">'.exit'</span> <span class="hljs-keyword">and</span> lastLine <span class="hljs-keyword">isnt</span> code</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-29">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-29">¶</a>
|
||
</div>
|
||
<p>Save the latest command in the file</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> fs.writeSync fd, <span class="hljs-string">"<span class="hljs-subst">#{code}</span>\n"</span>
|
||
lastLine = code</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-30">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-30">¶</a>
|
||
</div>
|
||
<p>XXX: The SIGINT event from REPLServer is undocumented, so this is a bit fragile</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> repl.<span class="hljs-literal">on</span> <span class="hljs-string">'SIGINT'</span>, <span class="hljs-function">-></span> sawSIGINT = <span class="hljs-literal">yes</span>
|
||
repl.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>, <span class="hljs-function">-></span> fs.closeSync fd</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-31">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-31">¶</a>
|
||
</div>
|
||
<p>Add a command to show the history stack</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> repl.commands[getCommandId(repl, <span class="hljs-string">'history'</span>)] =
|
||
help: <span class="hljs-string">'Show command history'</span>
|
||
action: <span class="hljs-function">-></span>
|
||
repl.outputStream.write <span class="hljs-string">"<span class="hljs-subst">#{repl.rli.history[..].reverse().join <span class="hljs-string">'\n'</span>}</span>\n"</span>
|
||
repl.displayPrompt()
|
||
<span class="hljs-function">
|
||
<span class="hljs-title">getCommandId</span> = <span class="hljs-params">(repl, commandName)</span> -></span></pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-32">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-32">¶</a>
|
||
</div>
|
||
<p>Node 0.11 changed API, a command such as ‘.help’ is now stored as ‘help’</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> commandsHaveLeadingDot = repl.commands[<span class="hljs-string">'.help'</span>]?
|
||
<span class="hljs-keyword">if</span> commandsHaveLeadingDot <span class="hljs-keyword">then</span> <span class="hljs-string">".<span class="hljs-subst">#{commandName}</span>"</span> <span class="hljs-keyword">else</span> commandName
|
||
|
||
<span class="hljs-built_in">module</span>.exports =
|
||
start: <span class="hljs-function"><span class="hljs-params">(opts = {})</span> -></span>
|
||
[major, minor, build] = process.versions.node.split(<span class="hljs-string">'.'</span>).map (n) -> parseInt(n, <span class="hljs-number">10</span>)
|
||
|
||
<span class="hljs-keyword">if</span> major < <span class="hljs-number">6</span>
|
||
<span class="hljs-built_in">console</span>.warn <span class="hljs-string">"Node 6+ required for CoffeeScript REPL"</span>
|
||
process.exit <span class="hljs-number">1</span>
|
||
|
||
CoffeeScript.register()
|
||
process.argv = [<span class="hljs-string">'coffee'</span>].concat process.argv[<span class="hljs-number">2.</span>.]
|
||
<span class="hljs-keyword">if</span> opts.transpile
|
||
<span class="hljs-keyword">try</span>
|
||
transpile = {}
|
||
transpile.transpile = <span class="hljs-built_in">require</span>(<span class="hljs-string">'babel-core'</span>).transform
|
||
<span class="hljs-keyword">catch</span>
|
||
<span class="hljs-built_in">console</span>.error <span class="hljs-string">'''
|
||
To use --transpile with an interactive REPL, babel-core must be installed either in the current folder or globally:
|
||
npm install --save-dev babel-core
|
||
or
|
||
npm install --global babel-core
|
||
And you must save options to configure Babel in one of the places it looks to find its options.
|
||
See http://coffeescript.org/#transpilation
|
||
'''</span>
|
||
process.exit <span class="hljs-number">1</span>
|
||
transpile.options =
|
||
filename: path.resolve process.cwd(), <span class="hljs-string">'<repl>'</span></pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-33">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-33">¶</a>
|
||
</div>
|
||
<p>Since the REPL compilation path is unique (in <code>eval</code> above), we need
|
||
another way to get the <code>options</code> object attached to a module so that
|
||
it knows later on whether it needs to be transpiled. In the case of
|
||
the REPL, the only applicable option is <code>transpile</code>.</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> Module = <span class="hljs-built_in">require</span> <span class="hljs-string">'module'</span>
|
||
originalModuleLoad = Module::load
|
||
Module::load = <span class="hljs-function"><span class="hljs-params">(filename)</span> -></span>
|
||
@options = transpile: transpile.options
|
||
originalModuleLoad.call @, filename
|
||
opts = merge replDefaults, opts
|
||
repl = nodeREPL.start opts
|
||
runInContext opts.prelude, repl.context, <span class="hljs-string">'prelude'</span> <span class="hljs-keyword">if</span> opts.prelude
|
||
repl.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>, <span class="hljs-function">-></span> repl.outputStream.write <span class="hljs-string">'\n'</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> repl.rli.closed
|
||
addMultilineHandler repl
|
||
addHistory repl, opts.historyFile, opts.historyMaxInputSize <span class="hljs-keyword">if</span> opts.historyFile</pre></div></div>
|
||
|
||
</li>
|
||
|
||
|
||
<li id="section-34">
|
||
<div class="annotation">
|
||
|
||
<div class="pilwrap ">
|
||
<a class="pilcrow" href="#section-34">¶</a>
|
||
</div>
|
||
<p>Adapt help inherited from the node REPL</p>
|
||
|
||
</div>
|
||
|
||
<div class="content"><div class='highlight'><pre> repl.commands[getCommandId(repl, <span class="hljs-string">'load'</span>)].help = <span class="hljs-string">'Load code from a file into this REPL session'</span>
|
||
repl</pre></div></div>
|
||
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
</body>
|
||
</html>
|