1 // Generated by CoffeeScript 1.8.0
3 var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, findDirectoryIndex, forkNode, fs, helpers, hidden, joinTimeout, mkdirp, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, removeSourceDir, silentUnlink, sourceCode, sources, spawn, timeLog, usage, useWinPathSep, version, wait, watch, watchDir, watchedDirs, writeJs, _ref,
4 __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
8 path = require('path');
10 helpers = require('./helpers');
12 optparse = require('./optparse');
14 CoffeeScript = require('./coffee-script');
16 mkdirp = require('mkdirp');
18 _ref = require('child_process'), spawn = _ref.spawn, exec = _ref.exec;
20 EventEmitter = require('events').EventEmitter;
22 useWinPathSep = path.sep === '\\';
24 helpers.extend(CoffeeScript, new EventEmitter);
26 printLine = function(line) {
27 return process.stdout.write(line + '\n');
30 printWarn = function(line) {
31 return process.stderr.write(line + '\n');
34 hidden = function(file) {
35 return /^\.|~$/.test(file);
38 BANNER = 'Usage: coffee [options] path/to/script.coffee -- [args]\n\nIf called without options, `coffee` will run your script.';
40 SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-m', '--map', 'generate source map and save as .js.map files'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['--no-header', 'suppress the "Generated by" header'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-l', '--literate', 'treat stdio as literate style coffee-script'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
54 exports.run = function() {
55 var literals, replCliOpts, source, _i, _len, _ref1, _results;
69 if (opts.interactive) {
70 return require('./repl').start(replCliOpts);
73 return compileStdio();
76 return compileScript(null, opts["arguments"][0]);
78 if (!opts["arguments"].length) {
79 return require('./repl').start(replCliOpts);
81 literals = opts.run ? opts["arguments"].splice(1) : [];
82 process.argv = process.argv.slice(0, 2).concat(literals);
83 process.argv[0] = 'coffee';
85 opts.output = path.resolve(opts.output);
88 opts.join = path.resolve(opts.join);
89 console.error('\nThe --join option is deprecated and will be removed in a future version.\n\nIf for some reason it\'s necessary to share local variables between files,\nreplace...\n\n $ coffee --compile --join bundle.js -- a.coffee b.coffee c.coffee\n\nwith...\n\n $ cat a.coffee b.coffee c.coffee | coffee --compile --stdio > bundle.js\n');
91 _ref1 = opts["arguments"];
93 for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
95 source = path.resolve(source);
96 _results.push(compilePath(source, true, source));
101 compilePath = function(source, topLevel, base) {
102 var code, err, file, files, stats, _i, _len, _results;
103 if (__indexOf.call(sources, source) >= 0 || watchedDirs[source] || !topLevel && (notSources[source] || hidden(source))) {
107 stats = fs.statSync(source);
110 if (err.code === 'ENOENT') {
111 console.error("File not found: " + source);
116 if (stats.isDirectory()) {
117 if (path.basename(source) === 'node_modules') {
118 notSources[source] = true;
122 compilePath(findDirectoryIndex(source), topLevel, base);
126 watchDir(source, base);
129 files = fs.readdirSync(source);
132 if (err.code === 'ENOENT') {
139 for (_i = 0, _len = files.length; _i < _len; _i++) {
141 _results.push(compilePath(path.join(source, file), false, base));
144 } else if (topLevel || helpers.isCoffee(source)) {
145 sources.push(source);
146 sourceCode.push(null);
147 delete notSources[source];
152 code = fs.readFileSync(source);
155 if (err.code === 'ENOENT') {
161 return compileScript(source, code.toString(), base);
163 return notSources[source] = true;
167 findDirectoryIndex = function(source) {
168 var err, ext, index, _i, _len, _ref1;
169 _ref1 = CoffeeScript.FILE_EXTENSIONS;
170 for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
172 index = path.join(source, "index" + ext);
174 if ((fs.statSync(index)).isFile()) {
179 if (err.code !== 'ENOENT') {
184 console.error("Missing index.coffee or index.litcoffee in " + source);
185 return process.exit(1);
188 compileScript = function(file, input, base) {
189 var compiled, err, message, o, options, t, task;
194 options = compileOptions(file, base);
201 CoffeeScript.emit('compile', task);
203 return printTokens(CoffeeScript.tokens(t.input, t.options));
204 } else if (o.nodes) {
205 return printLine(CoffeeScript.nodes(t.input, t.options).toString().trim());
207 CoffeeScript.register();
208 return CoffeeScript.run(t.input, t.options);
209 } else if (o.join && t.file !== o.join) {
210 if (helpers.isLiterate(file)) {
211 t.input = helpers.invertLiterate(t.input);
213 sourceCode[sources.indexOf(t.file)] = t.input;
214 return compileJoin();
216 compiled = CoffeeScript.compile(t.input, t.options);
219 t.output = compiled.js;
220 t.sourceMap = compiled.v3SourceMap;
222 CoffeeScript.emit('success', task);
224 return printLine(t.output.trim());
225 } else if (o.compile || o.map) {
226 return writeJs(base, t.file, t.output, options.jsPath, t.sourceMap);
231 CoffeeScript.emit('failure', err, task);
232 if (CoffeeScript.listeners('failure').length) {
235 message = err.stack || ("" + err);
237 return printLine(message + '\x07');
240 return process.exit(1);
245 compileStdio = function() {
248 stdin = process.openStdin();
249 stdin.on('data', function(buffer) {
251 return code += buffer.toString();
254 return stdin.on('end', function() {
255 return compileScript(null, code);
261 compileJoin = function() {
265 if (!sourceCode.some(function(code) {
266 return code === null;
268 clearTimeout(joinTimeout);
269 return joinTimeout = wait(100, function() {
270 return compileScript(opts.join, sourceCode.join('\n'), opts.join);
275 watch = function(source, base) {
276 var compile, compileTimeout, err, prevStats, rewatch, startWatcher, watchErr, watcher;
279 compileTimeout = null;
280 watchErr = function(err) {
281 if (err.code !== 'ENOENT') {
284 if (__indexOf.call(sources, source) < 0) {
291 removeSource(source, base);
292 return compileJoin();
295 compile = function() {
296 clearTimeout(compileTimeout);
297 return compileTimeout = wait(25, function() {
298 return fs.stat(source, function(err, stats) {
300 return watchErr(err);
302 if (prevStats && stats.size === prevStats.size && stats.mtime.getTime() === prevStats.mtime.getTime()) {
306 return fs.readFile(source, function(err, code) {
308 return watchErr(err);
310 compileScript(source, code.toString(), base);
316 startWatcher = function() {
317 return watcher = fs.watch(source).on('change', compile).on('error', function(err) {
318 if (err.code !== 'EPERM') {
321 return removeSource(source, base);
324 rewatch = function() {
325 if (watcher != null) {
328 return startWatcher();
331 return startWatcher();
334 return watchErr(err);
338 watchDir = function(source, base) {
339 var err, readdirTimeout, startWatcher, stopWatcher, watcher;
341 readdirTimeout = null;
342 startWatcher = function() {
343 return watcher = fs.watch(source).on('error', function(err) {
344 if (err.code !== 'EPERM') {
347 return stopWatcher();
348 }).on('change', function() {
349 clearTimeout(readdirTimeout);
350 return readdirTimeout = wait(25, function() {
351 var err, file, files, _i, _len, _results;
353 files = fs.readdirSync(source);
356 if (err.code !== 'ENOENT') {
359 return stopWatcher();
362 for (_i = 0, _len = files.length; _i < _len; _i++) {
364 _results.push(compilePath(path.join(source, file), false, base));
370 stopWatcher = function() {
372 return removeSourceDir(source, base);
374 watchedDirs[source] = true;
376 return startWatcher();
379 if (err.code !== 'ENOENT') {
385 removeSourceDir = function(source, base) {
386 var file, sourcesChanged, _i, _len;
387 delete watchedDirs[source];
388 sourcesChanged = false;
389 for (_i = 0, _len = sources.length; _i < _len; _i++) {
391 if (!(source === path.dirname(file))) {
394 removeSource(file, base);
395 sourcesChanged = true;
397 if (sourcesChanged) {
398 return compileJoin();
402 removeSource = function(source, base) {
404 index = sources.indexOf(source);
405 sources.splice(index, 1);
406 sourceCode.splice(index, 1);
408 silentUnlink(outputPath(source, base));
409 silentUnlink(outputPath(source, base, '.js.map'));
410 return timeLog("removed " + source);
414 silentUnlink = function(path) {
417 return fs.unlinkSync(path);
420 if ((_ref1 = err.code) !== 'ENOENT' && _ref1 !== 'EPERM') {
426 outputPath = function(source, base, extension) {
427 var basename, dir, srcDir;
428 if (extension == null) {
431 basename = helpers.baseFileName(source, true, useWinPathSep);
432 srcDir = path.dirname(source);
435 } else if (source === base) {
438 dir = path.join(opts.output, path.relative(base, srcDir));
440 return path.join(dir, basename + extension);
443 writeJs = function(base, sourcePath, js, jsPath, generatedSourceMap) {
444 var compile, jsDir, sourceMapPath;
445 if (generatedSourceMap == null) {
446 generatedSourceMap = null;
448 sourceMapPath = outputPath(sourcePath, base, ".js.map");
449 jsDir = path.dirname(jsPath);
450 compile = function() {
452 if (js.length <= 0) {
455 if (generatedSourceMap) {
456 js = "" + js + "\n//# sourceMappingURL=" + (helpers.baseFileName(sourceMapPath, false, useWinPathSep)) + "\n";
458 fs.writeFile(jsPath, js, function(err) {
460 printLine(err.message);
461 return process.exit(1);
462 } else if (opts.compile && opts.watch) {
463 return timeLog("compiled " + sourcePath);
467 if (generatedSourceMap) {
468 return fs.writeFile(sourceMapPath, generatedSourceMap, function(err) {
470 printLine("Could not write source map: " + err.message);
471 return process.exit(1);
476 return fs.exists(jsDir, function(itExists) {
480 return mkdirp(jsDir, compile);
485 wait = function(milliseconds, func) {
486 return setTimeout(func, milliseconds);
489 timeLog = function(message) {
490 return console.log("" + ((new Date).toLocaleTimeString()) + " - " + message);
493 printTokens = function(tokens) {
494 var strings, tag, token, value;
495 strings = (function() {
496 var _i, _len, _results;
498 for (_i = 0, _len = tokens.length; _i < _len; _i++) {
501 value = token[1].toString().replace(/\n/, '\\n');
502 _results.push("[" + tag + " " + value + "]");
506 return printLine(strings.join(' '));
509 parseOptions = function() {
511 optionParser = new optparse.OptionParser(SWITCHES, BANNER);
512 o = opts = optionParser.parse(process.argv.slice(2));
513 o.compile || (o.compile = !!o.output);
514 o.run = !(o.compile || o.print || o.map);
515 return o.print = !!(o.print || (o["eval"] || o.stdio && o.compile));
518 compileOptions = function(filename, base) {
519 var answer, cwd, jsDir, jsPath;
522 literate: opts.literate || helpers.isLiterate(filename),
524 header: opts.compile && !opts['no-header'],
530 jsPath = outputPath(filename, base);
531 jsDir = path.dirname(jsPath);
532 answer = helpers.merge(answer, {
534 sourceRoot: path.relative(jsDir, cwd),
535 sourceFiles: [path.relative(cwd, filename)],
536 generatedFile: helpers.baseFileName(jsPath, false, useWinPathSep)
539 answer = helpers.merge(answer, {
541 sourceFiles: [helpers.baseFileName(filename, false, useWinPathSep)],
542 generatedFile: helpers.baseFileName(filename, true, useWinPathSep) + ".js"
549 forkNode = function() {
550 var args, nodeArgs, p;
551 nodeArgs = opts.nodejs.split(/\s+/);
552 args = process.argv.slice(1);
553 args.splice(args.indexOf('--nodejs'), 2);
554 p = spawn(process.execPath, nodeArgs.concat(args), {
559 return p.on('exit', function(code) {
560 return process.exit(code);
565 return printLine((new optparse.OptionParser(SWITCHES, BANNER)).help());
568 version = function() {
569 return printLine("CoffeeScript version " + CoffeeScript.VERSION);