- Jump To … +
  browser.coffee cake.coffee coffee-script.coffee command.coffee grammar.coffee helpers.coffee index.coffee lexer.coffee nodes.coffee optparse.coffee register.coffee repl.coffee rewriter.coffee scope.litcoffee sourcemap.litcoffee

- # cake.coffee

- ¶

  `cake` is a simplified version of Make (Rake, 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 './coffee-script'

- ¶

  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()}"