2010-07-24 15:31:43 +00:00
( function ( ) {
2011-10-24 20:19:15 +00:00
var BANNER , CoffeeScript , EventEmitter , SWITCHES , compileJoin , compileOptions , compileScript , compileScripts , compileStdio , contents , exec , forkNode , fs , helpers , lint , loadRequires , optionParser , optparse , opts , parseOptions , path , printLine , printTokens , printWarn , sources , spawn , usage , version , watch , writeJs , _ref ;
2011-09-18 22:16:39 +00:00
2010-02-16 00:08:14 +00:00
fs = require ( 'fs' ) ;
2011-09-18 22:16:39 +00:00
2010-02-13 03:59:21 +00:00
path = require ( 'path' ) ;
2011-09-18 22:16:39 +00:00
2010-11-05 03:05:04 +00:00
helpers = require ( './helpers' ) ;
2011-09-18 22:16:39 +00:00
2010-03-16 03:39:46 +00:00
optparse = require ( './optparse' ) ;
2011-09-18 22:16:39 +00:00
2010-03-16 03:39:46 +00:00
CoffeeScript = require ( './coffee-script' ) ;
2011-09-18 22:16:39 +00:00
2010-09-28 20:47:12 +00:00
_ref = require ( 'child_process' ) , spawn = _ref . spawn , exec = _ref . exec ;
2011-09-18 22:16:39 +00:00
2010-09-28 20:47:12 +00:00
EventEmitter = require ( 'events' ) . EventEmitter ;
2011-09-18 22:16:39 +00:00
2010-09-25 08:39:19 +00:00
helpers . extend ( CoffeeScript , new EventEmitter ) ;
2011-09-18 22:16:39 +00:00
2011-10-24 20:19:15 +00:00
printLine = function ( line ) {
return process . stdout . write ( line + '\n' ) ;
} ;
printWarn = function ( line ) {
2011-10-27 15:23:03 +00:00
return process . stderr . write ( line + '\n' ) ;
2011-10-24 20:19:15 +00:00
} ;
2011-09-12 02:43:28 +00:00
BANNER = 'Usage: coffee [options] path/to/script.coffee\n\nIf called without options, `coffee` will run your script.' ;
2011-09-18 22:16:39 +00:00
2011-09-12 02:43:28 +00:00
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' ] , [ '-l' , '--lint' , 'pipe the compiled JavaScript through JavaScript Lint' ] , [ '-n' , '--nodes' , 'print out the parse tree that the parser produces' ] , [ '--nodejs [ARGS]' , 'pass options directly to the "node" binary' ] , [ '-o' , '--output [DIR]' , 'set the output directory for compiled JavaScript' ] , [ '-p' , '--print' , 'print out the compiled JavaScript' ] , [ '-r' , '--require [FILE*]' , 'require a library before executing your script' ] , [ '-s' , '--stdio' , 'listen for and compile scripts over stdio' ] , [ '-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' ] ] ;
2011-09-18 22:16:39 +00:00
2010-08-15 12:32:09 +00:00
opts = { } ;
2011-09-18 22:16:39 +00:00
2010-02-13 15:16:28 +00:00
sources = [ ] ;
2011-09-18 22:16:39 +00:00
2010-12-23 05:26:15 +00:00
contents = [ ] ;
2011-09-18 22:16:39 +00:00
2010-06-12 23:05:13 +00:00
optionParser = null ;
2011-09-18 22:16:39 +00:00
2011-05-01 03:01:36 +00:00
exports . run = function ( ) {
2010-06-12 23:05:13 +00:00
parseOptions ( ) ;
2011-08-07 06:59:37 +00:00
if ( opts . nodejs ) return forkNode ( ) ;
if ( opts . help ) return usage ( ) ;
if ( opts . version ) return version ( ) ;
if ( opts . require ) loadRequires ( ) ;
if ( opts . interactive ) return require ( './repl' ) ;
2011-11-10 14:11:27 +00:00
if ( opts . watch && ! fs . watch ) {
printWarn ( "The --watch feature depends on Node v0.6.0+. You are running " + process . version + "." ) ;
}
2011-08-07 06:59:37 +00:00
if ( opts . stdio ) return compileStdio ( ) ;
if ( opts . eval ) return compileScript ( null , sources [ 0 ] ) ;
if ( ! sources . length ) return require ( './repl' ) ;
if ( opts . run ) opts . literals = sources . splice ( 1 ) . concat ( opts . literals ) ;
2011-11-05 14:34:44 +00:00
process . argv = process . argv . slice ( 0 , 2 ) . concat ( opts . literals ) ;
2011-04-30 14:59:55 +00:00
process . argv [ 0 ] = 'coffee' ;
2011-05-01 17:45:47 +00:00
process . execPath = require . main . filename ;
2010-06-12 23:05:13 +00:00
return compileScripts ( ) ;
2010-02-11 06:57:33 +00:00
} ;
2011-09-18 22:16:39 +00:00
2010-06-12 23:05:13 +00:00
compileScripts = function ( ) {
2011-08-22 17:32:54 +00:00
var base , compile , remaining _files , source , trackCompleteFiles , trackUnprocessedFiles , unprocessed , _i , _j , _len , _len2 , _results ;
2011-06-23 08:26:54 +00:00
unprocessed = [ ] ;
2011-08-22 17:32:54 +00:00
remaining _files = function ( ) {
var total , x , _i , _len ;
total = 0 ;
for ( _i = 0 , _len = unprocessed . length ; _i < _len ; _i ++ ) {
x = unprocessed [ _i ] ;
total += x ;
}
return total ;
} ;
trackUnprocessedFiles = function ( sourceIndex , fileCount ) {
var _ref2 ;
if ( ( _ref2 = unprocessed [ sourceIndex ] ) == null ) unprocessed [ sourceIndex ] = 0 ;
return unprocessed [ sourceIndex ] += fileCount ;
} ;
trackCompleteFiles = function ( sourceIndex , fileCount ) {
unprocessed [ sourceIndex ] -= fileCount ;
if ( opts . join ) {
if ( helpers . compact ( contents ) . length > 0 && remaining _files ( ) === 0 ) {
return compileJoin ( ) ;
}
}
} ;
2010-12-21 20:45:46 +00:00
for ( _i = 0 , _len = sources . length ; _i < _len ; _i ++ ) {
source = sources [ _i ] ;
2011-08-22 17:32:54 +00:00
trackUnprocessedFiles ( sources . indexOf ( source ) , 1 ) ;
2011-06-23 08:26:54 +00:00
}
_results = [ ] ;
for ( _j = 0 , _len2 = sources . length ; _j < _len2 ; _j ++ ) {
source = sources [ _j ] ;
2010-10-24 05:36:23 +00:00
base = path . join ( source ) ;
2011-05-24 19:01:35 +00:00
compile = function ( source , sourceIndex , topLevel ) {
2010-10-24 05:36:23 +00:00
return path . exists ( source , function ( exists ) {
2011-08-08 16:55:22 +00:00
if ( topLevel && ! exists && source . slice ( - 7 ) !== '.coffee' ) {
2011-08-08 16:27:53 +00:00
return compile ( "" + source + ".coffee" , sourceIndex , topLevel ) ;
2011-08-08 16:55:22 +00:00
}
2011-08-07 06:59:37 +00:00
if ( topLevel && ! exists ) throw new Error ( "File not found: " + source ) ;
2010-10-24 05:36:23 +00:00
return fs . stat ( source , function ( err , stats ) {
2011-08-07 06:59:37 +00:00
if ( err ) throw err ;
2010-10-24 05:36:23 +00:00
if ( stats . isDirectory ( ) ) {
return fs . readdir ( source , function ( err , files ) {
2011-06-23 08:26:54 +00:00
var file , _k , _len3 ;
2011-08-07 06:59:37 +00:00
if ( err ) throw err ;
2011-08-22 17:32:54 +00:00
trackUnprocessedFiles ( sourceIndex , files . length ) ;
2011-06-23 08:26:54 +00:00
for ( _k = 0 , _len3 = files . length ; _k < _len3 ; _k ++ ) {
file = files [ _k ] ;
compile ( path . join ( source , file ) , sourceIndex ) ;
2010-10-24 05:36:23 +00:00
}
2011-08-22 17:32:54 +00:00
return trackCompleteFiles ( sourceIndex , 1 ) ;
2010-10-24 05:36:23 +00:00
} ) ;
} else if ( topLevel || path . extname ( source ) === '.coffee' ) {
fs . readFile ( source , function ( err , code ) {
2011-08-07 06:59:37 +00:00
if ( err ) throw err ;
2010-12-23 05:26:15 +00:00
if ( opts . join ) {
2011-05-24 19:01:35 +00:00
contents [ sourceIndex ] = helpers . compact ( [ contents [ sourceIndex ] , code . toString ( ) ] ) . join ( '\n' ) ;
2010-12-23 05:26:15 +00:00
} else {
2011-08-22 17:32:54 +00:00
compileScript ( source , code . toString ( ) , base ) ;
2010-12-23 05:26:15 +00:00
}
2011-08-22 17:32:54 +00:00
return trackCompleteFiles ( sourceIndex , 1 ) ;
2010-10-24 05:36:23 +00:00
} ) ;
2011-08-07 06:59:37 +00:00
if ( opts . watch && ! opts . join ) return watch ( source , base ) ;
2011-06-23 08:26:54 +00:00
} else {
2011-08-22 17:32:54 +00:00
return trackCompleteFiles ( sourceIndex , 1 ) ;
2010-10-13 11:29:22 +00:00
}
} ) ;
2010-10-24 05:36:23 +00:00
} ) ;
} ;
2011-05-24 19:01:35 +00:00
_results . push ( compile ( source , sources . indexOf ( source ) , true ) ) ;
2010-02-11 06:57:33 +00:00
}
2010-11-09 05:17:08 +00:00
return _results ;
2010-02-17 04:59:32 +00:00
} ;
2011-09-18 22:16:39 +00:00
2010-08-15 12:32:09 +00:00
compileScript = function ( file , input , base ) {
2011-01-13 19:50:00 +00:00
var o , options , t , task ;
2010-08-15 12:32:09 +00:00
o = opts ;
options = compileOptions ( file ) ;
2010-02-17 04:59:32 +00:00
try {
2010-10-20 17:29:06 +00:00
t = task = {
2010-08-15 12:32:09 +00:00
file : file ,
input : input ,
options : options
2010-10-20 17:29:06 +00:00
} ;
2010-08-15 12:32:09 +00:00
CoffeeScript . emit ( 'compile' , task ) ;
2010-02-24 23:56:32 +00:00
if ( o . tokens ) {
2010-08-15 12:32:09 +00:00
return printTokens ( CoffeeScript . tokens ( t . input ) ) ;
2010-02-25 23:42:35 +00:00
} else if ( o . nodes ) {
2011-10-24 20:19:15 +00:00
return printLine ( CoffeeScript . nodes ( t . input ) . toString ( ) . trim ( ) ) ;
2010-03-08 02:49:08 +00:00
} else if ( o . run ) {
2010-08-15 12:32:09 +00:00
return CoffeeScript . run ( t . input , t . options ) ;
2010-02-13 04:09:57 +00:00
} else {
2010-08-15 12:32:09 +00:00
t . output = CoffeeScript . compile ( t . input , t . options ) ;
2010-08-12 22:28:38 +00:00
CoffeeScript . emit ( 'success' , task ) ;
2010-11-09 04:07:51 +00:00
if ( o . print ) {
2011-10-24 20:19:15 +00:00
return printLine ( t . output . trim ( ) ) ;
2010-11-09 04:07:51 +00:00
} else if ( o . compile ) {
return writeJs ( t . file , t . output , base ) ;
} else if ( o . lint ) {
return lint ( t . file , t . output ) ;
}
2010-02-13 04:09:57 +00:00
}
2010-02-17 04:59:32 +00:00
} catch ( err ) {
2010-08-12 22:28:38 +00:00
CoffeeScript . emit ( 'failure' , err , task ) ;
2011-08-07 06:59:37 +00:00
if ( CoffeeScript . listeners ( 'failure' ) . length ) return ;
2011-10-24 20:19:15 +00:00
if ( o . watch ) return printLine ( err . message ) ;
printWarn ( err instanceof Error && err . stack || ( "ERROR: " + err ) ) ;
2010-08-15 12:32:09 +00:00
return process . exit ( 1 ) ;
2010-02-17 04:59:32 +00:00
}
} ;
2011-09-18 22:16:39 +00:00
2010-06-12 23:05:13 +00:00
compileStdio = function ( ) {
2010-04-10 22:05:35 +00:00
var code , stdin ;
2010-02-24 23:18:29 +00:00
code = '' ;
2010-04-10 22:05:35 +00:00
stdin = process . openStdin ( ) ;
2010-07-18 11:54:44 +00:00
stdin . on ( 'data' , function ( buffer ) {
2011-08-07 06:59:37 +00:00
if ( buffer ) return code += buffer . toString ( ) ;
2010-02-24 23:18:29 +00:00
} ) ;
2010-07-18 11:54:44 +00:00
return stdin . on ( 'end' , function ( ) {
2010-11-06 13:21:45 +00:00
return compileScript ( null , code ) ;
2010-02-24 23:18:29 +00:00
} ) ;
} ;
2011-09-18 22:16:39 +00:00
2010-12-23 05:26:15 +00:00
compileJoin = function ( ) {
var code ;
code = contents . join ( '\n' ) ;
2011-04-28 03:06:58 +00:00
return compileScript ( opts . join , code , opts . join ) ;
2010-12-23 05:26:15 +00:00
} ;
2011-09-18 22:16:39 +00:00
2011-01-15 15:46:53 +00:00
loadRequires = function ( ) {
2011-03-28 21:12:27 +00:00
var realFilename , req , _i , _len , _ref2 ;
2011-01-15 15:46:53 +00:00
realFilename = module . filename ;
module . filename = '.' ;
2011-03-28 21:12:27 +00:00
_ref2 = opts . require ;
for ( _i = 0 , _len = _ref2 . length ; _i < _len ; _i ++ ) {
req = _ref2 [ _i ] ;
2011-01-15 15:46:53 +00:00
require ( req ) ;
}
return module . filename = realFilename ;
} ;
2011-09-18 22:16:39 +00:00
2010-05-15 03:40:04 +00:00
watch = function ( source , base ) {
2011-11-10 14:11:27 +00:00
if ( ! fs . watch ) return ;
2011-11-08 21:13:45 +00:00
return fs . stat ( source , function ( err , prevStats ) {
2011-11-09 18:54:43 +00:00
var callback , watcher ;
2011-11-08 21:13:45 +00:00
if ( err ) throw err ;
2011-11-09 18:54:43 +00:00
return watcher = fs . watch ( source , callback = function ( event ) {
2011-11-09 18:49:14 +00:00
if ( event === 'rename' ) {
2011-11-09 18:54:43 +00:00
watcher . close ( ) ;
2011-11-10 13:44:48 +00:00
try {
return watcher = fs . watch ( source , callback ) ;
} catch ( _error ) { }
2011-11-09 18:49:14 +00:00
} else if ( event === 'change' ) {
2011-11-08 21:13:45 +00:00
return fs . stat ( source , function ( err , stats ) {
if ( err ) throw err ;
if ( stats . size === prevStats . size && stats . mtime . getTime ( ) === prevStats . mtime . getTime ( ) ) {
return ;
}
prevStats = stats ;
return fs . readFile ( source , function ( err , code ) {
if ( err ) throw err ;
return compileScript ( source , code . toString ( ) , base ) ;
} ) ;
} ) ;
}
2010-02-22 00:59:27 +00:00
} ) ;
2010-05-03 21:38:59 +00:00
} ) ;
2010-02-11 06:57:33 +00:00
} ;
2011-09-18 22:16:39 +00:00
2010-06-12 23:05:13 +00:00
writeJs = function ( source , js , base ) {
var baseDir , compile , dir , filename , jsPath , srcDir ;
2010-02-13 03:59:21 +00:00
filename = path . basename ( source , path . extname ( source ) ) + '.js' ;
2010-06-12 23:05:13 +00:00
srcDir = path . dirname ( source ) ;
2010-12-23 22:34:50 +00:00
baseDir = base === '.' ? srcDir : srcDir . substring ( base . length ) ;
2010-08-15 12:32:09 +00:00
dir = opts . output ? path . join ( opts . output , baseDir ) : srcDir ;
2010-06-12 23:05:13 +00:00
jsPath = path . join ( dir , filename ) ;
2010-05-15 03:40:04 +00:00
compile = function ( ) {
2011-08-07 06:59:37 +00:00
if ( js . length <= 0 ) js = ' ' ;
2010-06-13 18:21:02 +00:00
return fs . writeFile ( jsPath , js , function ( err ) {
2010-11-09 04:07:51 +00:00
if ( err ) {
2011-10-24 20:19:15 +00:00
return printLine ( err . message ) ;
2010-11-09 04:07:51 +00:00
} else if ( opts . compile && opts . watch ) {
2011-01-20 03:17:53 +00:00
return console . log ( "" + ( ( new Date ) . toLocaleTimeString ( ) ) + " - compiled " + source ) ;
2010-11-09 04:07:51 +00:00
}
2010-06-13 18:21:02 +00:00
} ) ;
2010-05-05 03:22:28 +00:00
} ;
return path . exists ( dir , function ( exists ) {
2010-11-09 04:07:51 +00:00
if ( exists ) {
return compile ( ) ;
} else {
return exec ( "mkdir -p " + dir , compile ) ;
}
2010-05-03 21:38:59 +00:00
} ) ;
2010-02-13 03:59:21 +00:00
} ;
2011-09-18 22:16:39 +00:00
2010-10-25 00:51:55 +00:00
lint = function ( file , js ) {
2010-08-14 20:02:01 +00:00
var conf , jsl , printIt ;
2010-06-12 23:05:13 +00:00
printIt = function ( buffer ) {
2011-10-24 20:19:15 +00:00
return printLine ( file + ':\t' + buffer . toString ( ) . trim ( ) ) ;
2010-04-10 22:05:35 +00:00
} ;
2011-11-08 21:04:10 +00:00
conf = _ _dirname + '/../../extras/jsl.conf' ;
2010-08-14 20:02:01 +00:00
jsl = spawn ( 'jsl' , [ '-nologo' , '-stdin' , '-conf' , conf ] ) ;
2010-07-18 11:54:44 +00:00
jsl . stdout . on ( 'data' , printIt ) ;
jsl . stderr . on ( 'data' , printIt ) ;
2010-04-10 22:05:35 +00:00
jsl . stdin . write ( js ) ;
return jsl . stdin . end ( ) ;
2010-02-13 04:09:57 +00:00
} ;
2011-09-18 22:16:39 +00:00
2010-06-12 23:05:13 +00:00
printTokens = function ( tokens ) {
2010-12-14 02:24:32 +00:00
var strings , tag , token , value ;
2010-12-23 18:50:52 +00:00
strings = ( function ( ) {
2011-03-28 21:12:27 +00:00
var _i , _len , _ref2 , _results ;
2010-11-09 05:17:08 +00:00
_results = [ ] ;
2010-10-22 01:51:06 +00:00
for ( _i = 0 , _len = tokens . length ; _i < _len ; _i ++ ) {
2010-10-01 22:26:37 +00:00
token = tokens [ _i ] ;
2011-03-28 21:12:27 +00:00
_ref2 = [ token [ 0 ] , token [ 1 ] . toString ( ) . replace ( /\n/ , '\\n' ) ] , tag = _ref2 [ 0 ] , value = _ref2 [ 1 ] ;
2010-11-09 05:17:08 +00:00
_results . push ( "[" + tag + " " + value + "]" ) ;
2010-02-24 23:56:32 +00:00
}
2010-11-09 05:17:08 +00:00
return _results ;
2010-12-23 18:50:52 +00:00
} ) ( ) ;
2011-10-24 20:19:15 +00:00
return printLine ( strings . join ( ' ' ) ) ;
2010-02-24 23:56:32 +00:00
} ;
2011-09-18 22:16:39 +00:00
2010-06-12 23:05:13 +00:00
parseOptions = function ( ) {
2010-03-08 02:49:08 +00:00
var o ;
2010-12-18 14:29:04 +00:00
optionParser = new optparse . OptionParser ( SWITCHES , BANNER ) ;
2010-10-20 17:29:06 +00:00
o = opts = optionParser . parse ( process . argv . slice ( 2 ) ) ;
2010-10-01 22:17:35 +00:00
o . compile || ( o . compile = ! ! o . output ) ;
2010-08-15 12:32:09 +00:00
o . run = ! ( o . compile || o . print || o . lint ) ;
o . print = ! ! ( o . print || ( o . eval || o . stdio && o . compile ) ) ;
2010-12-18 14:29:04 +00:00
return sources = o . arguments ;
2010-02-11 06:57:33 +00:00
} ;
2011-09-18 22:16:39 +00:00
2011-01-15 15:46:53 +00:00
compileOptions = function ( filename ) {
2010-10-13 19:09:56 +00:00
return {
2011-01-15 15:46:53 +00:00
filename : filename ,
2010-12-18 14:29:04 +00:00
bare : opts . bare
2010-03-08 03:08:24 +00:00
} ;
2010-02-24 23:18:29 +00:00
} ;
2011-09-18 22:16:39 +00:00
2010-12-18 14:29:04 +00:00
forkNode = function ( ) {
var args , nodeArgs ;
nodeArgs = opts . nodejs . split ( /\s+/ ) ;
args = process . argv . slice ( 1 ) ;
args . splice ( args . indexOf ( '--nodejs' ) , 2 ) ;
return spawn ( process . execPath , nodeArgs . concat ( args ) , {
2010-12-17 07:39:39 +00:00
cwd : process . cwd ( ) ,
env : process . env ,
customFds : [ 0 , 1 , 2 ]
} ) ;
} ;
2011-09-18 22:16:39 +00:00
2010-05-15 03:40:04 +00:00
usage = function ( ) {
2011-10-24 20:19:15 +00:00
return printLine ( ( new optparse . OptionParser ( SWITCHES , BANNER ) ) . help ( ) ) ;
2010-03-07 05:28:58 +00:00
} ;
2011-09-18 22:16:39 +00:00
2010-05-15 03:40:04 +00:00
version = function ( ) {
2011-10-24 20:19:15 +00:00
return printLine ( "CoffeeScript version " + CoffeeScript . VERSION ) ;
2010-03-07 05:28:58 +00:00
} ;
2011-09-18 22:16:39 +00:00
2010-09-21 07:53:58 +00:00
} ) . call ( this ) ;