UNPKG

18.5 kBJavaScriptView Raw
1// Generated by CoffeeScript 1.9.3
2(function() {
3 var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, findDirectoryIndex, forkNode, fs, helpers, hidden, joinTimeout, makePrelude, mkdirp, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, ref, removeSource, removeSourceDir, silentUnlink, sourceCode, sources, spawn, timeLog, usage, useWinPathSep, version, wait, watch, watchDir, watchedDirs, writeJs,
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; };
5
6 fs = require('fs');
7
8 path = require('path');
9
10 helpers = require('./helpers');
11
12 optparse = require('./optparse');
13
14 CoffeeScript = require('./coffee-script');
15
16 ref = require('child_process'), spawn = ref.spawn, exec = ref.exec;
17
18 EventEmitter = require('events').EventEmitter;
19
20 useWinPathSep = path.sep === '\\';
21
22 helpers.extend(CoffeeScript, new EventEmitter);
23
24 printLine = function(line) {
25 return process.stdout.write(line + '\n');
26 };
27
28 printWarn = function(line) {
29 return process.stderr.write(line + '\n');
30 };
31
32 hidden = function(file) {
33 return /^\.|~$/.test(file);
34 };
35
36 BANNER = 'Usage: coffee [options] path/to/script.coffee -- [args]\n\nIf called without options, `coffee` will run your script.';
37
38 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'], ['-r', '--require [MODULE*]', 'require the given module before eval or REPL'], ['-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']];
39
40 opts = {};
41
42 sources = [];
43
44 sourceCode = [];
45
46 notSources = {};
47
48 watchedDirs = {};
49
50 optionParser = null;
51
52 exports.run = function() {
53 var i, len, literals, ref1, replCliOpts, results, source;
54 parseOptions();
55 replCliOpts = {
56 useGlobal: true
57 };
58 if (opts.require) {
59 opts.prelude = makePrelude(opts.require);
60 }
61 replCliOpts.prelude = opts.prelude;
62 if (opts.nodejs) {
63 return forkNode();
64 }
65 if (opts.help) {
66 return usage();
67 }
68 if (opts.version) {
69 return version();
70 }
71 if (opts.interactive) {
72 return require('./repl').start(replCliOpts);
73 }
74 if (opts.stdio) {
75 return compileStdio();
76 }
77 if (opts["eval"]) {
78 return compileScript(null, opts["arguments"][0]);
79 }
80 if (!opts["arguments"].length) {
81 return require('./repl').start(replCliOpts);
82 }
83 literals = opts.run ? opts["arguments"].splice(1) : [];
84 process.argv = process.argv.slice(0, 2).concat(literals);
85 process.argv[0] = 'coffee';
86 if (opts.output) {
87 opts.output = path.resolve(opts.output);
88 }
89 if (opts.join) {
90 opts.join = path.resolve(opts.join);
91 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');
92 }
93 ref1 = opts["arguments"];
94 results = [];
95 for (i = 0, len = ref1.length; i < len; i++) {
96 source = ref1[i];
97 source = path.resolve(source);
98 results.push(compilePath(source, true, source));
99 }
100 return results;
101 };
102
103 makePrelude = function(requires) {
104 return requires.map(function(module) {
105 var _, match, name;
106 if (match = module.match(/^(.*)=(.*)$/)) {
107 _ = match[0], name = match[1], module = match[2];
108 }
109 name || (name = helpers.baseFileName(module, true, useWinPathSep));
110 return name + " = require('" + module + "')";
111 }).join(';');
112 };
113
114 compilePath = function(source, topLevel, base) {
115 var code, err, file, files, i, len, results, stats;
116 if (indexOf.call(sources, source) >= 0 || watchedDirs[source] || !topLevel && (notSources[source] || hidden(source))) {
117 return;
118 }
119 try {
120 stats = fs.statSync(source);
121 } catch (_error) {
122 err = _error;
123 if (err.code === 'ENOENT') {
124 console.error("File not found: " + source);
125 process.exit(1);
126 }
127 throw err;
128 }
129 if (stats.isDirectory()) {
130 if (path.basename(source) === 'node_modules') {
131 notSources[source] = true;
132 return;
133 }
134 if (opts.run) {
135 compilePath(findDirectoryIndex(source), topLevel, base);
136 return;
137 }
138 if (opts.watch) {
139 watchDir(source, base);
140 }
141 try {
142 files = fs.readdirSync(source);
143 } catch (_error) {
144 err = _error;
145 if (err.code === 'ENOENT') {
146 return;
147 } else {
148 throw err;
149 }
150 }
151 results = [];
152 for (i = 0, len = files.length; i < len; i++) {
153 file = files[i];
154 results.push(compilePath(path.join(source, file), false, base));
155 }
156 return results;
157 } else if (topLevel || helpers.isCoffee(source)) {
158 sources.push(source);
159 sourceCode.push(null);
160 delete notSources[source];
161 if (opts.watch) {
162 watch(source, base);
163 }
164 try {
165 code = fs.readFileSync(source);
166 } catch (_error) {
167 err = _error;
168 if (err.code === 'ENOENT') {
169 return;
170 } else {
171 throw err;
172 }
173 }
174 return compileScript(source, code.toString(), base);
175 } else {
176 return notSources[source] = true;
177 }
178 };
179
180 findDirectoryIndex = function(source) {
181 var err, ext, i, index, len, ref1;
182 ref1 = CoffeeScript.FILE_EXTENSIONS;
183 for (i = 0, len = ref1.length; i < len; i++) {
184 ext = ref1[i];
185 index = path.join(source, "index" + ext);
186 try {
187 if ((fs.statSync(index)).isFile()) {
188 return index;
189 }
190 } catch (_error) {
191 err = _error;
192 if (err.code !== 'ENOENT') {
193 throw err;
194 }
195 }
196 }
197 console.error("Missing index.coffee or index.litcoffee in " + source);
198 return process.exit(1);
199 };
200
201 compileScript = function(file, input, base) {
202 var compiled, err, message, o, options, t, task;
203 if (base == null) {
204 base = null;
205 }
206 o = opts;
207 options = compileOptions(file, base);
208 try {
209 t = task = {
210 file: file,
211 input: input,
212 options: options
213 };
214 CoffeeScript.emit('compile', task);
215 if (o.tokens) {
216 return printTokens(CoffeeScript.tokens(t.input, t.options));
217 } else if (o.nodes) {
218 return printLine(CoffeeScript.nodes(t.input, t.options).toString().trim());
219 } else if (o.run) {
220 CoffeeScript.register();
221 if (opts.prelude) {
222 CoffeeScript["eval"](opts.prelude, t.options);
223 }
224 return CoffeeScript.run(t.input, t.options);
225 } else if (o.join && t.file !== o.join) {
226 if (helpers.isLiterate(file)) {
227 t.input = helpers.invertLiterate(t.input);
228 }
229 sourceCode[sources.indexOf(t.file)] = t.input;
230 return compileJoin();
231 } else {
232 compiled = CoffeeScript.compile(t.input, t.options);
233 t.output = compiled;
234 if (o.map) {
235 t.output = compiled.js;
236 t.sourceMap = compiled.v3SourceMap;
237 }
238 CoffeeScript.emit('success', task);
239 if (o.print) {
240 return printLine(t.output.trim());
241 } else if (o.compile || o.map) {
242 return writeJs(base, t.file, t.output, options.jsPath, t.sourceMap);
243 }
244 }
245 } catch (_error) {
246 err = _error;
247 CoffeeScript.emit('failure', err, task);
248 if (CoffeeScript.listeners('failure').length) {
249 return;
250 }
251 message = err.stack || ("" + err);
252 if (o.watch) {
253 return printLine(message + '\x07');
254 } else {
255 printWarn(message);
256 return process.exit(1);
257 }
258 }
259 };
260
261 compileStdio = function() {
262 var code, stdin;
263 code = '';
264 stdin = process.openStdin();
265 stdin.on('data', function(buffer) {
266 if (buffer) {
267 return code += buffer.toString();
268 }
269 });
270 return stdin.on('end', function() {
271 return compileScript(null, code);
272 });
273 };
274
275 joinTimeout = null;
276
277 compileJoin = function() {
278 if (!opts.join) {
279 return;
280 }
281 if (!sourceCode.some(function(code) {
282 return code === null;
283 })) {
284 clearTimeout(joinTimeout);
285 return joinTimeout = wait(100, function() {
286 return compileScript(opts.join, sourceCode.join('\n'), opts.join);
287 });
288 }
289 };
290
291 watch = function(source, base) {
292 var compile, compileTimeout, err, prevStats, rewatch, startWatcher, watchErr, watcher;
293 watcher = null;
294 prevStats = null;
295 compileTimeout = null;
296 watchErr = function(err) {
297 if (err.code !== 'ENOENT') {
298 throw err;
299 }
300 if (indexOf.call(sources, source) < 0) {
301 return;
302 }
303 try {
304 rewatch();
305 return compile();
306 } catch (_error) {
307 removeSource(source, base);
308 return compileJoin();
309 }
310 };
311 compile = function() {
312 clearTimeout(compileTimeout);
313 return compileTimeout = wait(25, function() {
314 return fs.stat(source, function(err, stats) {
315 if (err) {
316 return watchErr(err);
317 }
318 if (prevStats && stats.size === prevStats.size && stats.mtime.getTime() === prevStats.mtime.getTime()) {
319 return rewatch();
320 }
321 prevStats = stats;
322 return fs.readFile(source, function(err, code) {
323 if (err) {
324 return watchErr(err);
325 }
326 compileScript(source, code.toString(), base);
327 return rewatch();
328 });
329 });
330 });
331 };
332 startWatcher = function() {
333 return watcher = fs.watch(source).on('change', compile).on('error', function(err) {
334 if (err.code !== 'EPERM') {
335 throw err;
336 }
337 return removeSource(source, base);
338 });
339 };
340 rewatch = function() {
341 if (watcher != null) {
342 watcher.close();
343 }
344 return startWatcher();
345 };
346 try {
347 return startWatcher();
348 } catch (_error) {
349 err = _error;
350 return watchErr(err);
351 }
352 };
353
354 watchDir = function(source, base) {
355 var err, readdirTimeout, startWatcher, stopWatcher, watcher;
356 watcher = null;
357 readdirTimeout = null;
358 startWatcher = function() {
359 return watcher = fs.watch(source).on('error', function(err) {
360 if (err.code !== 'EPERM') {
361 throw err;
362 }
363 return stopWatcher();
364 }).on('change', function() {
365 clearTimeout(readdirTimeout);
366 return readdirTimeout = wait(25, function() {
367 var err, file, files, i, len, results;
368 try {
369 files = fs.readdirSync(source);
370 } catch (_error) {
371 err = _error;
372 if (err.code !== 'ENOENT') {
373 throw err;
374 }
375 return stopWatcher();
376 }
377 results = [];
378 for (i = 0, len = files.length; i < len; i++) {
379 file = files[i];
380 results.push(compilePath(path.join(source, file), false, base));
381 }
382 return results;
383 });
384 });
385 };
386 stopWatcher = function() {
387 watcher.close();
388 return removeSourceDir(source, base);
389 };
390 watchedDirs[source] = true;
391 try {
392 return startWatcher();
393 } catch (_error) {
394 err = _error;
395 if (err.code !== 'ENOENT') {
396 throw err;
397 }
398 }
399 };
400
401 removeSourceDir = function(source, base) {
402 var file, i, len, sourcesChanged;
403 delete watchedDirs[source];
404 sourcesChanged = false;
405 for (i = 0, len = sources.length; i < len; i++) {
406 file = sources[i];
407 if (!(source === path.dirname(file))) {
408 continue;
409 }
410 removeSource(file, base);
411 sourcesChanged = true;
412 }
413 if (sourcesChanged) {
414 return compileJoin();
415 }
416 };
417
418 removeSource = function(source, base) {
419 var index;
420 index = sources.indexOf(source);
421 sources.splice(index, 1);
422 sourceCode.splice(index, 1);
423 if (!opts.join) {
424 silentUnlink(outputPath(source, base));
425 silentUnlink(outputPath(source, base, '.js.map'));
426 return timeLog("removed " + source);
427 }
428 };
429
430 silentUnlink = function(path) {
431 var err, ref1;
432 try {
433 return fs.unlinkSync(path);
434 } catch (_error) {
435 err = _error;
436 if ((ref1 = err.code) !== 'ENOENT' && ref1 !== 'EPERM') {
437 throw err;
438 }
439 }
440 };
441
442 outputPath = function(source, base, extension) {
443 var basename, dir, srcDir;
444 if (extension == null) {
445 extension = ".js";
446 }
447 basename = helpers.baseFileName(source, true, useWinPathSep);
448 srcDir = path.dirname(source);
449 if (!opts.output) {
450 dir = srcDir;
451 } else if (source === base) {
452 dir = opts.output;
453 } else {
454 dir = path.join(opts.output, path.relative(base, srcDir));
455 }
456 return path.join(dir, basename + extension);
457 };
458
459 mkdirp = function(dir, fn) {
460 var mkdirs, mode;
461 mode = 0x1ff & ~process.umask();
462 return (mkdirs = function(p, fn) {
463 return fs.exists(p, function(exists) {
464 if (exists) {
465 return fn();
466 } else {
467 return mkdirs(path.dirname(p), function() {
468 return fs.mkdir(p, mode, function(err) {
469 if (err) {
470 return fn(err);
471 }
472 return fn();
473 });
474 });
475 }
476 });
477 })(dir, fn);
478 };
479
480 writeJs = function(base, sourcePath, js, jsPath, generatedSourceMap) {
481 var compile, jsDir, sourceMapPath;
482 if (generatedSourceMap == null) {
483 generatedSourceMap = null;
484 }
485 sourceMapPath = outputPath(sourcePath, base, ".js.map");
486 jsDir = path.dirname(jsPath);
487 compile = function() {
488 if (opts.compile) {
489 if (js.length <= 0) {
490 js = ' ';
491 }
492 if (generatedSourceMap) {
493 js = js + "\n//# sourceMappingURL=" + (helpers.baseFileName(sourceMapPath, false, useWinPathSep)) + "\n";
494 }
495 fs.writeFile(jsPath, js, function(err) {
496 if (err) {
497 printLine(err.message);
498 return process.exit(1);
499 } else if (opts.compile && opts.watch) {
500 return timeLog("compiled " + sourcePath);
501 }
502 });
503 }
504 if (generatedSourceMap) {
505 return fs.writeFile(sourceMapPath, generatedSourceMap, function(err) {
506 if (err) {
507 printLine("Could not write source map: " + err.message);
508 return process.exit(1);
509 }
510 });
511 }
512 };
513 return fs.exists(jsDir, function(itExists) {
514 if (itExists) {
515 return compile();
516 } else {
517 return mkdirp(jsDir, compile);
518 }
519 });
520 };
521
522 wait = function(milliseconds, func) {
523 return setTimeout(func, milliseconds);
524 };
525
526 timeLog = function(message) {
527 return console.log(((new Date).toLocaleTimeString()) + " - " + message);
528 };
529
530 printTokens = function(tokens) {
531 var strings, tag, token, value;
532 strings = (function() {
533 var i, len, results;
534 results = [];
535 for (i = 0, len = tokens.length; i < len; i++) {
536 token = tokens[i];
537 tag = token[0];
538 value = token[1].toString().replace(/\n/, '\\n');
539 results.push("[" + tag + " " + value + "]");
540 }
541 return results;
542 })();
543 return printLine(strings.join(' '));
544 };
545
546 parseOptions = function() {
547 var o;
548 optionParser = new optparse.OptionParser(SWITCHES, BANNER);
549 o = opts = optionParser.parse(process.argv.slice(2));
550 o.compile || (o.compile = !!o.output);
551 o.run = !(o.compile || o.print || o.map);
552 return o.print = !!(o.print || (o["eval"] || o.stdio && o.compile));
553 };
554
555 compileOptions = function(filename, base) {
556 var answer, cwd, jsDir, jsPath;
557 answer = {
558 filename: filename,
559 literate: opts.literate || helpers.isLiterate(filename),
560 bare: opts.bare,
561 header: opts.compile && !opts['no-header'],
562 sourceMap: opts.map
563 };
564 if (filename) {
565 if (base) {
566 cwd = process.cwd();
567 jsPath = outputPath(filename, base);
568 jsDir = path.dirname(jsPath);
569 answer = helpers.merge(answer, {
570 jsPath: jsPath,
571 sourceRoot: path.relative(jsDir, cwd),
572 sourceFiles: [path.relative(cwd, filename)],
573 generatedFile: helpers.baseFileName(jsPath, false, useWinPathSep)
574 });
575 } else {
576 answer = helpers.merge(answer, {
577 sourceRoot: "",
578 sourceFiles: [helpers.baseFileName(filename, false, useWinPathSep)],
579 generatedFile: helpers.baseFileName(filename, true, useWinPathSep) + ".js"
580 });
581 }
582 }
583 return answer;
584 };
585
586 forkNode = function() {
587 var args, nodeArgs, p;
588 nodeArgs = opts.nodejs.split(/\s+/);
589 args = process.argv.slice(1);
590 args.splice(args.indexOf('--nodejs'), 2);
591 p = spawn(process.execPath, nodeArgs.concat(args), {
592 cwd: process.cwd(),
593 env: process.env,
594 stdio: [0, 1, 2]
595 });
596 return p.on('exit', function(code) {
597 return process.exit(code);
598 });
599 };
600
601 usage = function() {
602 return printLine((new optparse.OptionParser(SWITCHES, BANNER)).help());
603 };
604
605 version = function() {
606 return printLine("CoffeeScript version " + CoffeeScript.VERSION);
607 };
608
609}).call(this);