<!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_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>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 = <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> helpers = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span> optparse = <span class="hljs-built_in">require</span> <span class="hljs-string">'./optparse'</span> CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./coffee-script'</span> {spawn, exec} = <span class="hljs-built_in">require</span> <span class="hljs-string">'child_process'</span> {EventEmitter} = <span class="hljs-built_in">require</span> <span class="hljs-string">'events'</span> useWinPathSep = path.sep <span class="hljs-keyword">is</span> <span class="hljs-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="hljs-keyword">new</span> EventEmitter <span class="hljs-function"><span class="hljs-title">printLine</span> = <span class="hljs-params">(line)</span> -></span> process.stdout.write line + <span class="hljs-string">'\n'</span> <span class="hljs-function"><span class="hljs-title">printWarn</span> = <span class="hljs-params">(line)</span> -></span> process.stderr.write line + <span class="hljs-string">'\n'</span> <span class="hljs-function"><span class="hljs-title">hidden</span> = <span class="hljs-params">(file)</span> -></span> <span class="hljs-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 in conjunction with <code>-h</code>/<code>--help</code>.</p> </div> <div class="content"><div class='highlight'><pre>BANNER = <span class="hljs-string">''' Usage: coffee [options] path/to/script.coffee -- [args] If called without options, `coffee` will run your script. '''</span></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="hljs-string">'-b'</span>, <span class="hljs-string">'--bare'</span>, <span class="hljs-string">'compile without a top-level function wrapper'</span>] [<span class="hljs-string">'-c'</span>, <span class="hljs-string">'--compile'</span>, <span class="hljs-string">'compile to JavaScript and save as .js files'</span>] [<span class="hljs-string">'-e'</span>, <span class="hljs-string">'--eval'</span>, <span class="hljs-string">'pass a string from the command line as input'</span>] [<span class="hljs-string">'-h'</span>, <span class="hljs-string">'--help'</span>, <span class="hljs-string">'display this help message'</span>] [<span class="hljs-string">'-i'</span>, <span class="hljs-string">'--interactive'</span>, <span class="hljs-string">'run an interactive CoffeeScript REPL'</span>] [<span class="hljs-string">'-j'</span>, <span class="hljs-string">'--join [FILE]'</span>, <span class="hljs-string">'concatenate the source CoffeeScript before compiling'</span>] [<span class="hljs-string">'-m'</span>, <span class="hljs-string">'--map'</span>, <span class="hljs-string">'generate source map and save as .js.map files'</span>] [<span class="hljs-string">'-n'</span>, <span class="hljs-string">'--nodes'</span>, <span class="hljs-string">'print out the parse tree that the parser produces'</span>] [ <span class="hljs-string">'--nodejs [ARGS]'</span>, <span class="hljs-string">'pass options directly to the "node" binary'</span>] [ <span class="hljs-string">'--no-header'</span>, <span class="hljs-string">'suppress the "Generated by" header'</span>] [<span class="hljs-string">'-o'</span>, <span class="hljs-string">'--output [DIR]'</span>, <span class="hljs-string">'set the output directory for compiled JavaScript'</span>] [<span class="hljs-string">'-p'</span>, <span class="hljs-string">'--print'</span>, <span class="hljs-string">'print out the compiled JavaScript'</span>] [<span class="hljs-string">'-r'</span>, <span class="hljs-string">'--require [MODULE*]'</span>, <span class="hljs-string">'require the given module before eval or REPL'</span>] [<span class="hljs-string">'-s'</span>, <span class="hljs-string">'--stdio'</span>, <span class="hljs-string">'listen for and compile scripts over stdio'</span>] [<span class="hljs-string">'-l'</span>, <span class="hljs-string">'--literate'</span>, <span class="hljs-string">'treat stdio as literate style coffee-script'</span>] [<span class="hljs-string">'-t'</span>, <span class="hljs-string">'--tokens'</span>, <span class="hljs-string">'print out the tokens that the lexer/rewriter produce'</span>] [<span class="hljs-string">'-v'</span>, <span class="hljs-string">'--version'</span>, <span class="hljs-string">'display the version number'</span>] [<span class="hljs-string">'-w'</span>, <span class="hljs-string">'--watch'</span>, <span class="hljs-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 = {} watchedDirs = {} optionParser = <span class="hljs-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><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">run</span> = -></span> parseOptions()</pre></div></div> </li> <li id="section-8"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Make the REPL <em>CLI</em> use the global context so as to (a) be consistent with the <code>node</code> REPL CLI and, therefore, (b) make packages that modify native prototypes (such as ‘colors’ and ‘sugar’) work as expected.</p> </div> <div class="content"><div class='highlight'><pre> replCliOpts = <span class="hljs-attribute">useGlobal</span>: <span class="hljs-literal">yes</span> opts.prelude = makePrelude opts.<span class="hljs-built_in">require</span> <span class="hljs-keyword">if</span> opts.<span class="hljs-built_in">require</span> replCliOpts.prelude = opts.prelude <span class="hljs-keyword">return</span> forkNode() <span class="hljs-keyword">if</span> opts.nodejs <span class="hljs-keyword">return</span> usage() <span class="hljs-keyword">if</span> opts.help <span class="hljs-keyword">return</span> version() <span class="hljs-keyword">if</span> opts.version <span class="hljs-keyword">return</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'./repl'</span>).start(replCliOpts) <span class="hljs-keyword">if</span> opts.interactive <span class="hljs-keyword">return</span> compileStdio() <span class="hljs-keyword">if</span> opts.stdio <span class="hljs-keyword">return</span> compileScript <span class="hljs-literal">null</span>, opts.arguments[<span class="hljs-number">0</span>] <span class="hljs-keyword">if</span> opts.eval <span class="hljs-keyword">return</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'./repl'</span>).start(replCliOpts) <span class="hljs-keyword">unless</span> opts.arguments.length literals = <span class="hljs-keyword">if</span> opts.run <span class="hljs-keyword">then</span> opts.arguments.splice <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> [] process.argv = process.argv[<span class="hljs-number">0.</span><span class="hljs-number">.1</span>].concat literals process.argv[<span class="hljs-number">0</span>] = <span class="hljs-string">'coffee'</span> opts.output = path.resolve opts.output <span class="hljs-keyword">if</span> opts.output <span class="hljs-keyword">if</span> opts.join opts.join = path.resolve opts.join <span class="hljs-built_in">console</span>.error <span class="hljs-string">''' The --join option is deprecated and will be removed in a future version. If for some reason it's necessary to share local variables between files, replace... $ coffee --compile --join bundle.js -- a.coffee b.coffee c.coffee with... $ cat a.coffee b.coffee c.coffee | coffee --compile --stdio > bundle.js '''</span> <span class="hljs-keyword">for</span> source <span class="hljs-keyword">in</span> opts.arguments source = path.resolve source compilePath source, <span class="hljs-literal">yes</span>, source <span class="hljs-function"><span class="hljs-title">makePrelude</span> = <span class="hljs-params">(requires)</span> -></span> requires.map <span class="hljs-function"><span class="hljs-params">(<span class="hljs-built_in">module</span>)</span> -></span> [_, name, <span class="hljs-built_in">module</span>] = match <span class="hljs-keyword">if</span> match = <span class="hljs-built_in">module</span>.match(<span class="hljs-regexp">/^(.*)=(.*)$/</span>) name ||= helpers.baseFileName <span class="hljs-built_in">module</span>, <span class="hljs-literal">yes</span>, useWinPathSep <span class="hljs-string">"<span class="hljs-subst">#{name}</span> = require('<span class="hljs-subst">#{<span class="hljs-built_in">module</span>}</span>')"</span> .join <span class="hljs-string">';'</span></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 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="hljs-function"><span class="hljs-title">compilePath</span> = <span class="hljs-params">(source, topLevel, base)</span> -></span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> source <span class="hljs-keyword">in</span> sources <span class="hljs-keyword">or</span> watchedDirs[source] <span class="hljs-keyword">or</span> <span class="hljs-keyword">not</span> topLevel <span class="hljs-keyword">and</span> (notSources[source] <span class="hljs-keyword">or</span> hidden source) <span class="hljs-keyword">try</span> stats = fs.statSync source <span class="hljs-keyword">catch</span> err <span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span> <span class="hljs-built_in">console</span>.error <span class="hljs-string">"File not found: <span class="hljs-subst">#{source}</span>"</span> process.exit <span class="hljs-number">1</span> <span class="hljs-keyword">throw</span> err <span class="hljs-keyword">if</span> stats.isDirectory() <span class="hljs-keyword">if</span> path.basename(source) <span class="hljs-keyword">is</span> <span class="hljs-string">'node_modules'</span> notSources[source] = <span class="hljs-literal">yes</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> opts.run compilePath findDirectoryIndex(source), topLevel, base <span class="hljs-keyword">return</span> watchDir source, base <span class="hljs-keyword">if</span> opts.watch <span class="hljs-keyword">try</span> files = fs.readdirSync source <span class="hljs-keyword">catch</span> err <span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span> <span class="hljs-keyword">then</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">throw</span> err <span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> files compilePath (path.join source, file), <span class="hljs-literal">no</span>, base <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> topLevel <span class="hljs-keyword">or</span> helpers.isCoffee source sources.push source sourceCode.push <span class="hljs-literal">null</span> <span class="hljs-keyword">delete</span> notSources[source] watch source, base <span class="hljs-keyword">if</span> opts.watch <span class="hljs-keyword">try</span> code = fs.readFileSync source <span class="hljs-keyword">catch</span> err <span class="hljs-keyword">if</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span> <span class="hljs-keyword">then</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">throw</span> err compileScript(source, code.toString(), base) <span class="hljs-keyword">else</span> notSources[source] = <span class="hljs-literal">yes</span> <span class="hljs-function"><span class="hljs-title">findDirectoryIndex</span> = <span class="hljs-params">(source)</span> -></span> <span class="hljs-keyword">for</span> ext <span class="hljs-keyword">in</span> CoffeeScript.FILE_EXTENSIONS index = path.join source, <span class="hljs-string">"index<span class="hljs-subst">#{ext}</span>"</span> <span class="hljs-keyword">try</span> <span class="hljs-keyword">return</span> index <span class="hljs-keyword">if</span> (fs.statSync index).isFile() <span class="hljs-keyword">catch</span> err <span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span> <span class="hljs-built_in">console</span>.error <span class="hljs-string">"Missing index.coffee or index.litcoffee in <span class="hljs-subst">#{source}</span>"</span> process.exit <span class="hljs-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>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="hljs-function"><span class="hljs-title">compileScript</span> = <span class="hljs-params">(file, input, base = <span class="hljs-literal">null</span>)</span> -></span> o = opts options = compileOptions file, base <span class="hljs-keyword">try</span> t = task = {file, input, options} CoffeeScript.emit <span class="hljs-string">'compile'</span>, task <span class="hljs-keyword">if</span> o.tokens printTokens CoffeeScript.tokens t.input, t.options <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> o.nodes printLine CoffeeScript.nodes(t.input, t.options).toString().trim() <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> o.run CoffeeScript.register() CoffeeScript.eval opts.prelude, t.options <span class="hljs-keyword">if</span> opts.prelude CoffeeScript.run t.input, t.options <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> o.join <span class="hljs-keyword">and</span> t.file <span class="hljs-keyword">isnt</span> o.join t.input = helpers.invertLiterate t.input <span class="hljs-keyword">if</span> helpers.isLiterate file sourceCode[sources.indexOf(t.file)] = t.input compileJoin() <span class="hljs-keyword">else</span> compiled = CoffeeScript.compile t.input, t.options t.output = compiled <span class="hljs-keyword">if</span> o.map t.output = compiled.js t.sourceMap = compiled.v3SourceMap CoffeeScript.emit <span class="hljs-string">'success'</span>, task <span class="hljs-keyword">if</span> o.<span class="hljs-built_in">print</span> printLine t.output.trim() <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> o.compile <span class="hljs-keyword">or</span> o.map writeJs base, t.file, t.output, options.jsPath, t.sourceMap <span class="hljs-keyword">catch</span> err CoffeeScript.emit <span class="hljs-string">'failure'</span>, err, task <span class="hljs-keyword">return</span> <span class="hljs-keyword">if</span> CoffeeScript.listeners(<span class="hljs-string">'failure'</span>).length message = err.stack <span class="hljs-keyword">or</span> <span class="hljs-string">"<span class="hljs-subst">#{err}</span>"</span> <span class="hljs-keyword">if</span> o.watch printLine message + <span class="hljs-string">'\x07'</span> <span class="hljs-keyword">else</span> printWarn message process.exit <span class="hljs-number">1</span></pre></div></div> </li> <li id="section-11"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-11">¶</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="hljs-function"><span class="hljs-title">compileStdio</span> = -></span> code = <span class="hljs-string">''</span> stdin = process.openStdin() stdin.<span class="hljs-literal">on</span> <span class="hljs-string">'data'</span>, <span class="hljs-function"><span class="hljs-params">(buffer)</span> -></span> code += buffer.toString() <span class="hljs-keyword">if</span> buffer stdin.<span class="hljs-literal">on</span> <span class="hljs-string">'end'</span>,<span class="hljs-function"> -></span> compileScript <span class="hljs-literal">null</span>, code</pre></div></div> </li> <li id="section-12"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-12">¶</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="hljs-literal">null</span> <span class="hljs-function"><span class="hljs-title">compileJoin</span> = -></span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> opts.join <span class="hljs-keyword">unless</span> sourceCode.some<span class="hljs-function"><span class="hljs-params">((code) -> code <span class="hljs-keyword">is</span> <span class="hljs-literal">null</span>)</span> <span class="hljs-title">clearTimeout</span> <span class="hljs-title">joinTimeout</span> <span class="hljs-title">joinTimeout</span> = <span class="hljs-title">wait</span> 100, -></span> compileScript opts.join, sourceCode.join(<span class="hljs-string">'\n'</span>), opts.join</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 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="hljs-function"><span class="hljs-title">watch</span> = <span class="hljs-params">(source, base)</span> -></span> watcher = <span class="hljs-literal">null</span> prevStats = <span class="hljs-literal">null</span> compileTimeout = <span class="hljs-literal">null</span> <span class="hljs-function"><span class="hljs-title">watchErr</span> = <span class="hljs-params">(err)</span> -></span> <span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> source <span class="hljs-keyword">in</span> sources <span class="hljs-keyword">try</span> rewatch() compile() <span class="hljs-keyword">catch</span> removeSource source, base compileJoin() <span class="hljs-function"><span class="hljs-title">compile</span> = -></span> clearTimeout compileTimeout compileTimeout = wait <span class="hljs-number">25</span>,<span class="hljs-function"> -></span> fs.stat source, <span class="hljs-function"><span class="hljs-params">(err, stats)</span> -></span> <span class="hljs-keyword">return</span> watchErr err <span class="hljs-keyword">if</span> err <span class="hljs-keyword">return</span> rewatch() <span class="hljs-keyword">if</span> prevStats <span class="hljs-keyword">and</span> stats.size <span class="hljs-keyword">is</span> prevStats.size <span class="hljs-keyword">and</span> stats.mtime.getTime() <span class="hljs-keyword">is</span> prevStats.mtime.getTime() prevStats = stats fs.readFile source, <span class="hljs-function"><span class="hljs-params">(err, code)</span> -></span> <span class="hljs-keyword">return</span> watchErr err <span class="hljs-keyword">if</span> err compileScript(source, code.toString(), base) rewatch() <span class="hljs-function"><span class="hljs-title">startWatcher</span> = -></span> watcher = fs.watch source .<span class="hljs-literal">on</span> <span class="hljs-string">'change'</span>, compile .<span class="hljs-literal">on</span> <span class="hljs-string">'error'</span>, <span class="hljs-function"><span class="hljs-params">(err)</span> -></span> <span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'EPERM'</span> removeSource source, base <span class="hljs-function"><span class="hljs-title">rewatch</span> = -></span> watcher?.close() startWatcher() <span class="hljs-keyword">try</span> startWatcher() <span class="hljs-keyword">catch</span> err watchErr err</pre></div></div> </li> <li id="section-14"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Watch a directory of files for new additions.</p> </div> <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">watchDir</span> = <span class="hljs-params">(source, base)</span> -></span> watcher = <span class="hljs-literal">null</span> readdirTimeout = <span class="hljs-literal">null</span> <span class="hljs-function"><span class="hljs-title">startWatcher</span> = -></span> watcher = fs.watch source .<span class="hljs-literal">on</span> <span class="hljs-string">'error'</span>, <span class="hljs-function"><span class="hljs-params">(err)</span> -></span> <span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'EPERM'</span> stopWatcher() .<span class="hljs-literal">on</span> <span class="hljs-string">'change'</span>,<span class="hljs-function"> -></span> clearTimeout readdirTimeout readdirTimeout = wait <span class="hljs-number">25</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">try</span> files = fs.readdirSync source <span class="hljs-keyword">catch</span> err <span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span> <span class="hljs-keyword">return</span> stopWatcher() <span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> files compilePath (path.join source, file), <span class="hljs-literal">no</span>, base <span class="hljs-function"><span class="hljs-title">stopWatcher</span> = -></span> watcher.close() removeSourceDir source, base watchedDirs[source] = <span class="hljs-literal">yes</span> <span class="hljs-keyword">try</span> startWatcher() <span class="hljs-keyword">catch</span> err <span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">is</span> <span class="hljs-string">'ENOENT'</span> <span class="hljs-function"><span class="hljs-title">removeSourceDir</span> = <span class="hljs-params">(source, base)</span> -></span> <span class="hljs-keyword">delete</span> watchedDirs[source] sourcesChanged = <span class="hljs-literal">no</span> <span class="hljs-keyword">for</span> file <span class="hljs-keyword">in</span> sources <span class="hljs-keyword">when</span> source <span class="hljs-keyword">is</span> path.dirname file removeSource file, base sourcesChanged = <span class="hljs-literal">yes</span> compileJoin() <span class="hljs-keyword">if</span> sourcesChanged</pre></div></div> </li> <li id="section-15"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-15">¶</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="hljs-function"><span class="hljs-title">removeSource</span> = <span class="hljs-params">(source, base)</span> -></span> index = sources.indexOf source sources.splice index, <span class="hljs-number">1</span> sourceCode.splice index, <span class="hljs-number">1</span> <span class="hljs-keyword">unless</span> opts.join silentUnlink outputPath source, base silentUnlink outputPath source, base, <span class="hljs-string">'.js.map'</span> timeLog <span class="hljs-string">"removed <span class="hljs-subst">#{source}</span>"</span> <span class="hljs-function"><span class="hljs-title">silentUnlink</span> = <span class="hljs-params">(path)</span> -></span> <span class="hljs-keyword">try</span> fs.unlinkSync path <span class="hljs-keyword">catch</span> err <span class="hljs-keyword">throw</span> err <span class="hljs-keyword">unless</span> err.code <span class="hljs-keyword">in</span> [<span class="hljs-string">'ENOENT'</span>, <span class="hljs-string">'EPERM'</span>]</pre></div></div> </li> <li id="section-16"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Get the corresponding output JavaScript path for a source file.</p> </div> <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">outputPath</span> = <span class="hljs-params">(source, base, extension=<span class="hljs-string">".js"</span>)</span> -></span> basename = helpers.baseFileName source, <span class="hljs-literal">yes</span>, useWinPathSep srcDir = path.dirname source <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> opts.output dir = srcDir <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> source <span class="hljs-keyword">is</span> base dir = opts.output <span class="hljs-keyword">else</span> dir = path.join opts.output, path.relative base, srcDir path.join dir, basename + extension</pre></div></div> </li> <li id="section-17"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-17">¶</a> </div> <p>Recursively mkdir, like <code>mkdir -p</code>.</p> </div> <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">mkdirp</span> = <span class="hljs-params">(dir, fn)</span> -></span> mode = <span class="hljs-number">0</span>o777 & ~process.umask() <span class="hljs-keyword">do</span> <span class="hljs-function"><span class="hljs-title">mkdirs</span> = <span class="hljs-params">(p = dir, fn)</span> -></span> fs.exists p, <span class="hljs-function"><span class="hljs-params">(exists)</span> -></span> <span class="hljs-keyword">if</span> exists fn() <span class="hljs-keyword">else</span> mkdirs path.dirname(p),<span class="hljs-function"> -></span> fs.mkdir p, mode, <span class="hljs-function"><span class="hljs-params">(err)</span> -></span> <span class="hljs-keyword">return</span> fn err <span class="hljs-keyword">if</span> err fn()</pre></div></div> </li> <li id="section-18"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-18">¶</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>.js.map</code> file into the same directory as the <code>.js</code> file.</p> </div> <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">writeJs</span> = <span class="hljs-params">(base, sourcePath, js, jsPath, generatedSourceMap = <span class="hljs-literal">null</span>)</span> -></span> sourceMapPath = outputPath sourcePath, base, <span class="hljs-string">".js.map"</span> jsDir = path.dirname jsPath <span class="hljs-function"><span class="hljs-title">compile</span> = -></span> <span class="hljs-keyword">if</span> opts.compile js = <span class="hljs-string">' '</span> <span class="hljs-keyword">if</span> js.length <= <span class="hljs-number">0</span> <span class="hljs-keyword">if</span> generatedSourceMap <span class="hljs-keyword">then</span> js = <span class="hljs-string">"<span class="hljs-subst">#{js}</span>\n//# sourceMappingURL=<span class="hljs-subst">#{helpers.baseFileName sourceMapPath, <span class="hljs-literal">no</span>, useWinPathSep}</span>\n"</span> fs.writeFile jsPath, js, <span class="hljs-function"><span class="hljs-params">(err)</span> -></span> <span class="hljs-keyword">if</span> err printLine err.message process.exit <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> opts.compile <span class="hljs-keyword">and</span> opts.watch timeLog <span class="hljs-string">"compiled <span class="hljs-subst">#{sourcePath}</span>"</span> <span class="hljs-keyword">if</span> generatedSourceMap fs.writeFile sourceMapPath, generatedSourceMap, <span class="hljs-function"><span class="hljs-params">(err)</span> -></span> <span class="hljs-keyword">if</span> err printLine <span class="hljs-string">"Could not write source map: <span class="hljs-subst">#{err.message}</span>"</span> process.exit <span class="hljs-number">1</span> fs.exists jsDir, <span class="hljs-function"><span class="hljs-params">(itExists)</span> -></span> <span class="hljs-keyword">if</span> itExists <span class="hljs-keyword">then</span> compile() <span class="hljs-keyword">else</span> mkdirp jsDir, compile</pre></div></div> </li> <li id="section-19"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-19">¶</a> </div> <p>Convenience for cleaner setTimeouts.</p> </div> <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">wait</span> = <span class="hljs-params">(milliseconds, func)</span> -></span> setTimeout func, milliseconds</pre></div></div> </li> <li id="section-20"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-20">¶</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="hljs-function"><span class="hljs-title">timeLog</span> = <span class="hljs-params">(message)</span> -></span> <span class="hljs-built_in">console</span>.log <span class="hljs-string">"<span class="hljs-subst">#{(<span class="hljs-keyword">new</span> Date).toLocaleTimeString()}</span> - <span class="hljs-subst">#{message}</span>"</span></pre></div></div> </li> <li id="section-21"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-21">¶</a> </div> <p>Pretty-print a stream of tokens, sans location data.</p> </div> <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">printTokens</span> = <span class="hljs-params">(tokens)</span> -></span> strings = <span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens tag = token[<span class="hljs-number">0</span>] value = token[<span class="hljs-number">1</span>].toString().replace(<span class="hljs-regexp">/\n/</span>, <span class="hljs-string">'\\n'</span>) <span class="hljs-string">"[<span class="hljs-subst">#{tag}</span> <span class="hljs-subst">#{value}</span>]"</span> printLine strings.join(<span class="hljs-string">' '</span>)</pre></div></div> </li> <li id="section-22"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-22">¶</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="hljs-function"><span class="hljs-title">parseOptions</span> = -></span> optionParser = <span class="hljs-keyword">new</span> optparse.OptionParser SWITCHES, BANNER o = opts = optionParser.parse process.argv[<span class="hljs-number">2.</span>.] o.compile <span class="hljs-keyword">or</span>= !!o.output o.run = <span class="hljs-keyword">not</span> (o.compile <span class="hljs-keyword">or</span> o.<span class="hljs-built_in">print</span> <span class="hljs-keyword">or</span> o.map) o.<span class="hljs-built_in">print</span> = !! (o.<span class="hljs-built_in">print</span> <span class="hljs-keyword">or</span> (o.eval <span class="hljs-keyword">or</span> o.stdio <span class="hljs-keyword">and</span> o.compile))</pre></div></div> </li> <li id="section-23"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-23">¶</a> </div> <p>The compile-time options to pass to the CoffeeScript compiler.</p> </div> <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">compileOptions</span> = <span class="hljs-params">(filename, base)</span> -></span> answer = { filename <span class="hljs-attribute">literate</span>: opts.literate <span class="hljs-keyword">or</span> helpers.isLiterate(filename) <span class="hljs-attribute">bare</span>: opts.bare <span class="hljs-attribute">header</span>: opts.compile <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> opts[<span class="hljs-string">'no-header'</span>] <span class="hljs-attribute">sourceMap</span>: opts.map } <span class="hljs-keyword">if</span> filename <span class="hljs-keyword">if</span> base cwd = process.cwd() jsPath = outputPath filename, base jsDir = path.dirname jsPath answer = helpers.merge answer, { jsPath <span class="hljs-attribute">sourceRoot</span>: path.relative jsDir, cwd <span class="hljs-attribute">sourceFiles</span>: [path.relative cwd, filename] <span class="hljs-attribute">generatedFile</span>: helpers.baseFileName(jsPath, <span class="hljs-literal">no</span>, useWinPathSep) } <span class="hljs-keyword">else</span> answer = helpers.merge answer, <span class="hljs-attribute">sourceRoot</span>: <span class="hljs-string">""</span> <span class="hljs-attribute">sourceFiles</span>: [helpers.baseFileName filename, <span class="hljs-literal">no</span>, useWinPathSep] <span class="hljs-attribute">generatedFile</span>: helpers.baseFileName(filename, <span class="hljs-literal">yes</span>, useWinPathSep) + <span class="hljs-string">".js"</span> answer</pre></div></div> </li> <li id="section-24"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-24">¶</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="hljs-function"><span class="hljs-title">forkNode</span> = -></span> nodeArgs = opts.nodejs.split <span class="hljs-regexp">/\s+/</span> args = process.argv[<span class="hljs-number">1.</span>.] args.splice args.indexOf(<span class="hljs-string">'--nodejs'</span>), <span class="hljs-number">2</span> p = spawn process.execPath, nodeArgs.concat(args), <span class="hljs-attribute">cwd</span>: process.cwd() <span class="hljs-attribute">env</span>: process.env <span class="hljs-attribute">stdio</span>: [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>] p.<span class="hljs-literal">on</span> <span class="hljs-string">'exit'</span>, <span class="hljs-function"><span class="hljs-params">(code)</span> -></span> process.exit code</pre></div></div> </li> <li id="section-25"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-25">¶</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="hljs-function"><span class="hljs-title">usage</span> = -></span> printLine (<span class="hljs-keyword">new</span> optparse.OptionParser SWITCHES, BANNER).help()</pre></div></div> </li> <li id="section-26"> <div class="annotation"> <div class="pilwrap "> <a class="pilcrow" href="#section-26">¶</a> </div> <p>Print the <code>--version</code> message and exit.</p> </div> <div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">version</span> = -></span> printLine <span class="hljs-string">"CoffeeScript version <span class="hljs-subst">#{CoffeeScript.VERSION}</span>"</span></pre></div></div> </li> </ul> </div> </body> </html>