/documentation/docs/repl.html
http://github.com/jashkenas/coffee-script · HTML · 608 lines · 403 code · 205 blank · 0 comment · 0 complexity · 4d2b8f2ac77e3fe6d7ff3af448aed03f MD5 · raw file
- <!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="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="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">'./coffee-script'</span>
- {merge, updateSyntaxError} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
- replDefaults =
- <span class="hljs-attribute">prompt</span>: <span class="hljs-string">'coffee> '</span>,
- <span class="hljs-attribute">historyFile</span>: path.join process.env.HOME, <span class="hljs-string">'.coffee_history'</span> <span class="hljs-keyword">if</span> process.env.HOME
- <span class="hljs-attribute">historyMaxInputSize</span>: <span class="hljs-number">10240</span>
- <span class="hljs-attribute">eval</span>: <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>Require AST nodes to do some AST manipulation.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> {Block, Assign, Value, Literal} = <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-5">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-5">¶</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-6">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-6">¶</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.variable
- )</pre></div></div>
-
- </li>
-
-
- <li id="section-7">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-7">¶</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-8">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-8">¶</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>
- ]
- js = ast.compile {<span class="hljs-attribute">bare</span>: <span class="hljs-literal">yes</span>, <span class="hljs-attribute">locals</span>: Object.keys(context), referencedVars}
- cb <span class="hljs-literal">null</span>, runInContext js, context, filename
- <span class="hljs-keyword">catch</span> err</pre></div></div>
-
- </li>
-
-
- <li id="section-9">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-9">¶</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-10">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-10">¶</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 =
- <span class="hljs-attribute">enabled</span>: <span class="hljs-literal">off</span>
- <span class="hljs-attribute">initialPrompt</span>: 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>
- <span class="hljs-attribute">prompt</span>: 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>
- <span class="hljs-attribute">buffer</span>: <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>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-12">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-12">¶</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-13">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-13">¶</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-14">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-14">¶</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-15">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-15">¶</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-16">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-16">¶</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-17">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-17">¶</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-18">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-18">¶</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-19">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-19">¶</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 = <span class="hljs-keyword">new</span> Buffer(size)
- fs.readSync readFd, buffer, <span class="hljs-number">0</span>, size, stat.size - size
- fs.close readFd</pre></div></div>
-
- </li>
-
-
- <li id="section-20">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-20">¶</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-21">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-21">¶</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-22">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-22">¶</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> lastLine <span class="hljs-keyword">isnt</span> code</pre></div></div>
-
- </li>
-
-
- <li id="section-23">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-23">¶</a>
- </div>
- <p>Save the latest command in the file</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> fs.write fd, <span class="hljs-string">"<span class="hljs-subst">#{code}</span>\n"</span>
- lastLine = code
- repl.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>,<span class="hljs-function"> -></span> fs.close fd</pre></div></div>
-
- </li>
-
-
- <li id="section-24">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-24">¶</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>)] =
- <span class="hljs-attribute">help</span>: <span class="hljs-string">'Show command history'</span>
- <span class="hljs-attribute">action</span>:<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-25">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-25">¶</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>.<span class="hljs-built_in">exports</span> =
- <span class="hljs-attribute">start</span>: <span class="hljs-function"><span class="hljs-params">(opts = {})</span> -></span>
- [major, minor, build] = process.versions.node.split<span class="hljs-function"><span class="hljs-params">(<span class="hljs-string">'.'</span>)</span>.<span class="hljs-title">map</span> <span class="hljs-params">(n)</span> -></span> parseInt(n)
- <span class="hljs-keyword">if</span> major <span class="hljs-keyword">is</span> <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> minor < <span class="hljs-number">8</span>
- <span class="hljs-built_in">console</span>.warn <span class="hljs-string">"Node 0.8.0+ 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>.]
- 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-26">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-26">¶</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>