Class: Tap::Generator::Base

Inherits:
Task show all
Defined in:
lib/tap/generator/base.rb

Overview

:startdoc:::- Base provides the basic structure of a generator and custom generators inherit from it. Base is patterned after the Ruby on Rails generators, but obviously takes on all the advantages of Tasks.

Usage

Tap generators define a manifest method that defines what files and directories are created by the generator. Then, at execution time, a mixin with the appropriate funtion (ie Generate or Destory) is overlaid to figure out how to roll those actions forward or backwards.

Unlike typical tasks, generators must be named like ‘<Name>Generator’ and are identified using the ::generator flag rather than ::manifest. These requirements make generators available to the generate/destroy commands and not run.

Typically, generators live in a directory structure like this:

sample
|- sample_generator.rb
`- templates
    `- template_file.erb

And take the form:

[sample/sample_generator.rb]
require 'tap/generator/base'

# SampleGenerator::generator generates a directory, and two files
#
# An extended description of the
# generator goes here...
#
class SampleGenerator < Tap::Generator::Base

  config :key, 'value'       # a sample config

  def manifest(m, *args)
    # make a directory
    m.directory('path/to/dir')

    # make a file
    m.file('path/to/file.txt') do |file|
      file << "some content"
    end

    # template a file using config
    m.template('path/to/result.txt', 'template_file.erb', config.to_hash)
  end
end

As with any task, generators can have configurations and take arguments specified by manifest (minus the ‘m’ argument which is standard).

Creating directories and files is straightforward, as above. The template function a target file using the source file in the ‘templates’ directory; any attributes specified by the last argument will be available in the erb template. :startdoc:::+

Constant Summary

Constants inherited from Task

Task::DEFAULT_HELP_TEMPLATE

Instance Attribute Summary collapse

Attributes inherited from Task

#name

Attributes included from Support::Executable

#app, #batch, #dependencies, #method_name, #on_complete_block

Instance Method Summary collapse

Methods inherited from Task

execute, help, inherited, #initialize_batch_obj, #inspect, instance, intern, load, #log, parse, parse!, #to_s, use

Methods included from Support::Executable

#_execute, #batch_index, #batch_with, #batched?, #check_terminate, #depends_on, #enq, #execute, #fork, initialize, #initialize_batch_obj, #merge, #on_complete, #reset_dependencies, #resolve_dependencies, #sequence, #switch, #sync_merge, #unbatched_depends_on, #unbatched_enq, #unbatched_on_complete

Constructor Details

#initialize(*args) ⇒ Base

Returns a new instance of Base.



85
86
87
88
89
90
# File 'lib/tap/generator/base.rb', line 85

def initialize(*args)
  super
  @prompt_in = $stdin
  @prompt_out = $stdout
  @template_dir = File.dirname(self.class.source_file) + '/templates'
end

Instance Attribute Details

#prompt_inObject

The IO used to pull prompt inputs (default: $stdin)



80
81
82
# File 'lib/tap/generator/base.rb', line 80

def prompt_in
  @prompt_in
end

#prompt_outObject

The IO used to prompt users for input (default: $stdout)



83
84
85
# File 'lib/tap/generator/base.rb', line 83

def prompt_out
  @prompt_out
end

#template_dirObject

The generator-specific templates directory. By default: ‘path/to/name/templates’ for ‘path/to/name/name_generator.rb’



77
78
79
# File 'lib/tap/generator/base.rb', line 77

def template_dir
  @template_dir
end

Instance Method Details

#directories(root, targets, options = {}) ⇒ Object

Makes (or destroys) the root and each of the targets, relative to root. Options are passed onto directory.



129
130
131
132
133
134
# File 'lib/tap/generator/base.rb', line 129

def directories(root, targets, options={})
  directory(root, options)
  targets.each do |target|
    directory(File.join(root, target), options)
  end
end

#directory(target, options = {}) ⇒ Object

Peforms a directory action (ex generate or destroy). Must be overridden by one of the action mixins (ex Generate or Destroy).

Raises:

  • (NotImplementedError)


117
118
119
# File 'lib/tap/generator/base.rb', line 117

def directory(target, options={})
  raise NotImplementedError
end

#file(target, options = {}) ⇒ Object

Peforms a file action (ex generate or destroy). Must be overridden by one of the action mixins (ex Generate or Destroy).

Raises:

  • (NotImplementedError)


123
124
125
# File 'lib/tap/generator/base.rb', line 123

def file(target, options={})
  raise NotImplementedError
end

#iterate(actions) ⇒ Object

Peforms each of the input actions. Overridden by one of the action mixins (ex Generate or Destory).

Raises:

  • (NotImplementedError)


111
112
113
# File 'lib/tap/generator/base.rb', line 111

def iterate(actions)
  raise NotImplementedError
end

#log_relative(action, path) ⇒ Object

Logs the action with the relative filepath from Dir.pwd to path.



160
161
162
# File 'lib/tap/generator/base.rb', line 160

def log_relative(action, path)
  log(action, Root.relative_filepath(Dir.pwd, path))
end

#manifest(m, *argv) ⇒ Object

Overridden in subclasses to add actions to the input Manifest. Any arguments passed to process will be passed to manifest unchanged.

Raises:

  • (NotImplementedError)


105
106
107
# File 'lib/tap/generator/base.rb', line 105

def manifest(m, *argv)
  raise NotImplementedError
end

#process(*argv) ⇒ Object

Builds the manifest, then executes the actions of the manifest.



93
94
95
96
97
98
99
100
# File 'lib/tap/generator/base.rb', line 93

def process(*argv)
  actions = []
  manifest(Manifest.new(actions), *argv)
  
  iterate(actions) do |action, args, block|
    send(action, *args, &block)
  end
end

#template(target, source, attributes = {}, options = {}) ⇒ Object

Makes (or destroys) the target by templating the source using the specified attributes. Source is expanded relative to template_dir. Options are passed onto file.



139
140
141
142
143
144
145
146
# File 'lib/tap/generator/base.rb', line 139

def template(target, source, attributes={}, options={})
  template_path = File.expand_path(source, template_dir)
  templater = Support::Templater.new(File.read(template_path), attributes)
  
  file(target, options) do |file| 
    file << templater.build
  end
end

#template_filesObject

Yields each source file under template_dir to the block, with a target path of the source relative to template_dir.



150
151
152
153
154
155
156
157
# File 'lib/tap/generator/base.rb', line 150

def template_files
  Dir.glob(template_dir + "/**/*").sort.each do |source|
    next unless File.file?(source)
    
    target = Tap::Root.relative_filepath(template_dir, source)
    yield(source, target)
  end
end