mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
779 lines
37 KiB
HTML
779 lines
37 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<html>
|
|
<head>
|
|
<title>command.coffee</title>
|
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
|
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
|
|
<link rel="stylesheet" media="all" href="docco.css" />
|
|
</head>
|
|
<body>
|
|
<div id="container">
|
|
<div id="background"></div>
|
|
|
|
<ul id="jump_to">
|
|
<li>
|
|
<a class="large" href="javascript:void(0);">Jump To …</a>
|
|
<a class="small" href="javascript:void(0);">+</a>
|
|
<div id="jump_wrapper">
|
|
<div id="jump_page">
|
|
|
|
|
|
<a class="source" href="browser.html">
|
|
browser.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="cake.html">
|
|
cake.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="coffee-script.html">
|
|
coffee-script.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="command.html">
|
|
command.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="grammar.html">
|
|
grammar.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="helpers.html">
|
|
helpers.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="index.html">
|
|
index.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="lexer.html">
|
|
lexer.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="nodes.html">
|
|
nodes.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="optparse.html">
|
|
optparse.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="repl.html">
|
|
repl.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="rewriter.html">
|
|
rewriter.coffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="scope.html">
|
|
scope.litcoffee
|
|
</a>
|
|
|
|
|
|
<a class="source" href="sourcemap.html">
|
|
sourcemap.litcoffee
|
|
</a>
|
|
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
|
|
<ul class="sections">
|
|
|
|
<li id="title">
|
|
<div class="annotation">
|
|
<h1>command.coffee</h1>
|
|
</div>
|
|
</li>
|
|
|
|
|
|
|
|
<li id="section-1">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-1">¶</a>
|
|
</div>
|
|
<p>The <code>coffee</code> utility. Handles command-line compilation of CoffeeScript
|
|
into various forms: saved into <code>.js</code> files or printed to stdout
|
|
or recompiled every time the source is saved,
|
|
printed as a token stream or as the syntax tree, or launch an
|
|
interactive REPL.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-2">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-2">¶</a>
|
|
</div>
|
|
<p>External dependencies.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre>fs = require <span class="string">'fs'</span>
|
|
path = require <span class="string">'path'</span>
|
|
helpers = require <span class="string">'./helpers'</span>
|
|
optparse = require <span class="string">'./optparse'</span>
|
|
CoffeeScript = require <span class="string">'./coffee-script'</span>
|
|
{spawn, exec} = require <span class="string">'child_process'</span>
|
|
{EventEmitter} = require <span class="string">'events'</span>
|
|
|
|
exists = fs.exists <span class="keyword">or</span> path.exists
|
|
useWinPathSep = path.sep <span class="keyword">is</span> <span class="string">'\\'</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-3">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-3">¶</a>
|
|
</div>
|
|
<p>Allow CoffeeScript to emit Node.js events.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre>helpers.extend CoffeeScript, <span class="keyword">new</span> EventEmitter
|
|
|
|
<span class="function"><span class="title">printLine</span></span> = (line) -> process.stdout.write line + <span class="string">'\n'</span>
|
|
<span class="function"><span class="title">printWarn</span></span> = (line) -> process.stderr.write line + <span class="string">'\n'</span>
|
|
|
|
<span class="function"><span class="title">hidden</span></span> = (file) -> <span class="regexp">/^\.|~$/</span>.test file</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-4">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-4">¶</a>
|
|
</div>
|
|
<p>The help banner that is printed when <code>coffee</code> is called without arguments.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre>BANNER = '''
|
|
Usage: coffee [options] path/to/script.coffee -- [args]
|
|
|
|
If called without options, `coffee` will run your script.
|
|
'''</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-5">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-5">¶</a>
|
|
</div>
|
|
<p>The list of all the valid option flags that <code>coffee</code> knows how to handle.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre>SWITCHES = [
|
|
[<span class="string">'-b'</span>, <span class="string">'--bare'</span>, <span class="string">'compile without a top-level function wrapper'</span>]
|
|
[<span class="string">'-c'</span>, <span class="string">'--compile'</span>, <span class="string">'compile to JavaScript and save as .js files'</span>]
|
|
[<span class="string">'-e'</span>, <span class="string">'--eval'</span>, <span class="string">'pass a string from the command line as input'</span>]
|
|
[<span class="string">'-h'</span>, <span class="string">'--help'</span>, <span class="string">'display this help message'</span>]
|
|
[<span class="string">'-i'</span>, <span class="string">'--interactive'</span>, <span class="string">'run an interactive CoffeeScript REPL'</span>]
|
|
[<span class="string">'-j'</span>, <span class="string">'--join [FILE]'</span>, <span class="string">'concatenate the source CoffeeScript before compiling'</span>]
|
|
[<span class="string">'-m'</span>, <span class="string">'--map'</span>, <span class="string">'generate source map and save as .map files'</span>]
|
|
[<span class="string">'-n'</span>, <span class="string">'--nodes'</span>, <span class="string">'print out the parse tree that the parser produces'</span>]
|
|
[ <span class="string">'--nodejs [ARGS]'</span>, <span class="string">'pass options directly to the "node" binary'</span>]
|
|
[<span class="string">'-o'</span>, <span class="string">'--output [DIR]'</span>, <span class="string">'set the output directory for compiled JavaScript'</span>]
|
|
[<span class="string">'-p'</span>, <span class="string">'--print'</span>, <span class="string">'print out the compiled JavaScript'</span>]
|
|
[<span class="string">'-s'</span>, <span class="string">'--stdio'</span>, <span class="string">'listen for and compile scripts over stdio'</span>]
|
|
[<span class="string">'-l'</span>, <span class="string">'--literate'</span>, <span class="string">'treat stdio as literate style coffee-script'</span>]
|
|
[<span class="string">'-t'</span>, <span class="string">'--tokens'</span>, <span class="string">'print out the tokens that the lexer/rewriter produce'</span>]
|
|
[<span class="string">'-v'</span>, <span class="string">'--version'</span>, <span class="string">'display the version number'</span>]
|
|
[<span class="string">'-w'</span>, <span class="string">'--watch'</span>, <span class="string">'watch scripts for changes and rerun commands'</span>]
|
|
]</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-6">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-6">¶</a>
|
|
</div>
|
|
<p>Top-level objects shared by all the functions.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre>opts = {}
|
|
sources = []
|
|
sourceCode = []
|
|
notSources = {}
|
|
watchers = {}
|
|
optionParser = <span class="literal">null</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-7">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-7">¶</a>
|
|
</div>
|
|
<p>Run <code>coffee</code> by parsing passed options and determining what action to take.
|
|
Many flags cause us to divert before compiling anything. Flags passed after
|
|
<code>--</code> will be passed verbatim to your script as arguments in <code>process.argv</code>
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre>exports.<span class="function"><span class="title">run</span></span> = ->
|
|
parseOptions()
|
|
<span class="keyword">return</span> forkNode() <span class="keyword">if</span> opts.nodejs
|
|
<span class="keyword">return</span> usage() <span class="keyword">if</span> opts.help
|
|
<span class="keyword">return</span> version() <span class="keyword">if</span> opts.version
|
|
<span class="keyword">return</span> require(<span class="string">'./repl'</span>).start() <span class="keyword">if</span> opts.interactive
|
|
<span class="keyword">if</span> opts.watch <span class="keyword">and</span> <span class="keyword">not</span> fs.watch
|
|
<span class="keyword">return</span> printWarn <span class="string">"The --watch feature depends on Node v0.6.0+. You are running <span class="subst">#{process.version}</span>."</span>
|
|
<span class="keyword">return</span> compileStdio() <span class="keyword">if</span> opts.stdio
|
|
<span class="keyword">return</span> compileScript <span class="literal">null</span>, sources[<span class="number">0</span>] <span class="keyword">if</span> opts.eval
|
|
<span class="keyword">return</span> require(<span class="string">'./repl'</span>).start() <span class="keyword">unless</span> sources.length
|
|
literals = <span class="keyword">if</span> opts.run <span class="keyword">then</span> sources.splice <span class="number">1</span> <span class="keyword">else</span> []
|
|
process.argv = process.argv[<span class="number">0.</span><span class="number">.1</span>].concat literals
|
|
process.argv[<span class="number">0</span>] = <span class="string">'coffee'</span>
|
|
<span class="keyword">for</span> source <span class="keyword">in</span> sources
|
|
compilePath source, <span class="literal">yes</span>, path.normalize source</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-8">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-8">¶</a>
|
|
</div>
|
|
<p>Compile a path, which could be a script or a directory. If a directory
|
|
is passed, recursively compile all '.coffee', '.litcoffee', and '.coffee.md'
|
|
extension source files in it and all subdirectories.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">compilePath</span></span> = (source, topLevel, base) ->
|
|
fs.stat source, (err, stats) ->
|
|
<span class="keyword">throw</span> err <span class="keyword">if</span> err <span class="keyword">and</span> err.code <span class="keyword">isnt</span> <span class="string">'ENOENT'</span>
|
|
<span class="keyword">if</span> err?.code <span class="keyword">is</span> <span class="string">'ENOENT'</span>
|
|
console.error <span class="string">"File not found: <span class="subst">#{source}</span>"</span>
|
|
process.exit <span class="number">1</span>
|
|
<span class="keyword">if</span> stats.isDirectory() <span class="keyword">and</span> path.dirname(source) <span class="keyword">isnt</span> <span class="string">'node_modules'</span>
|
|
watchDir source, base <span class="keyword">if</span> opts.watch
|
|
fs.readdir source, (err, files) ->
|
|
<span class="keyword">throw</span> err <span class="keyword">if</span> err <span class="keyword">and</span> err.code <span class="keyword">isnt</span> <span class="string">'ENOENT'</span>
|
|
<span class="keyword">return</span> <span class="keyword">if</span> err?.code <span class="keyword">is</span> <span class="string">'ENOENT'</span>
|
|
index = sources.indexOf source
|
|
files = files.filter (file) -> <span class="keyword">not</span> hidden file
|
|
sources[index..index] = (path.join source, file <span class="keyword">for</span> file <span class="keyword">in</span> files)
|
|
sourceCode[index..index] = files.map -> <span class="literal">null</span>
|
|
files.forEach (file) ->
|
|
compilePath (path.join source, file), <span class="literal">no</span>, base
|
|
<span class="keyword">else</span> <span class="keyword">if</span> topLevel <span class="keyword">or</span> helpers.isCoffee source
|
|
watch source, base <span class="keyword">if</span> opts.watch
|
|
fs.readFile source, (err, code) ->
|
|
<span class="keyword">throw</span> err <span class="keyword">if</span> err <span class="keyword">and</span> err.code <span class="keyword">isnt</span> <span class="string">'ENOENT'</span>
|
|
<span class="keyword">return</span> <span class="keyword">if</span> err?.code <span class="keyword">is</span> <span class="string">'ENOENT'</span>
|
|
compileScript(source, code.toString(), base)
|
|
<span class="keyword">else</span>
|
|
notSources[source] = <span class="literal">yes</span>
|
|
removeSource source, base</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-9">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-9">¶</a>
|
|
</div>
|
|
<p>Compile a single source script, containing the given code, according to the
|
|
requested options. If evaluating the script directly sets <code>__filename</code>,
|
|
<code>__dirname</code> and <code>module.filename</code> to be correct relative to the script's path.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">compileScript</span></span> = (file, input, base=<span class="literal">null</span>) ->
|
|
o = opts
|
|
options = compileOptions file, base
|
|
<span class="keyword">try</span>
|
|
t = task = {file, input, options}
|
|
CoffeeScript.emit <span class="string">'compile'</span>, task
|
|
<span class="keyword">if</span> o.tokens <span class="keyword">then</span> printTokens CoffeeScript.tokens t.input, t.options
|
|
<span class="keyword">else</span> <span class="keyword">if</span> o.nodes <span class="keyword">then</span> printLine CoffeeScript.nodes(t.input, t.options).toString().trim()
|
|
<span class="keyword">else</span> <span class="keyword">if</span> o.run <span class="keyword">then</span> CoffeeScript.run t.input, t.options
|
|
<span class="keyword">else</span> <span class="keyword">if</span> o.join <span class="keyword">and</span> t.file <span class="keyword">isnt</span> o.join
|
|
t.input = helpers.invertLiterate t.input <span class="keyword">if</span> helpers.isLiterate file
|
|
sourceCode[sources.indexOf(t.file)] = t.input
|
|
compileJoin()
|
|
<span class="keyword">else</span>
|
|
compiled = CoffeeScript.compile t.input, t.options
|
|
t.output = compiled
|
|
<span class="keyword">if</span> o.map
|
|
t.output = compiled.js
|
|
t.sourceMap = compiled.v3SourceMap
|
|
|
|
CoffeeScript.emit <span class="string">'success'</span>, task
|
|
<span class="keyword">if</span> o.print
|
|
printLine t.output.trim()
|
|
<span class="keyword">else</span> <span class="keyword">if</span> o.compile <span class="keyword">or</span> o.map
|
|
writeJs base, t.file, t.output, options.jsPath, t.sourceMap
|
|
<span class="keyword">catch</span> err
|
|
CoffeeScript.emit <span class="string">'failure'</span>, err, task
|
|
<span class="keyword">return</span> <span class="keyword">if</span> CoffeeScript.listeners(<span class="string">'failure'</span>).length
|
|
useColors = process.stdout.isTTY <span class="keyword">and</span> <span class="keyword">not</span> process.env.NODE_DISABLE_COLORS
|
|
message = helpers.prettyErrorMessage err, file <span class="keyword">or</span> <span class="string">'[stdin]'</span>, input, useColors
|
|
<span class="keyword">if</span> o.watch
|
|
printLine message + <span class="string">'\x07'</span>
|
|
<span class="keyword">else</span>
|
|
printWarn message
|
|
process.exit <span class="number">1</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-10">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-10">¶</a>
|
|
</div>
|
|
<p>Attach the appropriate listeners to compile scripts incoming over <strong>stdin</strong>,
|
|
and write them back to <strong>stdout</strong>.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">compileStdio</span></span> = ->
|
|
code = <span class="string">''</span>
|
|
stdin = process.openStdin()
|
|
stdin.<span class="literal">on</span> <span class="string">'data'</span>, (buffer) ->
|
|
code += buffer.toString() <span class="keyword">if</span> buffer
|
|
stdin.<span class="literal">on</span> <span class="string">'end'</span>, ->
|
|
compileScript <span class="literal">null</span>, code</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-11">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-11">¶</a>
|
|
</div>
|
|
<p>If all of the source files are done being read, concatenate and compile
|
|
them together.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre>joinTimeout = <span class="literal">null</span>
|
|
<span class="function"><span class="title">compileJoin</span></span> = ->
|
|
<span class="keyword">return</span> <span class="keyword">unless</span> opts.join
|
|
<span class="keyword">unless</span> sourceCode.some((code) -> code <span class="keyword">is</span> <span class="literal">null</span>)
|
|
clearTimeout joinTimeout
|
|
joinTimeout = wait <span class="number">100</span>, ->
|
|
compileScript opts.join, sourceCode.join(<span class="string">'\n'</span>), opts.join</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-12">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-12">¶</a>
|
|
</div>
|
|
<p>Watch a source CoffeeScript file using <code>fs.watch</code>, recompiling it every
|
|
time the file is updated. May be used in combination with other options,
|
|
such as <code>--print</code>.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">watch</span></span> = (source, base) ->
|
|
|
|
prevStats = <span class="literal">null</span>
|
|
compileTimeout = <span class="literal">null</span>
|
|
|
|
<span class="function"><span class="title">watchErr</span></span> = (e) ->
|
|
<span class="keyword">if</span> e.code <span class="keyword">is</span> <span class="string">'ENOENT'</span>
|
|
<span class="keyword">return</span> <span class="keyword">if</span> sources.indexOf(source) <span class="keyword">is</span> -<span class="number">1</span>
|
|
<span class="keyword">try</span>
|
|
rewatch()
|
|
compile()
|
|
<span class="keyword">catch</span> e
|
|
removeSource source, base, <span class="literal">yes</span>
|
|
compileJoin()
|
|
<span class="keyword">else</span> <span class="keyword">throw</span> e
|
|
|
|
<span class="function"><span class="title">compile</span></span> = ->
|
|
clearTimeout compileTimeout
|
|
compileTimeout = wait <span class="number">25</span>, ->
|
|
fs.stat source, (err, stats) ->
|
|
<span class="keyword">return</span> watchErr err <span class="keyword">if</span> err
|
|
<span class="keyword">return</span> rewatch() <span class="keyword">if</span> prevStats <span class="keyword">and</span> stats.size <span class="keyword">is</span> prevStats.size <span class="keyword">and</span>
|
|
stats.mtime.getTime() <span class="keyword">is</span> prevStats.mtime.getTime()
|
|
prevStats = stats
|
|
fs.readFile source, (err, code) ->
|
|
<span class="keyword">return</span> watchErr err <span class="keyword">if</span> err
|
|
compileScript(source, code.toString(), base)
|
|
rewatch()
|
|
|
|
<span class="keyword">try</span>
|
|
watcher = fs.watch source, compile
|
|
<span class="keyword">catch</span> e
|
|
watchErr e
|
|
|
|
<span class="function"><span class="title">rewatch</span></span> = ->
|
|
watcher?.close()
|
|
watcher = fs.watch source, compile</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-13">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-13">¶</a>
|
|
</div>
|
|
<p>Watch a directory of files for new additions.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">watchDir</span></span> = (source, base) ->
|
|
readdirTimeout = <span class="literal">null</span>
|
|
<span class="keyword">try</span>
|
|
watcher = fs.watch source, ->
|
|
clearTimeout readdirTimeout
|
|
readdirTimeout = wait <span class="number">25</span>, ->
|
|
fs.readdir source, (err, files) ->
|
|
<span class="keyword">if</span> err
|
|
<span class="keyword">throw</span> err <span class="keyword">unless</span> err.code <span class="keyword">is</span> <span class="string">'ENOENT'</span>
|
|
watcher.close()
|
|
<span class="keyword">return</span> unwatchDir source, base
|
|
<span class="keyword">for</span> file <span class="keyword">in</span> files <span class="keyword">when</span> <span class="keyword">not</span> hidden(file) <span class="keyword">and</span> <span class="keyword">not</span> notSources[file]
|
|
file = path.join source, file
|
|
<span class="keyword">continue</span> <span class="keyword">if</span> sources.some (s) -> s.indexOf(file) >= <span class="number">0</span>
|
|
sources.push file
|
|
sourceCode.push <span class="literal">null</span>
|
|
compilePath file, <span class="literal">no</span>, base
|
|
<span class="keyword">catch</span> e
|
|
<span class="keyword">throw</span> e <span class="keyword">unless</span> e.code <span class="keyword">is</span> <span class="string">'ENOENT'</span>
|
|
|
|
<span class="function"><span class="title">unwatchDir</span></span> = (source, base) ->
|
|
prevSources = sources[..]
|
|
toRemove = (file <span class="keyword">for</span> file <span class="keyword">in</span> sources <span class="keyword">when</span> file.indexOf(source) >= <span class="number">0</span>)
|
|
removeSource file, base, <span class="literal">yes</span> <span class="keyword">for</span> file <span class="keyword">in</span> toRemove
|
|
<span class="keyword">return</span> <span class="keyword">unless</span> sources.some (s, i) -> prevSources[i] <span class="keyword">isnt</span> s
|
|
compileJoin()</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-14">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-14">¶</a>
|
|
</div>
|
|
<p>Remove a file from our source list, and source code cache. Optionally remove
|
|
the compiled JS version as well.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">removeSource</span></span> = (source, base, removeJs) ->
|
|
index = sources.indexOf source
|
|
sources.splice index, <span class="number">1</span>
|
|
sourceCode.splice index, <span class="number">1</span>
|
|
<span class="keyword">if</span> removeJs <span class="keyword">and</span> <span class="keyword">not</span> opts.join
|
|
jsPath = outputPath source, base
|
|
exists jsPath, (itExists) ->
|
|
<span class="keyword">if</span> itExists
|
|
fs.unlink jsPath, (err) ->
|
|
<span class="keyword">throw</span> err <span class="keyword">if</span> err <span class="keyword">and</span> err.code <span class="keyword">isnt</span> <span class="string">'ENOENT'</span>
|
|
timeLog <span class="string">"removed <span class="subst">#{source}</span>"</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-15">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-15">¶</a>
|
|
</div>
|
|
<p>Get the corresponding output JavaScript path for a source file.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">outputPath</span></span> = (source, base, extension=<span class="string">".js"</span>) ->
|
|
basename = helpers.baseFileName source, <span class="literal">yes</span>, useWinPathSep
|
|
srcDir = path.dirname source
|
|
baseDir = <span class="keyword">if</span> base <span class="keyword">is</span> <span class="string">'.'</span> <span class="keyword">then</span> srcDir <span class="keyword">else</span> srcDir.substring base.length
|
|
dir = <span class="keyword">if</span> opts.output <span class="keyword">then</span> path.join opts.output, baseDir <span class="keyword">else</span> srcDir
|
|
path.join dir, basename + extension</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-16">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-16">¶</a>
|
|
</div>
|
|
<p>Write out a JavaScript source file with the compiled code. By default, files
|
|
are written out in <code>cwd</code> as <code>.js</code> files with the same name, but the output
|
|
directory can be customized with <code>--output</code>.
|
|
|
|
</p>
|
|
<p>If <code>generatedSourceMap</code> is provided, this will write a <code>.map</code> file into the
|
|
same directory as the <code>.js</code> file.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">writeJs</span></span> = (base, sourcePath, js, jsPath, generatedSourceMap = <span class="literal">null</span>) ->
|
|
sourceMapPath = outputPath sourcePath, base, <span class="string">".map"</span>
|
|
jsDir = path.dirname jsPath
|
|
<span class="function"><span class="title">compile</span></span> = ->
|
|
<span class="keyword">if</span> opts.compile
|
|
js = <span class="string">' '</span> <span class="keyword">if</span> js.length <= <span class="number">0</span>
|
|
<span class="keyword">if</span> generatedSourceMap <span class="keyword">then</span> js = <span class="string">"<span class="subst">#{js}</span>\n/*\n//@ sourceMappingURL=<span class="subst">#{helpers.baseFileName sourceMapPath, <span class="literal">no</span>, useWinPathSep}</span>\n*/\n"</span>
|
|
fs.writeFile jsPath, js, (err) ->
|
|
<span class="keyword">if</span> err
|
|
printLine err.message
|
|
<span class="keyword">else</span> <span class="keyword">if</span> opts.compile <span class="keyword">and</span> opts.watch
|
|
timeLog <span class="string">"compiled <span class="subst">#{sourcePath}</span>"</span>
|
|
<span class="keyword">if</span> generatedSourceMap
|
|
fs.writeFile sourceMapPath, generatedSourceMap, (err) ->
|
|
<span class="keyword">if</span> err
|
|
printLine <span class="string">"Could not write source map: <span class="subst">#{err.message}</span>"</span>
|
|
exists jsDir, (itExists) ->
|
|
<span class="keyword">if</span> itExists <span class="keyword">then</span> compile() <span class="keyword">else</span> exec <span class="string">"mkdir -p <span class="subst">#{jsDir}</span>"</span>, compile</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-17">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-17">¶</a>
|
|
</div>
|
|
<p>Convenience for cleaner setTimeouts.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">wait</span></span> = (milliseconds, func) -> setTimeout func, milliseconds</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-18">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-18">¶</a>
|
|
</div>
|
|
<p>When watching scripts, it's useful to log changes with the timestamp.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">timeLog</span></span> = (message) ->
|
|
console.log <span class="string">"<span class="subst">#{(<span class="keyword">new</span> Date).toLocaleTimeString()}</span> - <span class="subst">#{message}</span>"</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-19">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-19">¶</a>
|
|
</div>
|
|
<p>Pretty-print a stream of tokens, sans location data.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">printTokens</span></span> = (tokens) ->
|
|
strings = <span class="keyword">for</span> token <span class="keyword">in</span> tokens
|
|
tag = token[<span class="number">0</span>]
|
|
value = token[<span class="number">1</span>].toString().replace(<span class="regexp">/\n/</span>, <span class="string">'\\n'</span>)
|
|
<span class="string">"[<span class="subst">#{tag}</span> <span class="subst">#{value}</span>]"</span>
|
|
printLine strings.join(<span class="string">' '</span>)</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-20">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-20">¶</a>
|
|
</div>
|
|
<p>Use the <a href="optparse.html">OptionParser module</a> to extract all options from
|
|
<code>process.argv</code> that are specified in <code>SWITCHES</code>.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">parseOptions</span></span> = ->
|
|
optionParser = <span class="keyword">new</span> optparse.OptionParser SWITCHES, BANNER
|
|
o = opts = optionParser.parse process.argv[<span class="number">2.</span>.]
|
|
o.compile <span class="keyword">or</span>= !!o.output
|
|
o.run = <span class="keyword">not</span> (o.compile <span class="keyword">or</span> o.print <span class="keyword">or</span> o.map)
|
|
o.print = !! (o.print <span class="keyword">or</span> (o.eval <span class="keyword">or</span> o.stdio <span class="keyword">and</span> o.compile))
|
|
sources = o.arguments
|
|
sourceCode[i] = <span class="literal">null</span> <span class="keyword">for</span> source, i <span class="keyword">in</span> sources
|
|
<span class="keyword">return</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-21">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-21">¶</a>
|
|
</div>
|
|
<p>The compile-time options to pass to the CoffeeScript compiler.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">compileOptions</span></span> = (filename, base) ->
|
|
answer = {
|
|
filename
|
|
literate: opts.literate <span class="keyword">or</span> helpers.isLiterate(filename)
|
|
bare: opts.bare
|
|
header: opts.compile
|
|
sourceMap: opts.map
|
|
}
|
|
<span class="keyword">if</span> filename
|
|
<span class="keyword">if</span> base
|
|
cwd = process.cwd()
|
|
jsPath = outputPath filename, base
|
|
jsDir = path.dirname jsPath
|
|
answer = helpers.merge answer, {
|
|
jsPath
|
|
sourceRoot: path.relative jsDir, cwd
|
|
sourceFiles: [path.relative cwd, filename]
|
|
generatedFile: helpers.baseFileName(jsPath, <span class="literal">no</span>, useWinPathSep)
|
|
}
|
|
<span class="keyword">else</span>
|
|
answer = helpers.merge answer,
|
|
sourceRoot: <span class="string">""</span>
|
|
sourceFiles: [helpers.baseFileName filename, <span class="literal">no</span>, useWinPathSep]
|
|
generatedFile: helpers.baseFileName(filename, <span class="literal">yes</span>, useWinPathSep) + <span class="string">".js"</span>
|
|
answer</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-22">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-22">¶</a>
|
|
</div>
|
|
<p>Start up a new Node.js instance with the arguments in <code>--nodejs</code> passed to
|
|
the <code>node</code> binary, preserving the other options.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">forkNode</span></span> = ->
|
|
nodeArgs = opts.nodejs.split <span class="regexp">/\s+/</span>
|
|
args = process.argv[<span class="number">1.</span>.]
|
|
args.splice args.indexOf(<span class="string">'--nodejs'</span>), <span class="number">2</span>
|
|
spawn process.execPath, nodeArgs.concat(args),
|
|
cwd: process.cwd()
|
|
env: process.env
|
|
customFds: [<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>]</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-23">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-23">¶</a>
|
|
</div>
|
|
<p>Print the <code>--help</code> usage message and exit. Deprecated switches are not
|
|
shown.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">usage</span></span> = ->
|
|
printLine (<span class="keyword">new</span> optparse.OptionParser SWITCHES, BANNER).help()</pre></div></div>
|
|
|
|
</li>
|
|
|
|
|
|
<li id="section-24">
|
|
<div class="annotation">
|
|
|
|
<div class="pilwrap ">
|
|
<a class="pilcrow" href="#section-24">¶</a>
|
|
</div>
|
|
<p>Print the <code>--version</code> message and exit.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div class="content"><div class='highlight'><pre><span class="function"><span class="title">version</span></span> = ->
|
|
printLine <span class="string">"CoffeeScript version <span class="subst">#{CoffeeScript.VERSION}</span>"</span></pre></div></div>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
</div>
|
|
</body>
|
|
</html>
|