PageRenderTime 52ms CodeModel.GetById 2ms app.highlight 41ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  1<!DOCTYPE html>
  2
  3<html>
  4<head>
  5  <title>repl.coffee</title>
  6  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  7  <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
  8  <link rel="stylesheet" media="all" href="docco.css" />
  9</head>
 10<body>
 11  <div id="container">
 12    <div id="background"></div>
 13    
 14      <ul id="jump_to">
 15        <li>
 16          <a class="large" href="javascript:void(0);">Jump To &hellip;</a>
 17          <a class="small" href="javascript:void(0);">+</a>
 18          <div id="jump_wrapper">
 19          <div id="jump_page_wrapper">
 20            <div id="jump_page">
 21              
 22                
 23                <a class="source" href="browser.html">
 24                  browser.coffee
 25                </a>
 26              
 27                
 28                <a class="source" href="cake.html">
 29                  cake.coffee
 30                </a>
 31              
 32                
 33                <a class="source" href="coffee-script.html">
 34                  coffee-script.coffee
 35                </a>
 36              
 37                
 38                <a class="source" href="command.html">
 39                  command.coffee
 40                </a>
 41              
 42                
 43                <a class="source" href="grammar.html">
 44                  grammar.coffee
 45                </a>
 46              
 47                
 48                <a class="source" href="helpers.html">
 49                  helpers.coffee
 50                </a>
 51              
 52                
 53                <a class="source" href="index.html">
 54                  index.coffee
 55                </a>
 56              
 57                
 58                <a class="source" href="lexer.html">
 59                  lexer.coffee
 60                </a>
 61              
 62                
 63                <a class="source" href="nodes.html">
 64                  nodes.coffee
 65                </a>
 66              
 67                
 68                <a class="source" href="optparse.html">
 69                  optparse.coffee
 70                </a>
 71              
 72                
 73                <a class="source" href="register.html">
 74                  register.coffee
 75                </a>
 76              
 77                
 78                <a class="source" href="repl.html">
 79                  repl.coffee
 80                </a>
 81              
 82                
 83                <a class="source" href="rewriter.html">
 84                  rewriter.coffee
 85                </a>
 86              
 87                
 88                <a class="source" href="scope.html">
 89                  scope.litcoffee
 90                </a>
 91              
 92                
 93                <a class="source" href="sourcemap.html">
 94                  sourcemap.litcoffee
 95                </a>
 96              
 97            </div>
 98          </div>
 99        </li>
100      </ul>
101    
102    <ul class="sections">
103        
104          <li id="title">
105              <div class="annotation">
106                  <h1>repl.coffee</h1>
107              </div>
108          </li>
109        
110        
111        
112        <li id="section-1">
113            <div class="annotation">
114              
115              <div class="pilwrap ">
116                <a class="pilcrow" href="#section-1">&#182;</a>
117              </div>
118              
119            </div>
120            
121            <div class="content"><div class='highlight'><pre>fs = <span class="hljs-built_in">require</span> <span class="hljs-string">'fs'</span>
122path = <span class="hljs-built_in">require</span> <span class="hljs-string">'path'</span>
123vm = <span class="hljs-built_in">require</span> <span class="hljs-string">'vm'</span>
124nodeREPL = <span class="hljs-built_in">require</span> <span class="hljs-string">'repl'</span>
125CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./coffee-script'</span>
126{merge, updateSyntaxError} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
127
128replDefaults =
129  <span class="hljs-attribute">prompt</span>: <span class="hljs-string">'coffee&gt; '</span>,
130  <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
131  <span class="hljs-attribute">historyMaxInputSize</span>: <span class="hljs-number">10240</span>
132  <span class="hljs-attribute">eval</span>: <span class="hljs-function"><span class="hljs-params">(input, context, filename, cb)</span> -&gt;</span></pre></div></div>
133            
134        </li>
135        
136        
137        <li id="section-2">
138            <div class="annotation">
139              
140              <div class="pilwrap ">
141                <a class="pilcrow" href="#section-2">&#182;</a>
142              </div>
143              <p>XXX: multiline hack.</p>
144
145            </div>
146            
147            <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>
148            
149        </li>
150        
151        
152        <li id="section-3">
153            <div class="annotation">
154              
155              <div class="pilwrap ">
156                <a class="pilcrow" href="#section-3">&#182;</a>
157              </div>
158              <p>Node’s REPL sends the input ending with a newline and then wrapped in
159parens. Unwrap all that.</p>
160
161            </div>
162            
163            <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>
164            
165        </li>
166        
167        
168        <li id="section-4">
169            <div class="annotation">
170              
171              <div class="pilwrap ">
172                <a class="pilcrow" href="#section-4">&#182;</a>
173              </div>
174              <p>Require AST nodes to do some AST manipulation.</p>
175
176            </div>
177            
178            <div class="content"><div class='highlight'><pre>    {Block, Assign, Value, Literal} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./nodes'</span>
179
180    <span class="hljs-keyword">try</span></pre></div></div>
181            
182        </li>
183        
184        
185        <li id="section-5">
186            <div class="annotation">
187              
188              <div class="pilwrap ">
189                <a class="pilcrow" href="#section-5">&#182;</a>
190              </div>
191              <p>Tokenize the clean input.</p>
192
193            </div>
194            
195            <div class="content"><div class='highlight'><pre>      tokens = CoffeeScript.tokens input</pre></div></div>
196            
197        </li>
198        
199        
200        <li id="section-6">
201            <div class="annotation">
202              
203              <div class="pilwrap ">
204                <a class="pilcrow" href="#section-6">&#182;</a>
205              </div>
206              <p>Collect referenced variable names just like in <code>CoffeeScript.compile</code>.</p>
207
208            </div>
209            
210            <div class="content"><div class='highlight'><pre>      referencedVars = (
211        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
212      )</pre></div></div>
213            
214        </li>
215        
216        
217        <li id="section-7">
218            <div class="annotation">
219              
220              <div class="pilwrap ">
221                <a class="pilcrow" href="#section-7">&#182;</a>
222              </div>
223              <p>Generate the AST of the tokens.</p>
224
225            </div>
226            
227            <div class="content"><div class='highlight'><pre>      ast = CoffeeScript.nodes tokens</pre></div></div>
228            
229        </li>
230        
231        
232        <li id="section-8">
233            <div class="annotation">
234              
235              <div class="pilwrap ">
236                <a class="pilcrow" href="#section-8">&#182;</a>
237              </div>
238              <p>Add assignment to <code>_</code> variable to force the input to be an expression.</p>
239
240            </div>
241            
242            <div class="content"><div class='highlight'><pre>      ast = <span class="hljs-keyword">new</span> Block [
243        <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>
244      ]
245      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}
246      cb <span class="hljs-literal">null</span>, runInContext js, context, filename
247    <span class="hljs-keyword">catch</span> err</pre></div></div>
248            
249        </li>
250        
251        
252        <li id="section-9">
253            <div class="annotation">
254              
255              <div class="pilwrap ">
256                <a class="pilcrow" href="#section-9">&#182;</a>
257              </div>
258              <p>AST’s <code>compile</code> does not add source code information to syntax errors.</p>
259
260            </div>
261            
262            <div class="content"><div class='highlight'><pre>      updateSyntaxError err, input
263      cb err
264
265<span class="hljs-function"><span class="hljs-title">runInContext</span> = <span class="hljs-params">(js, context, filename)</span> -&gt;</span>
266  <span class="hljs-keyword">if</span> context <span class="hljs-keyword">is</span> <span class="hljs-built_in">global</span>
267    vm.runInThisContext js, filename
268  <span class="hljs-keyword">else</span>
269    vm.runInContext js, context, filename
270
271<span class="hljs-function"><span class="hljs-title">addMultilineHandler</span> = <span class="hljs-params">(repl)</span> -&gt;</span>
272  {rli, inputStream, outputStream} = repl</pre></div></div>
273            
274        </li>
275        
276        
277        <li id="section-10">
278            <div class="annotation">
279              
280              <div class="pilwrap ">
281                <a class="pilcrow" href="#section-10">&#182;</a>
282              </div>
283              <p>Node 0.11.12 changed API, prompt is now _prompt.</p>
284
285            </div>
286            
287            <div class="content"><div class='highlight'><pre>  origPrompt = repl._prompt ? repl.prompt
288
289  multiline =
290    <span class="hljs-attribute">enabled</span>: <span class="hljs-literal">off</span>
291    <span class="hljs-attribute">initialPrompt</span>: origPrompt.replace <span class="hljs-regexp">/^[^&gt; ]*/</span>, <span class="hljs-function"><span class="hljs-params">(x)</span> -&gt;</span> x.replace <span class="hljs-regexp">/./g</span>, <span class="hljs-string">'-'</span>
292    <span class="hljs-attribute">prompt</span>: origPrompt.replace <span class="hljs-regexp">/^[^&gt; ]*&gt;?/</span>, <span class="hljs-function"><span class="hljs-params">(x)</span> -&gt;</span> x.replace <span class="hljs-regexp">/./g</span>, <span class="hljs-string">'.'</span>
293    <span class="hljs-attribute">buffer</span>: <span class="hljs-string">''</span></pre></div></div>
294            
295        </li>
296        
297        
298        <li id="section-11">
299            <div class="annotation">
300              
301              <div class="pilwrap ">
302                <a class="pilcrow" href="#section-11">&#182;</a>
303              </div>
304              <p>Proxy node’s line listener</p>
305
306            </div>
307            
308            <div class="content"><div class='highlight'><pre>  nodeLineListener = rli.listeners(<span class="hljs-string">'line'</span>)[<span class="hljs-number">0</span>]
309  rli.removeListener <span class="hljs-string">'line'</span>, nodeLineListener
310  rli.<span class="hljs-literal">on</span> <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(cmd)</span> -&gt;</span>
311    <span class="hljs-keyword">if</span> multiline.enabled
312      multiline.buffer += <span class="hljs-string">"<span class="hljs-subst">#{cmd}</span>\n"</span>
313      rli.setPrompt multiline.prompt
314      rli.prompt <span class="hljs-literal">true</span>
315    <span class="hljs-keyword">else</span>
316      rli.setPrompt origPrompt
317      nodeLineListener cmd
318    <span class="hljs-keyword">return</span></pre></div></div>
319            
320        </li>
321        
322        
323        <li id="section-12">
324            <div class="annotation">
325              
326              <div class="pilwrap ">
327                <a class="pilcrow" href="#section-12">&#182;</a>
328              </div>
329              <p>Handle Ctrl-v</p>
330
331            </div>
332            
333            <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> -&gt;</span>
334    <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>
335    <span class="hljs-keyword">if</span> multiline.enabled</pre></div></div>
336            
337        </li>
338        
339        
340        <li id="section-13">
341            <div class="annotation">
342              
343              <div class="pilwrap ">
344                <a class="pilcrow" href="#section-13">&#182;</a>
345              </div>
346              <p>allow arbitrarily switching between modes any time before multiple lines are entered</p>
347
348            </div>
349            
350            <div class="content"><div class='highlight'><pre>      <span class="hljs-keyword">unless</span> multiline.buffer.match <span class="hljs-regexp">/\n/</span>
351        multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
352        rli.setPrompt origPrompt
353        rli.prompt <span class="hljs-literal">true</span>
354        <span class="hljs-keyword">return</span></pre></div></div>
355            
356        </li>
357        
358        
359        <li id="section-14">
360            <div class="annotation">
361              
362              <div class="pilwrap ">
363                <a class="pilcrow" href="#section-14">&#182;</a>
364              </div>
365              <p>no-op unless the current line is empty</p>
366
367            </div>
368            
369            <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>
370            
371        </li>
372        
373        
374        <li id="section-15">
375            <div class="annotation">
376              
377              <div class="pilwrap ">
378                <a class="pilcrow" href="#section-15">&#182;</a>
379              </div>
380              <p>eval, print, loop</p>
381
382            </div>
383            
384            <div class="content"><div class='highlight'><pre>      multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
385      rli.line = <span class="hljs-string">''</span>
386      rli.cursor = <span class="hljs-number">0</span>
387      rli.output.cursorTo <span class="hljs-number">0</span>
388      rli.output.clearLine <span class="hljs-number">1</span></pre></div></div>
389            
390        </li>
391        
392        
393        <li id="section-16">
394            <div class="annotation">
395              
396              <div class="pilwrap ">
397                <a class="pilcrow" href="#section-16">&#182;</a>
398              </div>
399              <p>XXX: multiline hack</p>
400
401            </div>
402            
403            <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>
404      rli.emit <span class="hljs-string">'line'</span>, multiline.buffer
405      multiline.buffer = <span class="hljs-string">''</span>
406    <span class="hljs-keyword">else</span>
407      multiline.enabled = <span class="hljs-keyword">not</span> multiline.enabled
408      rli.setPrompt multiline.initialPrompt
409      rli.prompt <span class="hljs-literal">true</span>
410    <span class="hljs-keyword">return</span></pre></div></div>
411            
412        </li>
413        
414        
415        <li id="section-17">
416            <div class="annotation">
417              
418              <div class="pilwrap ">
419                <a class="pilcrow" href="#section-17">&#182;</a>
420              </div>
421              <p>Store and load command history from a file</p>
422
423            </div>
424            
425            <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> -&gt;</span>
426  lastLine = <span class="hljs-literal">null</span>
427  <span class="hljs-keyword">try</span></pre></div></div>
428            
429        </li>
430        
431        
432        <li id="section-18">
433            <div class="annotation">
434              
435              <div class="pilwrap ">
436                <a class="pilcrow" href="#section-18">&#182;</a>
437              </div>
438              <p>Get file info and at most maxSize of command history</p>
439
440            </div>
441            
442            <div class="content"><div class='highlight'><pre>    stat = fs.statSync filename
443    size = Math.min maxSize, stat.size</pre></div></div>
444            
445        </li>
446        
447        
448        <li id="section-19">
449            <div class="annotation">
450              
451              <div class="pilwrap ">
452                <a class="pilcrow" href="#section-19">&#182;</a>
453              </div>
454              <p>Read last <code>size</code> bytes from the file</p>
455
456            </div>
457            
458            <div class="content"><div class='highlight'><pre>    readFd = fs.openSync filename, <span class="hljs-string">'r'</span>
459    buffer = <span class="hljs-keyword">new</span> Buffer(size)
460    fs.readSync readFd, buffer, <span class="hljs-number">0</span>, size, stat.size - size
461    fs.close readFd</pre></div></div>
462            
463        </li>
464        
465        
466        <li id="section-20">
467            <div class="annotation">
468              
469              <div class="pilwrap ">
470                <a class="pilcrow" href="#section-20">&#182;</a>
471              </div>
472              <p>Set the history on the interpreter</p>
473
474            </div>
475            
476            <div class="content"><div class='highlight'><pre>    repl.rli.history = buffer.toString().split(<span class="hljs-string">'\n'</span>).reverse()</pre></div></div>
477            
478        </li>
479        
480        
481        <li id="section-21">
482            <div class="annotation">
483              
484              <div class="pilwrap ">
485                <a class="pilcrow" href="#section-21">&#182;</a>
486              </div>
487              <p>If the history file was truncated we should pop off a potential partial line</p>
488
489            </div>
490            
491            <div class="content"><div class='highlight'><pre>    repl.rli.history.pop() <span class="hljs-keyword">if</span> stat.size &gt; maxSize</pre></div></div>
492            
493        </li>
494        
495        
496        <li id="section-22">
497            <div class="annotation">
498              
499              <div class="pilwrap ">
500                <a class="pilcrow" href="#section-22">&#182;</a>
501              </div>
502              <p>Shift off the final blank newline</p>
503
504            </div>
505            
506            <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>
507    repl.rli.historyIndex = -<span class="hljs-number">1</span>
508    lastLine = repl.rli.history[<span class="hljs-number">0</span>]
509
510  fd = fs.openSync filename, <span class="hljs-string">'a'</span>
511
512  repl.rli.addListener <span class="hljs-string">'line'</span>, <span class="hljs-function"><span class="hljs-params">(code)</span> -&gt;</span>
513    <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>
514            
515        </li>
516        
517        
518        <li id="section-23">
519            <div class="annotation">
520              
521              <div class="pilwrap ">
522                <a class="pilcrow" href="#section-23">&#182;</a>
523              </div>
524              <p>Save the latest command in the file</p>
525
526            </div>
527            
528            <div class="content"><div class='highlight'><pre>      fs.write fd, <span class="hljs-string">"<span class="hljs-subst">#{code}</span>\n"</span>
529      lastLine = code
530
531  repl.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>,<span class="hljs-function"> -&gt;</span> fs.close fd</pre></div></div>
532            
533        </li>
534        
535        
536        <li id="section-24">
537            <div class="annotation">
538              
539              <div class="pilwrap ">
540                <a class="pilcrow" href="#section-24">&#182;</a>
541              </div>
542              <p>Add a command to show the history stack</p>
543
544            </div>
545            
546            <div class="content"><div class='highlight'><pre>  repl.commands[getCommandId(repl, <span class="hljs-string">'history'</span>)] =
547    <span class="hljs-attribute">help</span>: <span class="hljs-string">'Show command history'</span>
548    <span class="hljs-attribute">action</span>:<span class="hljs-function"> -&gt;</span>
549      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>
550      repl.displayPrompt()
551
552<span class="hljs-function"><span class="hljs-title">getCommandId</span> = <span class="hljs-params">(repl, commandName)</span> -&gt;</span></pre></div></div>
553            
554        </li>
555        
556        
557        <li id="section-25">
558            <div class="annotation">
559              
560              <div class="pilwrap ">
561                <a class="pilcrow" href="#section-25">&#182;</a>
562              </div>
563              <p>Node 0.11 changed API, a command such as ‘.help’ is now stored as ‘help’</p>
564
565            </div>
566            
567            <div class="content"><div class='highlight'><pre>  commandsHaveLeadingDot = repl.commands[<span class="hljs-string">'.help'</span>]?
568  <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
569
570<span class="hljs-built_in">module</span>.<span class="hljs-built_in">exports</span> =
571  <span class="hljs-attribute">start</span>: <span class="hljs-function"><span class="hljs-params">(opts = {})</span> -&gt;</span>
572    [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> -&gt;</span> parseInt(n)
573
574    <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 &lt; <span class="hljs-number">8</span>
575      <span class="hljs-built_in">console</span>.warn <span class="hljs-string">"Node 0.8.0+ required for CoffeeScript REPL"</span>
576      process.exit <span class="hljs-number">1</span>
577
578    CoffeeScript.register()
579    process.argv = [<span class="hljs-string">'coffee'</span>].concat process.argv[<span class="hljs-number">2.</span>.]
580    opts = merge replDefaults, opts
581    repl = nodeREPL.start opts
582    runInContext opts.prelude, repl.context, <span class="hljs-string">'prelude'</span> <span class="hljs-keyword">if</span> opts.prelude
583    repl.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>,<span class="hljs-function"> -&gt;</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
584    addMultilineHandler repl
585    addHistory repl, opts.historyFile, opts.historyMaxInputSize <span class="hljs-keyword">if</span> opts.historyFile</pre></div></div>
586            
587        </li>
588        
589        
590        <li id="section-26">
591            <div class="annotation">
592              
593              <div class="pilwrap ">
594                <a class="pilcrow" href="#section-26">&#182;</a>
595              </div>
596              <p>Adapt help inherited from the node REPL</p>
597
598            </div>
599            
600            <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>
601    repl</pre></div></div>
602            
603        </li>
604        
605    </ul>
606  </div>
607</body>
608</html>