/src/cake.coffee
CoffeeScript | 88 lines | 51 code | 12 blank | 25 comment | 7 complexity | e722c6667fddfa73f29ca27743df2510 MD5 | raw file
- # `cake` is a simplified version of [Make](http://www.gnu.org/software/make/)
- # ([Rake](http://rake.rubyforge.org/), [Jake](https://github.com/280north/jake))
- # for CoffeeScript. You define tasks with names and descriptions in a Cakefile,
- # and can call them from the command line, or invoke them from other tasks.
- #
- # Running `cake` with no arguments will print out a list of all the tasks in the
- # current directory's Cakefile.
- # External dependencies.
- fs = require 'fs'
- path = require 'path'
- helpers = require './helpers'
- optparse = require './optparse'
- CoffeeScript = require './'
- # Register .coffee extension
- CoffeeScript.register()
- # Keep track of the list of defined tasks, the accepted options, and so on.
- tasks = {}
- options = {}
- switches = []
- oparse = null
- # Mixin the top-level Cake functions for Cakefiles to use directly.
- helpers.extend global,
- # Define a Cake task with a short name, an optional sentence description,
- # and the function to run as the action itself.
- task: (name, description, action) ->
- [action, description] = [description, action] unless action
- tasks[name] = {name, description, action}
- # Define an option that the Cakefile accepts. The parsed options hash,
- # containing all of the command-line options passed, will be made available
- # as the first argument to the action.
- option: (letter, flag, description) ->
- switches.push [letter, flag, description]
- # Invoke another task in the current Cakefile.
- invoke: (name) ->
- missingTask name unless tasks[name]
- tasks[name].action options
- # Run `cake`. Executes all of the tasks you pass, in order. Note that Node's
- # asynchrony may cause tasks to execute in a different order than you'd expect.
- # If no tasks are passed, print the help screen. Keep a reference to the
- # original directory name, when running Cake tasks from subdirectories.
- exports.run = ->
- global.__originalDirname = fs.realpathSync '.'
- process.chdir cakefileDirectory __originalDirname
- args = process.argv[2..]
- CoffeeScript.run fs.readFileSync('Cakefile').toString(), filename: 'Cakefile'
- oparse = new optparse.OptionParser switches
- return printTasks() unless args.length
- try
- options = oparse.parse(args)
- catch e
- return fatalError "#{e}"
- invoke arg for arg in options.arguments
- # Display the list of Cake tasks in a format similar to `rake -T`
- printTasks = ->
- relative = path.relative or path.resolve
- cakefilePath = path.join relative(__originalDirname, process.cwd()), 'Cakefile'
- console.log "#{cakefilePath} defines the following tasks:\n"
- for name, task of tasks
- spaces = 20 - name.length
- spaces = if spaces > 0 then Array(spaces + 1).join(' ') else ''
- desc = if task.description then "# #{task.description}" else ''
- console.log "cake #{name}#{spaces} #{desc}"
- console.log oparse.help() if switches.length
- # Print an error and exit when attempting to use an invalid task/option.
- fatalError = (message) ->
- console.error message + '\n'
- console.log 'To see a list of all tasks/options, run "cake"'
- process.exit 1
- missingTask = (task) -> fatalError "No such task: #{task}"
- # When `cake` is invoked, search in the current and all parent directories
- # to find the relevant Cakefile.
- cakefileDirectory = (dir) ->
- return dir if fs.existsSync path.join dir, 'Cakefile'
- parent = path.normalize path.join dir, '..'
- return cakefileDirectory parent unless parent is dir
- throw new Error "Cakefile not found in #{process.cwd()}"