2010-02-11 01:57:33 -05:00
( function ( ) {
2010-02-21 13:48:38 -05:00
var BANNER , SWITCHES , coffee , compile _script , compile _scripts , fs , lint , option _parser , options , optparse , parse _options , path , sources , usage , version , watch _scripts , write _js ;
2010-02-15 19:08:14 -05:00
fs = require ( 'fs' ) ;
2010-02-12 22:59:21 -05:00
path = require ( 'path' ) ;
2010-02-11 01:57:33 -05:00
coffee = require ( 'coffee-script' ) ;
2010-02-14 15:16:33 -05:00
optparse = require ( 'optparse' ) ;
2010-02-11 01:57:33 -05:00
BANNER = "coffee compiles CoffeeScript source files into JavaScript.\n\nUsage:\n coffee path/to/script.coffee" ;
2010-02-21 13:48:38 -05:00
SWITCHES = [ [ '-i' , '--interactive' , 'run an interactive CoffeeScript REPL' ] , [ '-r' , '--run' , 'compile and run a CoffeeScript' ] , [ '-o' , '--output [DIR]' , 'set the directory for compiled JavaScript' ] , [ '-w' , '--watch' , 'watch scripts for changes, and recompile' ] , [ '-p' , '--print' , 'print the compiled JavaScript to stdout' ] , [ '-l' , '--lint' , 'pipe the compiled JavaScript through JSLint' ] , [ '-e' , '--eval' , 'compile a string from the command line' ] , [ '-t' , '--tokens' , 'print the tokens that the lexer produces' ] , [ '-tr' , '--tree' , 'print the parse tree that Jison produces' ] , [ '-n' , '--no-wrap' , 'compile without the top-level function wrapper' ] , [ '-v' , '--version' , 'display CoffeeScript version' ] , [ '-h' , '--help' , 'display this help message' ] ] ;
2010-02-13 10:16:28 -05:00
options = { } ;
sources = [ ] ;
option _parser = null ;
2010-02-11 01:57:33 -05:00
// The CommandLine handles all of the functionality of the `coffee` utility.
exports . run = function run ( ) {
2010-02-16 01:04:48 -05:00
var flags , separator ;
2010-02-13 10:16:28 -05:00
parse _options ( ) ;
if ( options . interactive ) {
2010-02-17 00:50:08 -05:00
return require ( 'repl' ) ;
2010-02-13 10:07:59 -05:00
}
2010-02-13 23:27:13 -05:00
if ( options . eval ) {
return puts ( coffee . compile ( sources [ 0 ] ) ) ;
}
2010-02-13 10:16:28 -05:00
if ( ! ( sources . length ) ) {
usage ( ) ;
}
2010-02-16 01:04:48 -05:00
separator = sources . indexOf ( '--' ) ;
flags = [ ] ;
if ( separator >= 0 ) {
flags = sources . slice ( ( separator + 1 ) , sources . length ) ;
sources = sources . slice ( 0 , separator ) ;
}
process . ARGV = flags ;
2010-02-16 23:59:32 -05:00
if ( options . watch ) {
watch _scripts ( ) ;
}
2010-02-13 10:16:28 -05:00
compile _scripts ( ) ;
2010-02-11 01:57:33 -05:00
return this ;
} ;
// The "--help" usage message.
2010-02-13 10:16:28 -05:00
usage = function usage ( ) {
2010-02-14 15:16:33 -05:00
puts ( '\n' + option _parser . help ( ) + '\n' ) ;
2010-02-11 01:57:33 -05:00
return process . exit ( 0 ) ;
} ;
// The "--version" message.
2010-02-13 10:16:28 -05:00
version = function version ( ) {
2010-02-11 01:57:33 -05:00
puts ( "CoffeeScript version " + coffee . VERSION ) ;
return process . exit ( 0 ) ;
} ;
// Compiles the source CoffeeScript, returning the desired JavaScript, tokens,
// or JSLint results.
2010-02-13 10:16:28 -05:00
compile _scripts = function compile _scripts ( ) {
2010-02-16 23:59:32 -05:00
var source ;
2010-02-13 10:16:28 -05:00
if ( ! ( ( source = sources . shift ( ) ) ) ) {
2010-02-11 01:57:33 -05:00
return null ;
}
2010-02-21 14:06:01 -05:00
return fs . readFile ( source , function ( err , code ) {
2010-02-16 23:59:32 -05:00
compile _script ( source , code ) ;
return compile _scripts ( ) ;
} ) ;
} ;
// Compile a single source script, containing the given code, according to the
// requested options. Both compile_scripts and watch_scripts share this method.
compile _script = function compile _script ( source , code ) {
2010-02-21 13:48:38 -05:00
var js , o , opts ;
2010-02-16 23:59:32 -05:00
opts = options ;
2010-02-21 13:48:38 -05:00
o = opts . no _wrap ? {
no _wrap : true
} : { } ;
2010-02-16 23:59:32 -05:00
try {
2010-02-12 23:09:57 -05:00
if ( opts . tokens ) {
2010-02-16 23:59:32 -05:00
return coffee . print _tokens ( coffee . tokenize ( code ) ) ;
2010-02-13 09:39:25 -05:00
} else if ( opts . tree ) {
2010-02-16 23:59:32 -05:00
return puts ( coffee . tree ( code ) . toString ( ) ) ;
2010-02-12 23:09:57 -05:00
} else {
2010-02-21 13:48:38 -05:00
js = coffee . compile ( code , o ) ;
2010-02-13 09:39:25 -05:00
if ( opts . run ) {
2010-02-16 23:59:32 -05:00
return eval ( js ) ;
2010-02-13 09:39:25 -05:00
} else if ( opts . print ) {
2010-02-16 23:59:32 -05:00
return puts ( js ) ;
2010-02-13 09:39:25 -05:00
} else if ( opts . lint ) {
2010-02-16 23:59:32 -05:00
return lint ( js ) ;
2010-02-13 09:39:25 -05:00
} else {
2010-02-19 18:29:24 -05:00
return write _js ( source , js ) ;
2010-02-13 09:39:25 -05:00
}
2010-02-12 23:09:57 -05:00
}
2010-02-16 23:59:32 -05:00
} catch ( err ) {
if ( opts . watch ) {
return puts ( err . message ) ;
} else {
throw err ;
}
}
} ;
// Watch a list of source CoffeeScript files, recompiling them every time the
// files are updated.
watch _scripts = function watch _scripts ( ) {
var _a , _b , _c , source ;
_a = [ ] ; _b = sources ;
for ( _c = 0 ; _c < _b . length ; _c ++ ) {
source = _b [ _c ] ;
_a . push ( process . watchFile ( source , {
persistent : true ,
interval : 500
} , function ( curr , prev ) {
if ( curr . mtime . getTime ( ) === prev . mtime . getTime ( ) ) {
return null ;
}
2010-02-21 14:06:01 -05:00
return fs . readFile ( source , function ( err , code ) {
2010-02-16 23:59:32 -05:00
return compile _script ( source , code ) ;
} ) ;
} ) ) ;
}
return _a ;
2010-02-11 01:57:33 -05:00
} ;
2010-02-12 22:59:21 -05:00
// Write out a JavaScript source file with the compiled code.
2010-02-13 10:16:28 -05:00
write _js = function write _js ( source , js ) {
2010-02-12 22:59:21 -05:00
var dir , filename , js _path ;
filename = path . basename ( source , path . extname ( source ) ) + '.js' ;
2010-02-13 10:16:28 -05:00
dir = options . output || path . dirname ( source ) ;
2010-02-12 22:59:21 -05:00
js _path = path . join ( dir , filename ) ;
2010-02-19 18:27:50 -05:00
return fs . writeFile ( js _path , js ) ;
2010-02-12 22:59:21 -05:00
} ;
2010-02-12 23:09:57 -05:00
// Pipe compiled JS through JSLint (requires a working 'jsl' command).
2010-02-13 10:16:28 -05:00
lint = function lint ( js ) {
2010-02-12 23:09:57 -05:00
var jsl ;
jsl = process . createChildProcess ( 'jsl' , [ '-nologo' , '-stdin' ] ) ;
jsl . addListener ( 'output' , function ( result ) {
if ( result ) {
return puts ( result . replace ( /\n/g , '' ) ) ;
}
} ) ;
2010-02-12 23:10:51 -05:00
jsl . addListener ( 'error' , function ( result ) {
2010-02-12 23:09:57 -05:00
if ( result ) {
return puts ( result ) ;
}
} ) ;
jsl . write ( js ) ;
return jsl . close ( ) ;
} ;
2010-02-11 01:57:33 -05:00
// Use OptionParser for all the options.
2010-02-13 10:16:28 -05:00
parse _options = function parse _options ( ) {
2010-02-11 01:57:33 -05:00
var oparser , opts , paths ;
2010-02-13 10:16:28 -05:00
opts = ( options = { } ) ;
oparser = ( option _parser = new optparse . OptionParser ( SWITCHES ) ) ;
2010-02-13 10:07:59 -05:00
oparser . banner = BANNER ;
2010-02-11 01:57:33 -05:00
oparser . add ( 'interactive' , function ( ) {
return opts . interactive = true ;
} ) ;
oparser . add ( 'run' , function ( ) {
return opts . run = true ;
} ) ;
2010-02-14 15:16:33 -05:00
oparser . add ( 'output' , function ( dir ) {
2010-02-11 01:57:33 -05:00
return opts . output = dir ;
} ) ;
oparser . add ( 'watch' , function ( ) {
return opts . watch = true ;
} ) ;
oparser . add ( 'print' , function ( ) {
return opts . print = true ;
} ) ;
oparser . add ( 'lint' , function ( ) {
return opts . lint = true ;
} ) ;
oparser . add ( 'eval' , function ( ) {
return opts . eval = true ;
} ) ;
oparser . add ( 'tokens' , function ( ) {
return opts . tokens = true ;
} ) ;
2010-02-11 23:11:05 -05:00
oparser . add ( 'tree' , function ( ) {
return opts . tree = true ;
} ) ;
2010-02-21 13:48:38 -05:00
oparser . add ( 'no-wrap' , function ( ) {
return opts . no _wrap = true ;
} ) ;
2010-02-11 01:57:33 -05:00
oparser . add ( 'help' , ( function ( _ _this ) {
var _ _func = function ( ) {
2010-02-13 10:16:28 -05:00
return usage ( ) ;
2010-02-11 01:57:33 -05:00
} ;
return ( function ( ) {
return _ _func . apply ( _ _this , arguments ) ;
} ) ;
} ) ( this ) ) ;
oparser . add ( 'version' , ( function ( _ _this ) {
var _ _func = function ( ) {
2010-02-13 10:16:28 -05:00
return version ( ) ;
2010-02-11 01:57:33 -05:00
} ;
return ( function ( ) {
return _ _func . apply ( _ _this , arguments ) ;
} ) ;
} ) ( this ) ) ;
paths = oparser . parse ( process . ARGV ) ;
2010-02-13 10:16:28 -05:00
return sources = paths . slice ( 2 , paths . length ) ;
2010-02-11 01:57:33 -05:00
} ;
} ) ( ) ;