Tapfile

Path: doc/Examples/Tapfile
Last Update: Tue May 04 23:26:16 -0600 2010

Tapfile

Tapfiles can be used to define tasks and workflows. Typically using the Tap::Declarations module which provides a syntax reminiscent of Rake.

  [tapfile]
  # A task declaration looks like this. The declaration creates a subclass of
  # Tap::Task, literally this:
  #
  #   class Goodnight < Tap::Task
  #     config :msg, 'goodnight'
  #     def process(thing)
  #       "#{msg} #{thing}!"
  #     end
  #   end
  #
  # The 'config' passed to the block is actually the task instance but it's
  # useful to think of it as a source of configs.  Note these comments are
  # meaningful, if present they become the task help.

  desc "a goodnight task"
  task :goodnight, :msg => 'goodnight' do |config, thing|
    "#{config.msg} #{thing}!"
  end

  # Use namespace to set tasks within a module.
  namespace :example do
    desc "concat files"
    task :cat do |config, *paths|
      paths.collect {|path| File.read(path) }.join
    end

    desc "sort a string by line"
    task :sort, :reverse => false do |config, str|
      lines = str.split("\n").sort
      config.reverse ? lines.reverse : lines
    end
  end

  # Use workflow to create a subclass of Tap::Workflow.  Access any tasks you
  # define in the workflow using node and return the tasks you want to use as
  # the entry/exit points for the workflow.

  desc "sort the lines of a file"
  work :sort_file, %q{
    -   cat
    -:a sort
    -:i dump
  },{
    :reverse => false
  } do |config|
    n0 = node(0)    # cat
    n1 = node(1)    # sort
    n1.reverse = config.reverse
    [n0, n1]
  end

  # Tasks defined in a singleton block will only execute once (given a set
  # of inputs) and can be used to make dependency-based workflows.

  singleton do
    task(:a)             { puts 'a' }
    task(:b => :a)       { puts 'b' }
    task(:c => [:b, :a]) { puts 'c' }
  end

Declaration tasks are available for use in workflows:

  % tap goodnight moon -: dump
  goodnight moon!
  % tap goodnight world --msg hello -: dump
  hello world!

And documented:

  % tap goodnight --help
  Tapfile::Goodnight -- a goodnight task
  --------------------------------------------------------------------------------
    A task declaration looks like this. The declaration creates a subclass of
    Tap::Task, literally this:

      class Goodnight < Tap::Task
        config :msg, 'goodnight'
        def process(thing)
          "#{msg} #{thing}!"
        end
      end

    The 'config' passed to the block is actually the task instance but it's
    useful to think of it as a source of configs.  Note these comments are
    meaningful, if present they become the task help.
  --------------------------------------------------------------------------------
  usage: tap tapfile/goodnight arg

  configurations:
          --msg MSG

  options:
          --help                       Print this help
          --config FILE                Specifies a config file

Workflows work just like tasks:

  % tap sort_file tapfile --reverse true
  work :sort_file, :reverse => false do |config|
  task :goodnight, :msg => 'goodnight' do |config, thing|
  ...

  % order c a b
  a b c

Singleton tasks can be used to create dependency-based workflows that function much like rake tasks in practice:

  % tap c
  a
  b
  c
  % tap b -- a
  a
  b

See Tap::Declarations for syntax details.

[Validate]