/documentation/docs/helpers.html
http://github.com/jashkenas/coffee-script · HTML · 612 lines · 417 code · 195 blank · 0 comment · 0 complexity · 35377504448519f52ecb29dcb4a7ee9e MD5 · raw file
- <!DOCTYPE html>
- <html>
- <head>
- <title>helpers.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>helpers.coffee</h1>
- </div>
- </li>
-
-
-
- <li id="section-1">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-1">¶</a>
- </div>
- <p>This file contains the common helper functions that we’d like to share among
- the <strong>Lexer</strong>, <strong>Rewriter</strong>, and the <strong>Nodes</strong>. Merge objects, flatten
- arrays, count characters, that sort of thing.</p>
- </div>
-
- </li>
-
-
- <li id="section-2">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-2">¶</a>
- </div>
- <p>Peek at the beginning of a given string to see if it matches a sequence.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">starts</span> = <span class="hljs-params">(string, literal, start)</span> -></span>
- literal <span class="hljs-keyword">is</span> string.substr start, literal.length</pre></div></div>
-
- </li>
-
-
- <li id="section-3">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-3">¶</a>
- </div>
- <p>Peek at the end of a given string to see if it matches a sequence.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">ends</span> = <span class="hljs-params">(string, literal, back)</span> -></span>
- len = literal.length
- literal <span class="hljs-keyword">is</span> string.substr string.length - len - (back <span class="hljs-keyword">or</span> <span class="hljs-number">0</span>), len</pre></div></div>
-
- </li>
-
-
- <li id="section-4">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-4">¶</a>
- </div>
- <p>Repeat a string <code>n</code> times.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.repeat = <span class="hljs-function"><span class="hljs-title">repeat</span> = <span class="hljs-params">(str, n)</span> -></span></pre></div></div>
-
- </li>
-
-
- <li id="section-5">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-5">¶</a>
- </div>
- <p>Use clever algorithm to have O(log(n)) string concatenation operations.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> res = <span class="hljs-string">''</span>
- <span class="hljs-keyword">while</span> n > <span class="hljs-number">0</span>
- res += str <span class="hljs-keyword">if</span> n & <span class="hljs-number">1</span>
- n >>>= <span class="hljs-number">1</span>
- str += str
- res</pre></div></div>
-
- </li>
-
-
- <li id="section-6">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-6">¶</a>
- </div>
- <p>Trim out all falsy values from an array.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">compact</span> = <span class="hljs-params">(array)</span> -></span>
- item <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> array <span class="hljs-keyword">when</span> item</pre></div></div>
-
- </li>
-
-
- <li id="section-7">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-7">¶</a>
- </div>
- <p>Count the number of occurrences of a string in a string.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">count</span> = <span class="hljs-params">(string, substr)</span> -></span>
- num = pos = <span class="hljs-number">0</span>
- <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>/<span class="hljs-number">0</span> <span class="hljs-keyword">unless</span> substr.length
- num++ <span class="hljs-keyword">while</span> pos = <span class="hljs-number">1</span> + string.indexOf substr, pos
- num</pre></div></div>
-
- </li>
-
-
- <li id="section-8">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-8">¶</a>
- </div>
- <p>Merge objects, returning a fresh copy with attributes from both sides.
- Used every time <code>Base#compile</code> is called, to allow properties in the
- options hash to propagate down the tree without polluting other branches.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">merge</span> = <span class="hljs-params">(options, overrides)</span> -></span>
- extend (extend {}, options), overrides</pre></div></div>
-
- </li>
-
-
- <li id="section-9">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-9">¶</a>
- </div>
- <p>Extend a source object with the properties of another object (shallow copy).</p>
- </div>
-
- <div class="content"><div class='highlight'><pre>extend = <span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">extend</span> = <span class="hljs-params">(object, properties)</span> -></span>
- <span class="hljs-keyword">for</span> key, val <span class="hljs-keyword">of</span> properties
- object[key] = val
- object</pre></div></div>
-
- </li>
-
-
- <li id="section-10">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-10">¶</a>
- </div>
- <p>Return a flattened version of an array.
- Handy for getting a list of <code>children</code> from the nodes.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.flatten = <span class="hljs-function"><span class="hljs-title">flatten</span> = <span class="hljs-params">(array)</span> -></span>
- flattened = []
- <span class="hljs-keyword">for</span> element <span class="hljs-keyword">in</span> array
- <span class="hljs-keyword">if</span> <span class="hljs-string">'[object Array]'</span> <span class="hljs-keyword">is</span> <span class="hljs-attribute">Object</span>::toString.call element
- flattened = flattened.concat flatten element
- <span class="hljs-keyword">else</span>
- flattened.push element
- flattened</pre></div></div>
-
- </li>
-
-
- <li id="section-11">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-11">¶</a>
- </div>
- <p>Delete a key from an object, returning the value. Useful when a node is
- looking for a particular method in an options hash.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">del</span> = <span class="hljs-params">(obj, key)</span> -></span>
- val = obj[key]
- <span class="hljs-keyword">delete</span> obj[key]
- val</pre></div></div>
-
- </li>
-
-
- <li id="section-12">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-12">¶</a>
- </div>
- <p>Typical Array::some</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.some = <span class="hljs-attribute">Array</span>::some ? <span class="hljs-function"><span class="hljs-params">(fn)</span> -></span>
- <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span> <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> <span class="hljs-keyword">this</span> <span class="hljs-keyword">when</span> fn e
- <span class="hljs-literal">false</span></pre></div></div>
-
- </li>
-
-
- <li id="section-13">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-13">¶</a>
- </div>
- <p>Simple function for inverting Literate CoffeeScript code by putting the
- documentation in comments, producing a string of CoffeeScript code that
- can be compiled “normally”.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">invertLiterate</span> = <span class="hljs-params">(code)</span> -></span>
- maybe_code = <span class="hljs-literal">true</span>
- lines = <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> code.split(<span class="hljs-string">'\n'</span>)
- <span class="hljs-keyword">if</span> maybe_code <span class="hljs-keyword">and</span> <span class="hljs-regexp">/^([ ]{4}|[ ]{0,3}\t)/</span>.test line
- line
- <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> maybe_code = <span class="hljs-regexp">/^\s*$/</span>.test line
- line
- <span class="hljs-keyword">else</span>
- <span class="hljs-string">'# '</span> + line
- lines.join <span class="hljs-string">'\n'</span></pre></div></div>
-
- </li>
-
-
- <li id="section-14">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-14">¶</a>
- </div>
- <p>Merge two jison-style location data objects together.
- If <code>last</code> is not provided, this will simply return <code>first</code>.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">buildLocationData</span> = <span class="hljs-params">(first, last)</span> -></span>
- <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> last
- first
- <span class="hljs-keyword">else</span>
- <span class="hljs-attribute">first_line</span>: first.first_line
- <span class="hljs-attribute">first_column</span>: first.first_column
- <span class="hljs-attribute">last_line</span>: last.last_line
- <span class="hljs-attribute">last_column</span>: last.last_column</pre></div></div>
-
- </li>
-
-
- <li id="section-15">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-15">¶</a>
- </div>
- <p>This returns a function which takes an object as a parameter, and if that
- object is an AST node, updates that object’s locationData.
- The object is returned either way.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">addLocationDataFn</span> = <span class="hljs-params">(first, last)</span> -></span>
- <span class="hljs-function"><span class="hljs-params">(obj)</span> -></span>
- <span class="hljs-keyword">if</span> ((<span class="hljs-keyword">typeof</span> obj) <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span>) <span class="hljs-keyword">and</span> (!!obj[<span class="hljs-string">'updateLocationDataIfMissing'</span>])
- obj.updateLocationDataIfMissing buildLocationData(first, last)
- <span class="hljs-keyword">return</span> obj</pre></div></div>
-
- </li>
-
-
- <li id="section-16">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-16">¶</a>
- </div>
- <p>Convert jison location data to a string.
- <code>obj</code> can be a token, or a locationData.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">locationDataToString</span> = <span class="hljs-params">(obj)</span> -></span>
- <span class="hljs-keyword">if</span> (<span class="hljs-string">"2"</span> <span class="hljs-keyword">of</span> obj) <span class="hljs-keyword">and</span> (<span class="hljs-string">"first_line"</span> <span class="hljs-keyword">of</span> obj[<span class="hljs-number">2</span>]) <span class="hljs-keyword">then</span> locationData = obj[<span class="hljs-number">2</span>]
- <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-string">"first_line"</span> <span class="hljs-keyword">of</span> obj <span class="hljs-keyword">then</span> locationData = obj
- <span class="hljs-keyword">if</span> locationData
- <span class="hljs-string">"<span class="hljs-subst">#{locationData.first_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{locationData.first_column + <span class="hljs-number">1</span>}</span>-"</span> +
- <span class="hljs-string">"<span class="hljs-subst">#{locationData.last_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{locationData.last_column + <span class="hljs-number">1</span>}</span>"</span>
- <span class="hljs-keyword">else</span>
- <span class="hljs-string">"No location data"</span></pre></div></div>
-
- </li>
-
-
- <li id="section-17">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-17">¶</a>
- </div>
- <p>A <code>.coffee.md</code> compatible version of <code>basename</code>, that returns the file sans-extension.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">baseFileName</span> = <span class="hljs-params">(file, stripExt = <span class="hljs-literal">no</span>, useWinPathSep = <span class="hljs-literal">no</span>)</span> -></span>
- pathSep = <span class="hljs-keyword">if</span> useWinPathSep <span class="hljs-keyword">then</span> <span class="hljs-regexp">/\\|\//</span> <span class="hljs-keyword">else</span> <span class="hljs-regexp">/\/</span>/
- parts = file.split(pathSep)
- file = parts[parts.length - <span class="hljs-number">1</span>]
- <span class="hljs-keyword">return</span> file <span class="hljs-keyword">unless</span> stripExt <span class="hljs-keyword">and</span> file.indexOf(<span class="hljs-string">'.'</span>) >= <span class="hljs-number">0</span>
- parts = file.split(<span class="hljs-string">'.'</span>)
- parts.pop()
- parts.pop() <span class="hljs-keyword">if</span> parts[parts.length - <span class="hljs-number">1</span>] <span class="hljs-keyword">is</span> <span class="hljs-string">'coffee'</span> <span class="hljs-keyword">and</span> parts.length > <span class="hljs-number">1</span>
- parts.join(<span class="hljs-string">'.'</span>)</pre></div></div>
-
- </li>
-
-
- <li id="section-18">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-18">¶</a>
- </div>
- <p>Determine if a filename represents a CoffeeScript file.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">isCoffee</span> = <span class="hljs-params">(file)</span> -></span> <span class="hljs-regexp">/\.((lit)?coffee|coffee\.md)$/</span>.test file</pre></div></div>
-
- </li>
-
-
- <li id="section-19">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-19">¶</a>
- </div>
- <p>Determine if a filename represents a Literate CoffeeScript file.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">isLiterate</span> = <span class="hljs-params">(file)</span> -></span> <span class="hljs-regexp">/\.(litcoffee|coffee\.md)$/</span>.test file</pre></div></div>
-
- </li>
-
-
- <li id="section-20">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-20">¶</a>
- </div>
- <p>Throws a SyntaxError from a given location.
- The error’s <code>toString</code> will return an error message following the “standard”
- format <filename>:<line>:<col>: <message> plus the line with the error and a
- marker showing where the error is.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">throwSyntaxError</span> = <span class="hljs-params">(message, location)</span> -></span>
- error = <span class="hljs-keyword">new</span> SyntaxError message
- error.location = location
- error.toString = syntaxErrorToString</pre></div></div>
-
- </li>
-
-
- <li id="section-21">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-21">¶</a>
- </div>
- <p>Instead of showing the compiler’s stacktrace, show our custom error message
- (this is useful when the error bubbles up in Node.js applications that
- compile CoffeeScript for example).</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> error.stack = error.toString()
- <span class="hljs-keyword">throw</span> error</pre></div></div>
-
- </li>
-
-
- <li id="section-22">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-22">¶</a>
- </div>
- <p>Update a compiler SyntaxError with source code information if it didn’t have
- it already.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">updateSyntaxError</span> = <span class="hljs-params">(error, code, filename)</span> -></span></pre></div></div>
-
- </li>
-
-
- <li id="section-23">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-23">¶</a>
- </div>
- <p>Avoid screwing up the <code>stack</code> property of other errors (i.e. possible bugs).</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> error.toString <span class="hljs-keyword">is</span> syntaxErrorToString
- error.code <span class="hljs-keyword">or</span>= code
- error.filename <span class="hljs-keyword">or</span>= filename
- error.stack = error.toString()
- error
- <span class="hljs-function"><span class="hljs-title">syntaxErrorToString</span> = -></span>
- <span class="hljs-keyword">return</span> <span class="hljs-attribute">Error</span>::toString.call @ <span class="hljs-keyword">unless</span> <span class="hljs-property">@code</span> <span class="hljs-keyword">and</span> <span class="hljs-property">@location</span>
- {first_line, first_column, last_line, last_column} = <span class="hljs-property">@location</span>
- last_line ?= first_line
- last_column ?= first_column
- filename = <span class="hljs-property">@filename</span> <span class="hljs-keyword">or</span> <span class="hljs-string">'[stdin]'</span>
- codeLine = <span class="hljs-property">@code</span>.split(<span class="hljs-string">'\n'</span>)[first_line]
- start = first_column</pre></div></div>
-
- </li>
-
-
- <li id="section-24">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-24">¶</a>
- </div>
- <p>Show only the first line on multi-line errors.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> end = <span class="hljs-keyword">if</span> first_line <span class="hljs-keyword">is</span> last_line <span class="hljs-keyword">then</span> last_column + <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> codeLine.length
- marker = codeLine[...start].replace(<span class="hljs-regexp">/[^\s]/g</span>, <span class="hljs-string">' '</span>) + repeat(<span class="hljs-string">'^'</span>, end - start)</pre></div></div>
-
- </li>
-
-
- <li id="section-25">
- <div class="annotation">
-
- <div class="pilwrap ">
- <a class="pilcrow" href="#section-25">¶</a>
- </div>
- <p>Check to see if we’re running on a color-enabled TTY.</p>
- </div>
-
- <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> process?
- colorsEnabled = process.stdout?.isTTY <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> process.env?.NODE_DISABLE_COLORS
- <span class="hljs-keyword">if</span> <span class="hljs-property">@colorful</span> ? colorsEnabled
- <span class="hljs-function"><span class="hljs-title">colorize</span> = <span class="hljs-params">(str)</span> -></span> <span class="hljs-string">"\x1B[1;31m<span class="hljs-subst">#{str}</span>\x1B[0m"</span>
- codeLine = codeLine[...start] + colorize(codeLine[start...end]) + codeLine[end..]
- marker = colorize marker
- <span class="hljs-string">"""
- <span class="hljs-subst">#{filename}</span>:<span class="hljs-subst">#{first_line + <span class="hljs-number">1</span>}</span>:<span class="hljs-subst">#{first_column + <span class="hljs-number">1</span>}</span>: error: <span class="hljs-subst">#{<span class="hljs-property">@message</span>}</span>
- <span class="hljs-subst">#{codeLine}</span>
- <span class="hljs-subst">#{marker}</span>
- """</span>
- <span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">nameWhitespaceCharacter</span> = <span class="hljs-params">(string)</span> -></span>
- <span class="hljs-keyword">switch</span> string
- <span class="hljs-keyword">when</span> <span class="hljs-string">' '</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'space'</span>
- <span class="hljs-keyword">when</span> <span class="hljs-string">'\n'</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'newline'</span>
- <span class="hljs-keyword">when</span> <span class="hljs-string">'\r'</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'carriage return'</span>
- <span class="hljs-keyword">when</span> <span class="hljs-string">'\t'</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'tab'</span>
- <span class="hljs-keyword">else</span> string</pre></div></div>
-
- </li>
-
- </ul>
- </div>
- </body>
- </html>