Class: Tap::Generator::Base
- Inherits:
-
Task
- Object
- Task
- Tap::Generator::Base
- Extended by:
- Helpers
- 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 Destroy) is overlaid to figure out how to roll those actions forward or backwards.
Generators are identified using the ::generator flag rather than ::task, so that generators are available to the generate/destroy commands and not run.
Typically, generators live in a directory structure like this:
root
|- lib
| `- sample.rb
|
`- templates
`- sample
`- template_file.erb
Tap generators keep templates out of lib and under templates, in a directory is named after the generator class. Generators themselves take the form:
[sample.rb]
require 'tap/generator/base'
# ::generator generates a directory, and two files
#
# An extended description of the
# generator goes here...
#
class Sample < 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
m.template('path/to/result.txt', 'template_file.erb', config.to_hash)
end
end
The arguments that a generator receives are specified by manifest (minus the ‘m’ argument which is standard) rather than process. Creating directories and files is straightforward, as above. Template renders the erb source file using attributes specified in the last argument; in the example template uses the generator configurations.
:startdoc:::+
Direct Known Subclasses
Generators::Config, Generators::Env, Generators::Resource, Generators::Root, Generators::Tap
Instance Attribute Summary collapse
-
#prompt_in ⇒ Object
The IO used to pull prompt inputs (default: $stdin).
-
#prompt_out ⇒ Object
The IO used to prompt users for input (default: $stdout).
Attributes included from Helpers
Class Method Summary collapse
- .build(spec = {}, app = Tap::App.current) ⇒ Object
- .convert_to_spec(parser, args) ⇒ Object
- .parse_as(mixin, argv = ARGV, app = Tap::App.current, &block) ⇒ Object
Instance Method Summary collapse
-
#action ⇒ Object
Returns the action for self (ie :generate or :destroy).
-
#directories(root, targets, options = {}) ⇒ Object
Makes (or destroys) the root and each of the targets, relative to root.
-
#directory(target, options = {}) ⇒ Object
Peforms a directory action (ex generate or destroy).
-
#file(target, options = {}) ⇒ Object
Peforms a file action (ex generate or destroy).
-
#initialize(config = {}, app = Tap::App.current) ⇒ Base
constructor
A new instance of Base.
-
#iterate(actions) ⇒ Object
Peforms each of the input actions in order, and collects the results.
-
#log_relative(action, path) ⇒ Object
Logs the action with the relative filepath from destination_root to path.
-
#manifest(m, *argv) ⇒ Object
Overridden in subclasses to add actions to the input Manifest.
-
#on(*actions, &block) ⇒ Object
Calls the block when specified by the action for self.
-
#path(*paths) ⇒ Object
Constructs a path relative to destination_root.
-
#process(*argv) ⇒ Object
Builds the manifest, then executes the actions of the manifest.
-
#template(target, source, attributes = {}, options = {}) ⇒ Object
Makes (or destroys) the target by templating the source using the specified attributes.
-
#template_files ⇒ Object
Yields each source file under template_root to the block, with a target path of the source relative to template_root.
Methods included from Helpers
Constructor Details
#initialize(config = {}, app = Tap::App.current) ⇒ Base
Returns a new instance of Base.
149 150 151 152 153 |
# File 'lib/tap/generator/base.rb', line 149 def initialize(config={}, app=Tap::App.current) super @prompt_in = $stdin @prompt_out = $stdout end |
Instance Attribute Details
#prompt_in ⇒ Object
The IO used to pull prompt inputs (default: $stdin)
144 145 146 |
# File 'lib/tap/generator/base.rb', line 144 def prompt_in @prompt_in end |
#prompt_out ⇒ Object
The IO used to prompt users for input (default: $stdout)
147 148 149 |
# File 'lib/tap/generator/base.rb', line 147 def prompt_out @prompt_out end |
Class Method Details
.build(spec = {}, app = Tap::App.current) ⇒ Object
101 102 103 104 105 106 107 108 109 |
# File 'lib/tap/generator/base.rb', line 101 def build(spec={}, app=Tap::App.current) obj = new(spec['config'] || {}, app) if mixin = spec['mixin'] obj.extend app.env.constant(mixin) end obj end |
.convert_to_spec(parser, args) ⇒ Object
111 112 113 114 115 116 |
# File 'lib/tap/generator/base.rb', line 111 def convert_to_spec(parser, args) { 'config' => parser.nested_config, 'mixin' => args.shift } end |
.parse_as(mixin, argv = ARGV, app = Tap::App.current, &block) ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/tap/generator/base.rb', line 78 def parse_as(mixin, argv=ARGV, app=Tap::App.current, &block) if argv.empty? raise "no generator specified" end if argv[0] == '--help' desc = mixin.desc lines = ["#{mixin}#{desc.empty? ? '' : ' -- '}#{desc.to_s}"] lines << '-' * 80 lines.concat desc.wrap(77, 2, nil).collect {|line| " #{line}"} lines << '-' * 80 lines << "usage: tap #{mixin.to_s.underscore} generator *args" lines << '' lines.concat Tasks::List.new(:types => ['generator']).manifest raise lines.join("\n") end argv = argv.dup generator = argv.shift argv.unshift mixin app.env.constant(generator, 'generator').parse(argv, app, &block) end |
Instance Method Details
#action ⇒ Object
Returns the action for self (ie :generate or :destroy)
249 250 251 |
# File 'lib/tap/generator/base.rb', line 249 def action raise NotImplementedError end |
#directories(root, targets, options = {}) ⇒ Object
Makes (or destroys) the root and each of the targets, relative to root. Options are passed onto directory.
201 202 203 204 205 206 207 |
# File 'lib/tap/generator/base.rb', line 201 def directories(root, targets, ={}) results = [directory(root, )] targets.each do |target| results << directory(File.join(root, target), ) end results 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).
187 188 189 |
# File 'lib/tap/generator/base.rb', line 187 def directory(target, ={}) raise NotImplementedError end |
#file(target, options = {}) ⇒ Object
Peforms a file action (ex generate or destroy). Calls to file specify input for a target by providing a block; the block recieves an IO and pushes content to it. Must be overridden by one of the action mixins (ex Generate or Destroy).
195 196 197 |
# File 'lib/tap/generator/base.rb', line 195 def file(target, ={}) # :yields: io raise NotImplementedError end |
#iterate(actions) ⇒ Object
Peforms each of the input actions in order, and collects the results. The process method returns these results.
176 177 178 |
# File 'lib/tap/generator/base.rb', line 176 def iterate(actions) actions.collect {|action| yield(action) } end |
#log_relative(action, path) ⇒ Object
Logs the action with the relative filepath from destination_root to path.
254 255 256 257 |
# File 'lib/tap/generator/base.rb', line 254 def log_relative(action, path) relative_path = destination_root.relative_path(path) app.log(action, relative_path || 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.
170 171 172 |
# File 'lib/tap/generator/base.rb', line 170 def manifest(m, *argv) raise NotImplementedError end |
#on(*actions, &block) ⇒ Object
Calls the block when specified by the action for self.
240 241 242 243 244 245 246 |
# File 'lib/tap/generator/base.rb', line 240 def on(*actions, &block) if actions.include?(action) block.call else nil end end |
#path(*paths) ⇒ Object
Constructs a path relative to destination_root.
181 182 183 |
# File 'lib/tap/generator/base.rb', line 181 def path(*paths) destination_root.path(*paths) end |
#process(*argv) ⇒ Object
Builds the manifest, then executes the actions of the manifest. Process returns the results of iterate, which normally will be an array of files and directories created (or destroyed) by self.
158 159 160 161 162 163 164 165 |
# File 'lib/tap/generator/base.rb', line 158 def process(*argv) actions = [] manifest(Manifest.new(actions), *argv) iterate(actions) do |action, args, block| send(action, *args, &block) end.compact 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_root. Options are passed onto file.
212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/tap/generator/base.rb', line 212 def template(target, source, attributes={}, ={}) template_path = template_root.path(source) templater = Templater.new(File.read(template_path), attributes) ([:helpers] || self.class.helpers).each do |helper| templater.extend(helper) end file(target, ) do |file| file << templater.build(nil, template_path) end end |
#template_files ⇒ Object
Yields each source file under template_root to the block, with a target path of the source relative to template_root.
227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/tap/generator/base.rb', line 227 def template_files targets = [] template_root.glob('**/*').sort.each do |source| next unless File.file?(source) target = template_root.relative_path(source) yield(source, target) targets << target end targets end |