tap-gen 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History +4 -0
- data/MIT-LICENSE +22 -0
- data/README +57 -0
- data/cmd/destroy.rb +21 -0
- data/cmd/generate.rb +21 -0
- data/lib/tap/generator/arguments.rb +13 -0
- data/lib/tap/generator/base.rb +180 -0
- data/lib/tap/generator/destroy.rb +60 -0
- data/lib/tap/generator/exe.rb +27 -0
- data/lib/tap/generator/generate.rb +93 -0
- data/lib/tap/generator/generators/command.rb +19 -0
- data/lib/tap/generator/generators/config.rb +118 -0
- data/lib/tap/generator/generators/generator.rb +28 -0
- data/lib/tap/generator/generators/root.rb +96 -0
- data/lib/tap/generator/generators/task.rb +27 -0
- data/lib/tap/generator/manifest.rb +20 -0
- data/lib/tap/generator/preview.rb +69 -0
- data/tap.yml +0 -0
- data/templates/tap/generator/generators/command/command.erb +31 -0
- data/templates/tap/generator/generators/generator/task.erb +29 -0
- data/templates/tap/generator/generators/generator/test.erb +26 -0
- data/templates/tap/generator/generators/root/MIT-LICENSE +22 -0
- data/templates/tap/generator/generators/root/README +14 -0
- data/templates/tap/generator/generators/root/Rakefile +85 -0
- data/templates/tap/generator/generators/root/Rapfile +11 -0
- data/templates/tap/generator/generators/root/gemspec +28 -0
- data/templates/tap/generator/generators/root/test/tap_test_helper.rb +1 -0
- data/templates/tap/generator/generators/task/task.erb +16 -0
- data/templates/tap/generator/generators/task/test.erb +14 -0
- metadata +97 -0
data/History
ADDED
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2009, Regents of the University of Colorado.
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
|
4
|
+
obtaining a copy of this software and associated documentation
|
|
5
|
+
files (the "Software"), to deal in the Software without
|
|
6
|
+
restriction, including without limitation the rights to use,
|
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the
|
|
9
|
+
Software is furnished to do so, subject to the following
|
|
10
|
+
conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be
|
|
13
|
+
included in all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
= {Tap Generator}[http://tap.rubyforge.org/tap-gen]
|
|
2
|
+
|
|
3
|
+
gen.er.a.tor n. a thing that generates something
|
|
4
|
+
|
|
5
|
+
Generators for Tap.
|
|
6
|
+
|
|
7
|
+
== Description
|
|
8
|
+
|
|
9
|
+
Provides generators for Tap. Generators are subclasses of Task are therefore
|
|
10
|
+
easy to configure, subclass, and distribute.
|
|
11
|
+
{Tap-Generator}[http://tap.rubyforge.org/tap-gen] is a part of the
|
|
12
|
+
{Tap-Suite}[http://tap.rubyforge.org/tap-suite]. Check out these links for
|
|
13
|
+
documentation, development, and bug tracking.
|
|
14
|
+
|
|
15
|
+
* Website[http://tap.rubyforge.org]
|
|
16
|
+
* Lighthouse[http://bahuvrihi.lighthouseapp.com/projects/9908-tap-task-application/tickets]
|
|
17
|
+
* Github[http://github.com/bahuvrihi/tap/tree/master]
|
|
18
|
+
* {Google Group}[http://groups.google.com/group/ruby-on-tap]
|
|
19
|
+
|
|
20
|
+
== Usage
|
|
21
|
+
|
|
22
|
+
Get started:
|
|
23
|
+
|
|
24
|
+
% tap generate root sample
|
|
25
|
+
% cd sample
|
|
26
|
+
% tap generate task goodnight
|
|
27
|
+
% tap run -- goodnight moon
|
|
28
|
+
|
|
29
|
+
Get some help:
|
|
30
|
+
|
|
31
|
+
% tap generate --help
|
|
32
|
+
% tap generate task --help
|
|
33
|
+
|
|
34
|
+
Roll your own:
|
|
35
|
+
|
|
36
|
+
% tap generate generator thing
|
|
37
|
+
|
|
38
|
+
Roll it back:
|
|
39
|
+
|
|
40
|
+
% tap destroy generator thing
|
|
41
|
+
% tap destroy task goodnight
|
|
42
|
+
% cd ..
|
|
43
|
+
% tap destroy root sample
|
|
44
|
+
|
|
45
|
+
== Installation
|
|
46
|
+
|
|
47
|
+
Tap-Generator is available as a gem on
|
|
48
|
+
RubyForge[http://rubyforge.org/projects/tap]. Use:
|
|
49
|
+
|
|
50
|
+
% gem install tap-gen
|
|
51
|
+
|
|
52
|
+
== Info
|
|
53
|
+
|
|
54
|
+
Copyright (c) 2009, Regents of the University of Colorado.
|
|
55
|
+
Developer:: {Simon Chiang}[http://bahuvrihi.wordpress.com], {Biomolecular Structure Program}[http://biomol.uchsc.edu/], {Hansen Lab}[http://hsc-proteomics.uchsc.edu/hansenlab/]
|
|
56
|
+
Support:: CU Denver School of Medicine Deans Academic Enrichment Fund
|
|
57
|
+
License:: {MIT-Style}[link:files/MIT-LICENSE.html]
|
data/cmd/destroy.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# usage: tap destroy GENERATOR ...
|
|
2
|
+
#
|
|
3
|
+
# Runs a generator in reverse. Each generator works a little differently; the
|
|
4
|
+
# best way to figure out what a generator does is to use --help. For example:
|
|
5
|
+
#
|
|
6
|
+
# % tap generate root --help
|
|
7
|
+
#
|
|
8
|
+
|
|
9
|
+
require 'tap/generator/exe'
|
|
10
|
+
require 'tap/generator/destroy'
|
|
11
|
+
|
|
12
|
+
env = Tap::Env.instance
|
|
13
|
+
env.extend Tap::Generator::Exe
|
|
14
|
+
|
|
15
|
+
env.run(Tap::Generator::Destroy, ARGV) do
|
|
16
|
+
puts Lazydoc.usage(__FILE__)
|
|
17
|
+
puts
|
|
18
|
+
puts "generators:"
|
|
19
|
+
puts env.manifest('generator').summarize
|
|
20
|
+
exit(1)
|
|
21
|
+
end
|
data/cmd/generate.rb
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# usage: tap generate GENERATOR ...
|
|
2
|
+
#
|
|
3
|
+
# Runs a generator. Each generator works a little differently; the best way to
|
|
4
|
+
# figure out what a generator does is to use --help. For example:
|
|
5
|
+
#
|
|
6
|
+
# % tap generate root --help
|
|
7
|
+
#
|
|
8
|
+
|
|
9
|
+
require 'tap/generator/exe'
|
|
10
|
+
require 'tap/generator/generate'
|
|
11
|
+
|
|
12
|
+
env = Tap::Env.instance
|
|
13
|
+
env.extend Tap::Generator::Exe
|
|
14
|
+
|
|
15
|
+
env.run(Tap::Generator::Generate, ARGV) do
|
|
16
|
+
puts Lazydoc.usage(__FILE__)
|
|
17
|
+
puts
|
|
18
|
+
puts "generators:"
|
|
19
|
+
puts env.manifest('generator').summarize
|
|
20
|
+
exit(1)
|
|
21
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Tap
|
|
2
|
+
module Generator
|
|
3
|
+
|
|
4
|
+
# A special type of Lazydoc::Arguments that shifts off the standard 'm'
|
|
5
|
+
# argument on generator manifest methods, to properly reflect how may
|
|
6
|
+
# arguments the generator should receive.
|
|
7
|
+
class Arguments < Lazydoc::Arguments
|
|
8
|
+
def arguments(shift_manifest_arg=true)
|
|
9
|
+
shift_manifest_arg ? @arguments[1..-1] : @arguments
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
require 'tap'
|
|
2
|
+
require 'tap/generator/manifest'
|
|
3
|
+
require 'tap/generator/arguments'
|
|
4
|
+
|
|
5
|
+
module Tap
|
|
6
|
+
module Generator
|
|
7
|
+
|
|
8
|
+
# :startdoc:::-
|
|
9
|
+
# Base provides the basic structure of a generator and custom generators
|
|
10
|
+
# inherit from it. Base is patterned after the {Ruby on Rails}[http://rubyonrails.org/]
|
|
11
|
+
# generators, but obviously takes on all the advantages of Tasks.
|
|
12
|
+
#
|
|
13
|
+
# === Usage
|
|
14
|
+
#
|
|
15
|
+
# Tap generators define a manifest method that defines what files and
|
|
16
|
+
# directories are created by the generator. Then, at execution time,
|
|
17
|
+
# a mixin with the appropriate funtion (ie Generate or Destroy) is
|
|
18
|
+
# overlaid to figure out how to roll those actions forward or backwards.
|
|
19
|
+
#
|
|
20
|
+
# Generators are identified using the ::generator flag rather than ::task,
|
|
21
|
+
# so that generators are available to the generate/destroy commands and
|
|
22
|
+
# not run.
|
|
23
|
+
#
|
|
24
|
+
# Typically, generators live in a directory structure like this:
|
|
25
|
+
#
|
|
26
|
+
# root
|
|
27
|
+
# |- lib
|
|
28
|
+
# | `- sample.rb
|
|
29
|
+
# |
|
|
30
|
+
# `- templates
|
|
31
|
+
# `- sample
|
|
32
|
+
# `- template_file.erb
|
|
33
|
+
#
|
|
34
|
+
# Tap generators keep templates out of lib and under templates, in a
|
|
35
|
+
# directory is named after the generator class. Generators themselves
|
|
36
|
+
# take the form:
|
|
37
|
+
#
|
|
38
|
+
# [sample.rb]
|
|
39
|
+
# require 'tap/generator/base'
|
|
40
|
+
#
|
|
41
|
+
# # ::generator generates a directory, and two files
|
|
42
|
+
# #
|
|
43
|
+
# # An extended description of the
|
|
44
|
+
# # generator goes here...
|
|
45
|
+
# #
|
|
46
|
+
# class Sample < Tap::Generator::Base
|
|
47
|
+
#
|
|
48
|
+
# config :key, 'value' # a sample config
|
|
49
|
+
#
|
|
50
|
+
# def manifest(m, *args)
|
|
51
|
+
# # make a directory
|
|
52
|
+
# m.directory('path/to/dir')
|
|
53
|
+
#
|
|
54
|
+
# # make a file
|
|
55
|
+
# m.file('path/to/file.txt') do |file|
|
|
56
|
+
# file << "some content"
|
|
57
|
+
# end
|
|
58
|
+
#
|
|
59
|
+
# # template a file
|
|
60
|
+
# m.template('path/to/result.txt', 'template_file.erb', config.to_hash)
|
|
61
|
+
# end
|
|
62
|
+
# end
|
|
63
|
+
#
|
|
64
|
+
# The arguments that a generator receives are specified by manifest (minus
|
|
65
|
+
# the 'm' argument which is standard) rather than process. Creating
|
|
66
|
+
# directories and files is straightforward, as above. Template renders the
|
|
67
|
+
# erb source file using attributes specified in the last argument; in the
|
|
68
|
+
# example template uses the generator configurations.
|
|
69
|
+
#
|
|
70
|
+
# :startdoc:::+
|
|
71
|
+
class Base < Tap::Task
|
|
72
|
+
lazy_attr :manifest, 'generator'
|
|
73
|
+
lazy_attr :args, :manifest
|
|
74
|
+
lazy_register :manifest, Arguments
|
|
75
|
+
|
|
76
|
+
config :destination_root, Dir.pwd # The destination root directory
|
|
77
|
+
config :pretend, false, &c.flag # Run but rollback any changes.
|
|
78
|
+
config :force, false, &c.flag # Overwrite files that already exist.
|
|
79
|
+
config :skip, false, &c.flag # Skip files that already exist.
|
|
80
|
+
|
|
81
|
+
# The generator-specific templates directory. By default:
|
|
82
|
+
# 'templates/path/to/name' for 'lib/path/to/name.rb'
|
|
83
|
+
attr_accessor :template_dir
|
|
84
|
+
|
|
85
|
+
# The IO used to pull prompt inputs (default: $stdin)
|
|
86
|
+
attr_accessor :prompt_in
|
|
87
|
+
|
|
88
|
+
# The IO used to prompt users for input (default: $stdout)
|
|
89
|
+
attr_accessor :prompt_out
|
|
90
|
+
|
|
91
|
+
def initialize(config={}, app=Tap::App.instance)
|
|
92
|
+
super
|
|
93
|
+
@prompt_in = $stdin
|
|
94
|
+
@prompt_out = $stdout
|
|
95
|
+
@template_dir = File.expand_path("templates/#{self.class.to_s.underscore}")
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Builds the manifest, then executes the actions of the manifest.
|
|
99
|
+
# Process returns the results of iterate, which normally will be
|
|
100
|
+
# an array of files and directories created (or destroyed) by self.
|
|
101
|
+
def process(*argv)
|
|
102
|
+
actions = []
|
|
103
|
+
manifest(Manifest.new(actions), *argv)
|
|
104
|
+
|
|
105
|
+
iterate(actions) do |action, args, block|
|
|
106
|
+
send(action, *args, &block)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Overridden in subclasses to add actions to the input Manifest.
|
|
111
|
+
# Any arguments passed to process will be passed to manifest
|
|
112
|
+
# unchanged.
|
|
113
|
+
def manifest(m, *argv)
|
|
114
|
+
raise NotImplementedError
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Peforms each of the input actions in order, and collects the
|
|
118
|
+
# results. The process method returns these results.
|
|
119
|
+
def iterate(actions)
|
|
120
|
+
actions.collect {|action| yield(action) }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Constructs a path relative to destination_root.
|
|
124
|
+
def path(*paths)
|
|
125
|
+
File.expand_path(File.join(*paths), destination_root)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Peforms a directory action (ex generate or destroy). Must be
|
|
129
|
+
# overridden by one of the action mixins (ex Generate or Destroy).
|
|
130
|
+
def directory(target, options={})
|
|
131
|
+
raise NotImplementedError
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Peforms a file action (ex generate or destroy). Calls to file specify
|
|
135
|
+
# input for a target by providing a block; the block recieves an IO and
|
|
136
|
+
# pushes content to it. Must be overridden by one of the action mixins
|
|
137
|
+
# (ex Generate or Destroy).
|
|
138
|
+
def file(target, options={}) # :yields: io
|
|
139
|
+
raise NotImplementedError
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Makes (or destroys) the root and each of the targets, relative
|
|
143
|
+
# to root. Options are passed onto directory.
|
|
144
|
+
def directories(root, targets, options={})
|
|
145
|
+
directory(root, options)
|
|
146
|
+
targets.each do |target|
|
|
147
|
+
directory(File.join(root, target), options)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Makes (or destroys) the target by templating the source using
|
|
152
|
+
# the specified attributes. Source is expanded relative to
|
|
153
|
+
# template_dir. Options are passed onto file.
|
|
154
|
+
def template(target, source, attributes={}, options={})
|
|
155
|
+
template_path = File.expand_path(source, template_dir)
|
|
156
|
+
templater = Support::Templater.new(File.read(template_path), attributes)
|
|
157
|
+
|
|
158
|
+
file(target, options) do |file|
|
|
159
|
+
file << templater.build
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Yields each source file under template_dir to the block, with
|
|
164
|
+
# a target path of the source relative to template_dir.
|
|
165
|
+
def template_files
|
|
166
|
+
Dir.glob(template_dir + "/**/*").sort.each do |source|
|
|
167
|
+
next unless File.file?(source)
|
|
168
|
+
|
|
169
|
+
target = Tap::Root::Utils.relative_path(template_dir, source)
|
|
170
|
+
yield(source, target)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Logs the action with the relative filepath from Dir.pwd to path.
|
|
175
|
+
def log_relative(action, path)
|
|
176
|
+
log(action, Tap::Root::Utils.relative_path(Dir.pwd, path))
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module Tap
|
|
2
|
+
module Generator
|
|
3
|
+
|
|
4
|
+
# A mixin defining how to run manifest actions in reverse.
|
|
5
|
+
module Destroy
|
|
6
|
+
|
|
7
|
+
# Iterates over the actions in reverse, and collects the results.
|
|
8
|
+
def iterate(actions)
|
|
9
|
+
results = []
|
|
10
|
+
actions.reverse_each {|action| results << yield(action) }
|
|
11
|
+
results
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Removes the target directory if it exists. Missing, non-directory and
|
|
15
|
+
# non-empty targets are simply logged and not removed. When pretend is
|
|
16
|
+
# true, removal is logged but does not actually happen.
|
|
17
|
+
#
|
|
18
|
+
# No options currently affect the behavior of this method.
|
|
19
|
+
def directory(target, options={})
|
|
20
|
+
target = File.expand_path(target)
|
|
21
|
+
|
|
22
|
+
case
|
|
23
|
+
when !File.exists?(target)
|
|
24
|
+
log_relative :missing, target
|
|
25
|
+
when !File.directory?(target)
|
|
26
|
+
log_relative 'not a directory', target
|
|
27
|
+
when !Root::Utils.empty?(target)
|
|
28
|
+
log_relative 'not empty', target
|
|
29
|
+
else
|
|
30
|
+
log_relative :rm, target
|
|
31
|
+
FileUtils.rmdir(target) unless pretend
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
target
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Removes the target file if it exists. Missing and non-file and targets
|
|
38
|
+
# are simply logged and not removed. When pretend is true, removal is
|
|
39
|
+
# logged but does not actually happen.
|
|
40
|
+
#
|
|
41
|
+
# No options currently affect the behavior of this method.
|
|
42
|
+
def file(target, options={})
|
|
43
|
+
target = File.expand_path(target)
|
|
44
|
+
|
|
45
|
+
case
|
|
46
|
+
when File.file?(target)
|
|
47
|
+
log_relative :rm, target
|
|
48
|
+
FileUtils.rm(target) unless pretend
|
|
49
|
+
when File.directory?(target)
|
|
50
|
+
log_relative 'not a file', target
|
|
51
|
+
else
|
|
52
|
+
log_relative :missing, target
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
target
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'tap/generator/base'
|
|
2
|
+
|
|
3
|
+
module Tap
|
|
4
|
+
module Generator
|
|
5
|
+
|
|
6
|
+
# Methods used by the generate and destroy commands.
|
|
7
|
+
module Exe
|
|
8
|
+
|
|
9
|
+
def run(mod, argv=ARGV)
|
|
10
|
+
if argv.empty? || argv == ['--help']
|
|
11
|
+
yield
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
name = argv.shift
|
|
15
|
+
env, const = eeek('generator', name)
|
|
16
|
+
|
|
17
|
+
unless const
|
|
18
|
+
raise "unknown generator: #{name}"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
generator, argv = const.constantize.parse(argv)
|
|
22
|
+
generator.template_dir = env.class_path(:templates, generator) {|dir| File.directory?(dir) }
|
|
23
|
+
generator.extend(mod).process(*argv)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
autoload(:Tempfile, 'tempfile')
|
|
2
|
+
|
|
3
|
+
module Tap
|
|
4
|
+
module Generator
|
|
5
|
+
|
|
6
|
+
# A mixin defining how to run manifest actions.
|
|
7
|
+
module Generate
|
|
8
|
+
|
|
9
|
+
# Creates the target directory if it doesn't exist. When pretend is
|
|
10
|
+
# true, creation is logged but does not actually happen.
|
|
11
|
+
#
|
|
12
|
+
# No options currently affect the behavior of this method.
|
|
13
|
+
def directory(target, options={})
|
|
14
|
+
target = File.expand_path(target)
|
|
15
|
+
|
|
16
|
+
case
|
|
17
|
+
when File.exists?(target)
|
|
18
|
+
log_relative :exists, target
|
|
19
|
+
else
|
|
20
|
+
log_relative :create, target
|
|
21
|
+
FileUtils.mkdir_p(target) unless pretend
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
target
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Creates the target file; content may be added to the file by providing
|
|
28
|
+
# block. If the target file already exists, the new and existing content
|
|
29
|
+
# is compared and the user will be prompted for how to handle collisions.
|
|
30
|
+
# All activity is logged. When pretend is true, creation is logged but
|
|
31
|
+
# does not actually happen.
|
|
32
|
+
#
|
|
33
|
+
# No options currently affect the behavior of this method.
|
|
34
|
+
def file(target, options={})
|
|
35
|
+
source_file = Tempfile.new('generate')
|
|
36
|
+
yield(source_file) if block_given?
|
|
37
|
+
source_file.close
|
|
38
|
+
|
|
39
|
+
source = source_file.path
|
|
40
|
+
target = File.expand_path(target)
|
|
41
|
+
|
|
42
|
+
copy_file = true
|
|
43
|
+
msg = case
|
|
44
|
+
when !File.exists?(target)
|
|
45
|
+
:create
|
|
46
|
+
when FileUtils.cmp(source, target)
|
|
47
|
+
:exists
|
|
48
|
+
when force_file_collision?(target)
|
|
49
|
+
:force
|
|
50
|
+
else
|
|
51
|
+
copy_file = false
|
|
52
|
+
:skip
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
log_relative msg, target
|
|
56
|
+
if copy_file && !pretend
|
|
57
|
+
dir = File.dirname(target)
|
|
58
|
+
FileUtils.mkdir_p(dir) unless File.exists?(dir)
|
|
59
|
+
FileUtils.mv(source, target, :force => true)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
target
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
protected
|
|
66
|
+
|
|
67
|
+
# Ask the user interactively whether to force collision.
|
|
68
|
+
def force_file_collision?(target)
|
|
69
|
+
return false if skip
|
|
70
|
+
return true if force
|
|
71
|
+
|
|
72
|
+
prompt_out.print "overwrite #{target}? [Ynaiq] "
|
|
73
|
+
prompt_out.flush
|
|
74
|
+
case prompt_in.gets.strip
|
|
75
|
+
when /^y(es)?$/i
|
|
76
|
+
true
|
|
77
|
+
when /^n(o)?$/i
|
|
78
|
+
false
|
|
79
|
+
when /^a(ll)?$/i
|
|
80
|
+
self.force = true
|
|
81
|
+
true
|
|
82
|
+
when /^i(gnore)?$/i
|
|
83
|
+
self.skip = true
|
|
84
|
+
false
|
|
85
|
+
when /^q(uit)?$/i
|
|
86
|
+
prompt_out.puts "aborting"
|
|
87
|
+
raise SystemExit
|
|
88
|
+
else force_file_collision?(target)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Tap::Generator::Generators
|
|
2
|
+
|
|
3
|
+
# :startdoc::generator a new tap command
|
|
4
|
+
#
|
|
5
|
+
# Generates a new tap command under the cmd directory. The
|
|
6
|
+
# new command can be run from the command line using:
|
|
7
|
+
#
|
|
8
|
+
# % tap <command>
|
|
9
|
+
#
|
|
10
|
+
class Command < Tap::Generator::Base
|
|
11
|
+
def manifest(m, command_name)
|
|
12
|
+
m.directory path('cmd')
|
|
13
|
+
|
|
14
|
+
template_files do |source, target|
|
|
15
|
+
m.template path('cmd', "#{command_name}.rb"), source, :command_name => command_name
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
module Tap::Generator::Generators
|
|
2
|
+
|
|
3
|
+
# :startdoc::generator a config file generator
|
|
4
|
+
#
|
|
5
|
+
# Generates a new config file for a task. The configurations, defaults,
|
|
6
|
+
# and documentation is determined from the source file.
|
|
7
|
+
#
|
|
8
|
+
# Configurations for other types of configurable resources may also be
|
|
9
|
+
# generated. Specify the constant attribute identifying the resource
|
|
10
|
+
# using the 'resource' flag. This generates a config file for the Root
|
|
11
|
+
# generator:
|
|
12
|
+
#
|
|
13
|
+
# % tap generate config root --resource generator
|
|
14
|
+
#
|
|
15
|
+
class Config < Tap::Generator::Base
|
|
16
|
+
|
|
17
|
+
dump_delegates = lambda do |leader, delegate, block|
|
|
18
|
+
nested_delegates = delegate.default(false).delegates
|
|
19
|
+
indented_dump = Configurable::Utils.dump(nested_delegates, &block).gsub(/^/, " ")
|
|
20
|
+
"#{leader}: \n#{indented_dump}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
doc_format = lambda do |key, delegate|
|
|
24
|
+
# get the description
|
|
25
|
+
desc = delegate.attributes[:desc]
|
|
26
|
+
doc = desc.to_s
|
|
27
|
+
doc = desc.comment if doc.empty?
|
|
28
|
+
|
|
29
|
+
# wrap as lines
|
|
30
|
+
lines = Lazydoc::Utils.wrap(doc, 50).collect {|line| "# #{line}"}
|
|
31
|
+
lines << "" unless lines.empty?
|
|
32
|
+
|
|
33
|
+
if delegate.is_nest?
|
|
34
|
+
leader = "#{lines.join("\n")}#{key}"
|
|
35
|
+
DUMP_DELEGATES[leader, delegate, DOC_FORMAT]
|
|
36
|
+
else
|
|
37
|
+
default = delegate.default
|
|
38
|
+
|
|
39
|
+
# setup formatting
|
|
40
|
+
leader = default == nil ? '# ' : ''
|
|
41
|
+
config = YAML.dump({key => default})[5..-1]
|
|
42
|
+
"#{lines.join("\n")}#{leader}#{config.strip}\n\n"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
nodoc_format = lambda do |key, delegate|
|
|
47
|
+
if delegate.is_nest?
|
|
48
|
+
DUMP_DELEGATES[key, delegate, NODOC_FORMAT]
|
|
49
|
+
else
|
|
50
|
+
default = delegate.default
|
|
51
|
+
|
|
52
|
+
# setup formatting
|
|
53
|
+
leader = default == nil ? '# ' : ''
|
|
54
|
+
config = YAML.dump({key => default})[5..-1]
|
|
55
|
+
"#{leader}#{config.strip}\n"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Dumps a nested configuration.
|
|
60
|
+
DUMP_DELEGATES = dump_delegates
|
|
61
|
+
|
|
62
|
+
# Dumps configurations as YAML with documentation,
|
|
63
|
+
# used when the doc config is true.
|
|
64
|
+
DOC_FORMAT = doc_format
|
|
65
|
+
|
|
66
|
+
# Dumps configurations as YAML without documentation,
|
|
67
|
+
# used when the doc config is false.
|
|
68
|
+
NODOC_FORMAT = nodoc_format
|
|
69
|
+
|
|
70
|
+
config :doc, true, &c.switch # include documentation in the config
|
|
71
|
+
config :nest, false, &c.switch # generate nested config files
|
|
72
|
+
config :blanks, true, &c.switch # allow generation of empty config files
|
|
73
|
+
config :resource, 'task' # specify the resource type
|
|
74
|
+
|
|
75
|
+
# Lookup the named resource class. Lookup happens through the active Env
|
|
76
|
+
# instance, specifically using:
|
|
77
|
+
#
|
|
78
|
+
# Env.instance.constant_manifest(resource)[name]
|
|
79
|
+
#
|
|
80
|
+
# Raises an error if the name cannot be resolved to a resource.
|
|
81
|
+
def lookup(name)
|
|
82
|
+
env = Tap::Env.instance
|
|
83
|
+
env.constant_manifest(resource)[name] or raise "unknown #{resource}: #{name}"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def manifest(m, name, config_name=nil)
|
|
87
|
+
# setup
|
|
88
|
+
tasc = lookup(name)
|
|
89
|
+
config_name ||= tasc.to_s.underscore
|
|
90
|
+
config_file = path('config', config_name)
|
|
91
|
+
config_file += ".yml" if File.extname(config_file).empty?
|
|
92
|
+
|
|
93
|
+
# generate the dumps
|
|
94
|
+
dumps = Configurable::Utils.dump_file(
|
|
95
|
+
tasc.configurations,
|
|
96
|
+
config_file,
|
|
97
|
+
nest,
|
|
98
|
+
true,
|
|
99
|
+
&format_block)
|
|
100
|
+
|
|
101
|
+
# now put the dumps to the manifest
|
|
102
|
+
m.directory(path('config'))
|
|
103
|
+
|
|
104
|
+
dumps.each do |path, content|
|
|
105
|
+
next if content.empty? && !blanks
|
|
106
|
+
m.file(path) do |file|
|
|
107
|
+
file << content
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# A hook to set a formatting block. By default format_blocks
|
|
113
|
+
# returns DOC_FORMAT or NODOC_FORMAT as per the doc config.
|
|
114
|
+
def format_block
|
|
115
|
+
doc ? DOC_FORMAT : NODOC_FORMAT
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'tap/generator/generators/task'
|
|
2
|
+
|
|
3
|
+
module Tap::Generator::Generators
|
|
4
|
+
|
|
5
|
+
# :startdoc::generator a generator task and test
|
|
6
|
+
#
|
|
7
|
+
# Generates a new generator.
|
|
8
|
+
class Generator < Tap::Generator::Generators::Task
|
|
9
|
+
|
|
10
|
+
config :test, true, &c.switch # specifies creation of a test file
|
|
11
|
+
|
|
12
|
+
def manifest(m, const_name)
|
|
13
|
+
super
|
|
14
|
+
|
|
15
|
+
const = Tap::Env::Constant.new(const_name.camelize)
|
|
16
|
+
|
|
17
|
+
# make the templates directory
|
|
18
|
+
m.directory path('templates', const.path)
|
|
19
|
+
|
|
20
|
+
# make a template file
|
|
21
|
+
# (note it's easier to do this as a file since erb is
|
|
22
|
+
# added, and would have to be escaped in a template)
|
|
23
|
+
m.file path('templates', const.path, 'template_file.erb') do |file|
|
|
24
|
+
file << "# A sample template file.\nkey: <%= key %>\n"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require 'tap/generator/base'
|
|
2
|
+
require 'tap/constants'
|
|
3
|
+
|
|
4
|
+
module Tap::Generator::Generators
|
|
5
|
+
|
|
6
|
+
# :startdoc::generator a basic tap directory structure
|
|
7
|
+
#
|
|
8
|
+
# Generates a tap root directory structure. Use the switches to turn on or
|
|
9
|
+
# off the creation of various files:
|
|
10
|
+
#
|
|
11
|
+
# project
|
|
12
|
+
# |- MIT-LICENSE
|
|
13
|
+
# |- README
|
|
14
|
+
# |- Rakefile
|
|
15
|
+
# |- lib
|
|
16
|
+
# |- project.gemspec
|
|
17
|
+
# |- tap.yml
|
|
18
|
+
# `- test
|
|
19
|
+
# `- tap_test_helper.rb
|
|
20
|
+
#
|
|
21
|
+
class Root < Tap::Generator::Base
|
|
22
|
+
|
|
23
|
+
nest :gemspec do
|
|
24
|
+
config :name, "Your Name Here" # Author name
|
|
25
|
+
config :email, "your.email@pubfactory.edu" # Author email
|
|
26
|
+
config :homepage, "" # The project hompage
|
|
27
|
+
config :rubyforge_project, "" # The rubyforge project name
|
|
28
|
+
config :summary, "" # The project summary
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
config :env, false, &c.switch # Create a full tap.yml file
|
|
32
|
+
config :license, true, &c.switch # Create an MIT-LICENSE
|
|
33
|
+
config :history, true, &c.switch # Create History file
|
|
34
|
+
config :rapfile, false, &c.switch # Create a Rapfile
|
|
35
|
+
config :rakefile, true, &c.switch # Create a Rakefile
|
|
36
|
+
|
|
37
|
+
# ::args ROOT, PROJECT_NAME=basename(ROOT)
|
|
38
|
+
def manifest(m, root, project_name=nil)
|
|
39
|
+
r = Tap::Root.new(root)
|
|
40
|
+
project_name = File.basename(r.root) if project_name == nil
|
|
41
|
+
|
|
42
|
+
m.directory r.root
|
|
43
|
+
m.directory r['lib']
|
|
44
|
+
m.directory r['test']
|
|
45
|
+
|
|
46
|
+
template_files do |source, target|
|
|
47
|
+
case
|
|
48
|
+
when File.directory?(source)
|
|
49
|
+
m.directory r[target]
|
|
50
|
+
next
|
|
51
|
+
when source =~ /gemspec$/
|
|
52
|
+
locals = gemspec.config.to_hash.merge(
|
|
53
|
+
:project_name => project_name,
|
|
54
|
+
:license => license,
|
|
55
|
+
:history => history
|
|
56
|
+
)
|
|
57
|
+
m.template r[project_name + '.gemspec'], source, locals
|
|
58
|
+
next
|
|
59
|
+
when source =~ /Rakefile$/
|
|
60
|
+
next unless rakefile
|
|
61
|
+
when source =~ /Rapfile$/
|
|
62
|
+
next unless rapfile
|
|
63
|
+
when source =~ /MIT-LICENSE$/
|
|
64
|
+
next unless license
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
m.template r[target], source, :project_name => project_name, :license => license
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
m.file(r['History']) if history
|
|
71
|
+
m.file(r['tap.yml']) do |file|
|
|
72
|
+
Configurable::Utils.dump(Tap::Env.configurations, file) do |key, delegate|
|
|
73
|
+
default = delegate.default(false)
|
|
74
|
+
|
|
75
|
+
# get the description
|
|
76
|
+
desc = delegate.attributes[:desc]
|
|
77
|
+
doc = desc.to_s
|
|
78
|
+
doc = desc.comment if doc.empty?
|
|
79
|
+
|
|
80
|
+
# wrap as lines
|
|
81
|
+
lines = Lazydoc::Utils.wrap(doc, 78).collect {|line| "# #{line}"}
|
|
82
|
+
lines << "" unless lines.empty?
|
|
83
|
+
|
|
84
|
+
# note: this causes order to be lost...
|
|
85
|
+
default = default.to_hash if delegate.is_nest?
|
|
86
|
+
|
|
87
|
+
# setup formatting
|
|
88
|
+
leader = key == 'root' || default == nil ? '# ' : ''
|
|
89
|
+
config = YAML.dump({key => default})[5..-1].strip.gsub(/\n+/, "\n#{leader}")
|
|
90
|
+
"#{lines.join("\n")}#{leader}#{config}\n\n"
|
|
91
|
+
end if env
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'tap/env'
|
|
2
|
+
|
|
3
|
+
module Tap::Generator::Generators
|
|
4
|
+
|
|
5
|
+
# :startdoc::generator a task and test
|
|
6
|
+
#
|
|
7
|
+
# Generates a new Tap::Task and an associated test file.
|
|
8
|
+
class Task < Tap::Generator::Base
|
|
9
|
+
|
|
10
|
+
config :test, true, &c.switch # specifies creation of a test file
|
|
11
|
+
|
|
12
|
+
def manifest(m, const_name)
|
|
13
|
+
const = Tap::Env::Constant.new(const_name.camelize)
|
|
14
|
+
|
|
15
|
+
task_path = path('lib', "#{const.path}.rb")
|
|
16
|
+
m.directory File.dirname(task_path)
|
|
17
|
+
m.template task_path, "task.erb", :const => const
|
|
18
|
+
|
|
19
|
+
if test
|
|
20
|
+
test_path = path('test', "#{const.path}_test.rb")
|
|
21
|
+
m.directory File.dirname(test_path)
|
|
22
|
+
m.template test_path, "test.erb", :const => const
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Tap
|
|
2
|
+
module Generator
|
|
3
|
+
|
|
4
|
+
# Manifest records methods called upon it using method_missing. These
|
|
5
|
+
# actions are replayed on a generator in order (for generate) or in
|
|
6
|
+
# reverse order (for destroy).
|
|
7
|
+
class Manifest
|
|
8
|
+
|
|
9
|
+
# Makes a new Manifest. Method calls on self are recorded to actions.
|
|
10
|
+
def initialize(actions)
|
|
11
|
+
@actions = actions
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Records an action.
|
|
15
|
+
def method_missing(action, *args, &block)
|
|
16
|
+
@actions << [action, args, block]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require 'stringio'
|
|
2
|
+
|
|
3
|
+
module Tap
|
|
4
|
+
module Generator
|
|
5
|
+
|
|
6
|
+
# Preview is a testing module designed so that process will return an array
|
|
7
|
+
# of relative paths for the created files/directories (which are easy
|
|
8
|
+
# to specify in a test). Preview also collects the content of created files
|
|
9
|
+
# to be tested as needed.
|
|
10
|
+
#
|
|
11
|
+
# class Sample < Tap::Generator::Base
|
|
12
|
+
# def manifest(m)
|
|
13
|
+
# dir = path('dir')
|
|
14
|
+
#
|
|
15
|
+
# m.directory dir
|
|
16
|
+
# m.file(File.join(dir, 'file.txt')) {|io| io << "content"}
|
|
17
|
+
# end
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# These assertions will pass:
|
|
21
|
+
#
|
|
22
|
+
# s = Sample.new.extend Preview
|
|
23
|
+
# assert_equal %w{
|
|
24
|
+
# dir
|
|
25
|
+
# dir/file.txt
|
|
26
|
+
# }, s.process
|
|
27
|
+
#
|
|
28
|
+
# assert_equal "content", s.preview['dir/file.txt']
|
|
29
|
+
#
|
|
30
|
+
# Note that relative paths are relative to destination_root.
|
|
31
|
+
module Preview
|
|
32
|
+
|
|
33
|
+
# A hash of (relative_path, content) pairs representing
|
|
34
|
+
# content built to files.
|
|
35
|
+
attr_accessor :preview
|
|
36
|
+
|
|
37
|
+
def self.extended(base) # :nodoc:
|
|
38
|
+
base.instance_variable_set(:@preview, {})
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Returns the path of path, relative to destination_root. If path
|
|
42
|
+
# is destination_root, '.' will be returned.
|
|
43
|
+
def relative_path(path)
|
|
44
|
+
path = Root::Utils.relative_path(destination_root, path, destination_root) || path
|
|
45
|
+
path.empty? ? "." : path
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Returns the relative path of the target.
|
|
49
|
+
def directory(target, options={})
|
|
50
|
+
relative_path(target)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Returns the relative path of the target. If a block is given,
|
|
54
|
+
# the block will be called with a StringIO and the results stored
|
|
55
|
+
# in builds.
|
|
56
|
+
def file(target, options={})
|
|
57
|
+
target = relative_path(target)
|
|
58
|
+
|
|
59
|
+
if block_given?
|
|
60
|
+
io = StringIO.new
|
|
61
|
+
yield(io)
|
|
62
|
+
preview[target] = io.string
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
target
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
data/tap.yml
ADDED
|
File without changes
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# tap <%= command_name %> {options} ARGS...
|
|
2
|
+
#
|
|
3
|
+
# The default command simply prints the input arguments
|
|
4
|
+
# and application information, then exits.
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
env = Tap::Env.instance
|
|
8
|
+
app = Tap::App.new
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# handle options
|
|
12
|
+
#
|
|
13
|
+
|
|
14
|
+
ConfigParser.new do |opts|
|
|
15
|
+
opts.separator ""
|
|
16
|
+
opts.separator "options:"
|
|
17
|
+
|
|
18
|
+
opts.on("-h", "--help", "Show this message") do
|
|
19
|
+
puts Lazydoc.usage(__FILE__)
|
|
20
|
+
puts opts
|
|
21
|
+
exit
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end.parse!(ARGV)
|
|
25
|
+
|
|
26
|
+
#
|
|
27
|
+
# add your script code here
|
|
28
|
+
#
|
|
29
|
+
|
|
30
|
+
puts "Received: #{ARGV.join(', ')}"
|
|
31
|
+
puts app.info
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'tap/generator/base'
|
|
2
|
+
|
|
3
|
+
<% redirect do |target| %># <%= const.const_name %>::generator <replace with manifest summary>
|
|
4
|
+
# <replace with command line description>
|
|
5
|
+
|
|
6
|
+
# <%= const.name %> Documentation
|
|
7
|
+
class <%= const.name %> < Tap::Generator::Base
|
|
8
|
+
|
|
9
|
+
config :key, 'value' # a sample config
|
|
10
|
+
|
|
11
|
+
# The generator will receive the inputs on the command line, and
|
|
12
|
+
# m, a Manifest object that records the actions of this method.
|
|
13
|
+
def manifest(m, *inputs)
|
|
14
|
+
|
|
15
|
+
# make a directory
|
|
16
|
+
# m.directory path
|
|
17
|
+
|
|
18
|
+
# make a file
|
|
19
|
+
# m.file path do |file|
|
|
20
|
+
# file << content
|
|
21
|
+
# end
|
|
22
|
+
|
|
23
|
+
# template a file in the templates directory using ERB.
|
|
24
|
+
# The last argument defines a hash of local variables
|
|
25
|
+
# for use in the template (here config is used).
|
|
26
|
+
m.template "<%= const.const_name.underscore %>_file.txt", "template_file.erb", config.to_hash
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end <% module_nest(const.nesting, ' ') { target } end %>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), '<%= '../' * const.nesting_depth %>tap_test_helper.rb')
|
|
2
|
+
require '<%= const.path %>'
|
|
3
|
+
require 'tap/generator/preview.rb'
|
|
4
|
+
|
|
5
|
+
class <%= const.name %>Test < Test::Unit::TestCase
|
|
6
|
+
|
|
7
|
+
# Preview fakes out a generator for testing
|
|
8
|
+
Preview = Tap::Generator::Preview
|
|
9
|
+
|
|
10
|
+
acts_as_tap_test
|
|
11
|
+
|
|
12
|
+
def test_<%= const.basename %>
|
|
13
|
+
g = <%= const.const_name %>.new.extend Preview
|
|
14
|
+
|
|
15
|
+
# check the files and directories
|
|
16
|
+
assert_equal %w{
|
|
17
|
+
<%= const.const_name.underscore %>_file.txt
|
|
18
|
+
}, g.process
|
|
19
|
+
|
|
20
|
+
# check the content as necessary
|
|
21
|
+
assert_equal %q{
|
|
22
|
+
# A sample template file.
|
|
23
|
+
key: value
|
|
24
|
+
}, "\n" + g.preview['<%= const.const_name.underscore %>_file.txt']
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) <%= Time.now.year %>, <copyright holders>
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
|
4
|
+
obtaining a copy of this software and associated documentation
|
|
5
|
+
files (the "Software"), to deal in the Software without
|
|
6
|
+
restriction, including without limitation the rights to use,
|
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the
|
|
9
|
+
Software is furnished to do so, subject to the following
|
|
10
|
+
conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be
|
|
13
|
+
included in all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
require 'rake'
|
|
2
|
+
require 'rake/testtask'
|
|
3
|
+
require 'rake/rdoctask'
|
|
4
|
+
require 'rake/gempackagetask'
|
|
5
|
+
|
|
6
|
+
#
|
|
7
|
+
# Gem specification
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
def gemspec
|
|
11
|
+
data = File.read('<%= project_name %>.gemspec')
|
|
12
|
+
spec = nil
|
|
13
|
+
Thread.new { spec = eval("$SAFE = 3\n#{data}") }.join
|
|
14
|
+
spec
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
Rake::GemPackageTask.new(gemspec) do |pkg|
|
|
18
|
+
pkg.need_tar = true
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
desc 'Prints the gemspec manifest.'
|
|
22
|
+
task :print_manifest do
|
|
23
|
+
# collect files from the gemspec, labeling
|
|
24
|
+
# with true or false corresponding to the
|
|
25
|
+
# file existing or not
|
|
26
|
+
files = gemspec.files.inject({}) do |files, file|
|
|
27
|
+
files[File.expand_path(file)] = [File.exists?(file), file]
|
|
28
|
+
files
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# gather non-rdoc/pkg files for the project
|
|
32
|
+
# and add to the files list if they are not
|
|
33
|
+
# included already (marking by the absence
|
|
34
|
+
# of a label)
|
|
35
|
+
Dir.glob("**/*").each do |file|
|
|
36
|
+
next if file =~ /^(rdoc|pkg|backup)/ || File.directory?(file)
|
|
37
|
+
|
|
38
|
+
path = File.expand_path(file)
|
|
39
|
+
files[path] = ["", file] unless files.has_key?(path)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# sort and output the results
|
|
43
|
+
files.values.sort_by {|exists, file| file }.each do |entry|
|
|
44
|
+
puts "%-5s %s" % entry
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
#
|
|
49
|
+
# Documentation tasks
|
|
50
|
+
#
|
|
51
|
+
|
|
52
|
+
desc 'Generate documentation.'
|
|
53
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
54
|
+
spec = gemspec
|
|
55
|
+
|
|
56
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
57
|
+
rdoc.options.concat(spec.rdoc_options)
|
|
58
|
+
rdoc.rdoc_files.include( spec.extra_rdoc_files )
|
|
59
|
+
|
|
60
|
+
files = spec.files.select {|file| file =~ /^lib.*\.rb$/}
|
|
61
|
+
rdoc.rdoc_files.include( files )
|
|
62
|
+
|
|
63
|
+
# Using CDoc to template your RDoc will result in configurations being
|
|
64
|
+
# listed with documentation in a subsection following attributes. Not
|
|
65
|
+
# necessary, but nice.
|
|
66
|
+
require 'cdoc'
|
|
67
|
+
rdoc.template = 'cdoc/cdoc_html_template'
|
|
68
|
+
rdoc.options << '--fmt' << 'cdoc'
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
#
|
|
72
|
+
# Test tasks
|
|
73
|
+
#
|
|
74
|
+
|
|
75
|
+
desc 'Default: Run tests.'
|
|
76
|
+
task :default => :test
|
|
77
|
+
|
|
78
|
+
desc 'Run tests.'
|
|
79
|
+
Rake::TestTask.new(:test) do |t|
|
|
80
|
+
t.test_files = Dir.glob( File.join('test', ENV['pattern'] || '**/*_test.rb') )
|
|
81
|
+
t.ruby_opts = ['-rubygems']
|
|
82
|
+
t.verbose = true
|
|
83
|
+
t.warning = true
|
|
84
|
+
end
|
|
85
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require 'tap/declarations'
|
|
2
|
+
|
|
3
|
+
module <%= project_name.camelize %>
|
|
4
|
+
extend Rap::Declarations
|
|
5
|
+
|
|
6
|
+
# ::desc your basic goodnight moon task
|
|
7
|
+
# Says goodnight with a configurable message.
|
|
8
|
+
task(:goodnight, :obj, :message => 'goodnight') do |task, args|
|
|
9
|
+
puts "#{task.message} #{args.obj}"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.name = "<%= project_name %>"
|
|
3
|
+
s.version = "0.0.1"
|
|
4
|
+
s.author = "<%= name %>"
|
|
5
|
+
s.email = "<%= email %>"
|
|
6
|
+
s.homepage = "<%= homepage %>"
|
|
7
|
+
s.platform = Gem::Platform::RUBY
|
|
8
|
+
s.summary = "<%= summary %>"
|
|
9
|
+
s.require_path = "lib"
|
|
10
|
+
s.rubyforge_project = "<%= rubyforge_project %>"
|
|
11
|
+
s.add_dependency("tap", "= <%= Tap::VERSION %>")
|
|
12
|
+
s.add_development_dependency("tap-test")
|
|
13
|
+
s.has_rdoc = true
|
|
14
|
+
s.rdoc_options.concat %W{--main README -S -N --title <%= project_name.capitalize %>}
|
|
15
|
+
|
|
16
|
+
# list extra rdoc files here.
|
|
17
|
+
s.extra_rdoc_files = %W{
|
|
18
|
+
<%= history ? " History\n" : '' %>
|
|
19
|
+
README
|
|
20
|
+
<%= license ? " MIT-LICENSE\n" : '' %>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
# list the files you want to include here. you can
|
|
24
|
+
# check this manifest using 'rap print_manifest'
|
|
25
|
+
s.files = %W{
|
|
26
|
+
tap.yml
|
|
27
|
+
}
|
|
28
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'tap/test/unit'
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'tap/task'
|
|
2
|
+
|
|
3
|
+
<% redirect do |target| %># <%= const.const_name %>::manifest <replace with manifest summary>
|
|
4
|
+
# <replace with command line description>
|
|
5
|
+
|
|
6
|
+
# <%= const.name %> Documentation
|
|
7
|
+
class <%= const.name %> < Tap::Task
|
|
8
|
+
|
|
9
|
+
# <config file documentation>
|
|
10
|
+
config :message, 'goodnight' # a sample config
|
|
11
|
+
|
|
12
|
+
def process(name)
|
|
13
|
+
log message, name
|
|
14
|
+
"#{message} #{name}"
|
|
15
|
+
end
|
|
16
|
+
end <% module_nest(const.nesting, ' ') { target } end %>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), '<%= '../' * const.nesting_depth %>tap_test_helper.rb')
|
|
2
|
+
require '<%= const.path %>'
|
|
3
|
+
|
|
4
|
+
class <%= const.name %>Test < Test::Unit::TestCase
|
|
5
|
+
acts_as_tap_test
|
|
6
|
+
|
|
7
|
+
def test_<%= const.basename %>
|
|
8
|
+
task = <%= const.const_name %>.new :message => "goodnight"
|
|
9
|
+
|
|
10
|
+
# a simple test
|
|
11
|
+
assert_equal({:message => 'goodnight'}, task.config)
|
|
12
|
+
assert_equal "goodnight moon", task.process("moon")
|
|
13
|
+
end
|
|
14
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: tap-gen
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Simon Chiang
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2009-05-25 00:00:00 -06:00
|
|
13
|
+
default_executable:
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: tap
|
|
17
|
+
type: :runtime
|
|
18
|
+
version_requirement:
|
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
20
|
+
requirements:
|
|
21
|
+
- - ">="
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: 0.17.0
|
|
24
|
+
version:
|
|
25
|
+
description:
|
|
26
|
+
email: simon.a.chiang@gmail.com
|
|
27
|
+
executables: []
|
|
28
|
+
|
|
29
|
+
extensions: []
|
|
30
|
+
|
|
31
|
+
extra_rdoc_files:
|
|
32
|
+
- History
|
|
33
|
+
- README
|
|
34
|
+
- MIT-LICENSE
|
|
35
|
+
files:
|
|
36
|
+
- cmd/destroy.rb
|
|
37
|
+
- cmd/generate.rb
|
|
38
|
+
- lib/tap/generator/arguments.rb
|
|
39
|
+
- lib/tap/generator/base.rb
|
|
40
|
+
- lib/tap/generator/destroy.rb
|
|
41
|
+
- lib/tap/generator/exe.rb
|
|
42
|
+
- lib/tap/generator/generate.rb
|
|
43
|
+
- lib/tap/generator/generators/command.rb
|
|
44
|
+
- lib/tap/generator/generators/config.rb
|
|
45
|
+
- lib/tap/generator/generators/generator.rb
|
|
46
|
+
- lib/tap/generator/generators/root.rb
|
|
47
|
+
- lib/tap/generator/generators/task.rb
|
|
48
|
+
- lib/tap/generator/manifest.rb
|
|
49
|
+
- lib/tap/generator/preview.rb
|
|
50
|
+
- tap.yml
|
|
51
|
+
- templates/tap/generator/generators/command/command.erb
|
|
52
|
+
- templates/tap/generator/generators/generator/task.erb
|
|
53
|
+
- templates/tap/generator/generators/generator/test.erb
|
|
54
|
+
- templates/tap/generator/generators/root/MIT-LICENSE
|
|
55
|
+
- templates/tap/generator/generators/root/README
|
|
56
|
+
- templates/tap/generator/generators/root/Rakefile
|
|
57
|
+
- templates/tap/generator/generators/root/Rapfile
|
|
58
|
+
- templates/tap/generator/generators/root/gemspec
|
|
59
|
+
- templates/tap/generator/generators/root/test/tap_test_helper.rb
|
|
60
|
+
- templates/tap/generator/generators/task/task.erb
|
|
61
|
+
- templates/tap/generator/generators/task/test.erb
|
|
62
|
+
- History
|
|
63
|
+
- README
|
|
64
|
+
- MIT-LICENSE
|
|
65
|
+
has_rdoc: true
|
|
66
|
+
homepage: http://tap.rubyforge.org/tap-gen
|
|
67
|
+
post_install_message:
|
|
68
|
+
rdoc_options:
|
|
69
|
+
- --main
|
|
70
|
+
- README
|
|
71
|
+
- -S
|
|
72
|
+
- -N
|
|
73
|
+
- --title
|
|
74
|
+
- Tap-Generator
|
|
75
|
+
require_paths:
|
|
76
|
+
- lib
|
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: "0"
|
|
82
|
+
version:
|
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
|
+
requirements:
|
|
85
|
+
- - ">="
|
|
86
|
+
- !ruby/object:Gem::Version
|
|
87
|
+
version: "0"
|
|
88
|
+
version:
|
|
89
|
+
requirements: []
|
|
90
|
+
|
|
91
|
+
rubyforge_project: tap
|
|
92
|
+
rubygems_version: 1.3.1
|
|
93
|
+
signing_key:
|
|
94
|
+
specification_version: 2
|
|
95
|
+
summary: Generators for Tap
|
|
96
|
+
test_files: []
|
|
97
|
+
|