bahuvrihi-tap 0.10.7 → 0.10.8
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +0 -2
- data/README +20 -31
- data/bin/rap +18 -8
- data/cgi/run.rb +47 -37
- data/cmd/console.rb +1 -1
- data/cmd/destroy.rb +3 -3
- data/cmd/generate.rb +3 -3
- data/cmd/manifest.rb +61 -53
- data/cmd/run.rb +1 -1
- data/doc/Class Reference +119 -110
- data/doc/Command Reference +76 -123
- data/doc/Syntax Reference +290 -0
- data/doc/Tutorial +307 -237
- data/lib/tap.rb +1 -12
- data/lib/tap/app.rb +46 -71
- data/lib/tap/constants.rb +1 -1
- data/lib/tap/declarations.rb +110 -100
- data/lib/tap/env.rb +141 -173
- data/lib/tap/exe.rb +5 -5
- data/lib/tap/file_task.rb +2 -2
- data/lib/tap/generator/base.rb +0 -4
- data/lib/tap/generator/destroy.rb +8 -12
- data/lib/tap/generator/generate.rb +19 -14
- data/lib/tap/generator/generators/command/command_generator.rb +1 -1
- data/lib/tap/generator/generators/config/config_generator.rb +3 -3
- data/lib/tap/generator/generators/file_task/file_task_generator.rb +1 -1
- data/lib/tap/generator/generators/generator/generator_generator.rb +27 -0
- data/lib/tap/generator/generators/generator/templates/task.erb +27 -0
- data/lib/tap/generator/generators/root/root_generator.rb +12 -12
- data/lib/tap/generator/generators/root/templates/Rakefile +1 -2
- data/lib/tap/generator/generators/root/templates/tapfile +11 -8
- data/lib/tap/generator/generators/task/task_generator.rb +1 -3
- data/lib/tap/generator/generators/task/templates/test.erb +1 -3
- data/lib/tap/root.rb +4 -2
- data/lib/tap/support/aggregator.rb +16 -3
- data/lib/tap/support/assignments.rb +10 -9
- data/lib/tap/support/audit.rb +58 -62
- data/lib/tap/support/class_configuration.rb +32 -43
- data/lib/tap/support/combinator.rb +7 -7
- data/lib/tap/support/configurable.rb +13 -14
- data/lib/tap/support/configurable_class.rb +6 -30
- data/lib/tap/support/configuration.rb +36 -9
- data/lib/tap/support/constant.rb +75 -13
- data/lib/tap/support/constant_manifest.rb +115 -0
- data/lib/tap/support/dependencies.rb +27 -67
- data/lib/tap/support/dependency.rb +44 -0
- data/lib/tap/support/executable.rb +78 -109
- data/lib/tap/support/executable_queue.rb +1 -1
- data/lib/tap/support/gems.rb +6 -0
- data/lib/tap/support/gems/rack.rb +197 -84
- data/lib/tap/support/instance_configuration.rb +29 -3
- data/lib/tap/support/intern.rb +46 -0
- data/lib/tap/support/join.rb +67 -11
- data/lib/tap/support/joins.rb +2 -0
- data/lib/tap/support/joins/fork.rb +1 -0
- data/lib/tap/support/joins/merge.rb +3 -1
- data/lib/tap/support/joins/sequence.rb +2 -2
- data/lib/tap/support/joins/switch.rb +3 -1
- data/lib/tap/support/joins/sync_merge.rb +6 -0
- data/lib/tap/support/lazy_attributes.rb +16 -1
- data/lib/tap/support/lazydoc.rb +21 -21
- data/lib/tap/support/lazydoc/comment.rb +59 -55
- data/lib/tap/support/lazydoc/definition.rb +36 -0
- data/lib/tap/support/lazydoc/document.rb +37 -13
- data/lib/tap/support/manifest.rb +120 -131
- data/lib/tap/support/minimap.rb +90 -0
- data/lib/tap/support/node.rb +4 -6
- data/lib/tap/support/parser.rb +63 -6
- data/lib/tap/support/schema.rb +11 -2
- data/lib/tap/support/shell_utils.rb +3 -5
- data/lib/tap/support/string_ext.rb +60 -0
- data/lib/tap/support/tdoc.rb +2 -2
- data/lib/tap/support/templater.rb +29 -15
- data/lib/tap/support/validation.rb +22 -11
- data/lib/tap/task.rb +155 -156
- data/lib/tap/tasks/load.rb +95 -8
- data/lib/tap/test/extensions.rb +2 -1
- data/lib/tap/test/script_tester.rb +7 -1
- data/template/index.erb +39 -32
- metadata +13 -13
- data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +0 -15
- data/lib/tap/patches/rake/rake_test_loader.rb +0 -8
- data/lib/tap/patches/rake/testtask.rb +0 -57
- data/lib/tap/patches/ruby19/backtrace_filter.rb +0 -51
- data/lib/tap/patches/ruby19/parsedate.rb +0 -16
- data/lib/tap/spec.rb +0 -42
- data/lib/tap/spec/adapter.rb +0 -25
- data/lib/tap/spec/inheritable_class_test_root.rb +0 -9
- data/lib/tap/support/constant_utils.rb +0 -127
- data/lib/tap/support/summary.rb +0 -30
@@ -5,20 +5,29 @@ require 'tap/support/configuration'
|
|
5
5
|
module Tap
|
6
6
|
module Support
|
7
7
|
|
8
|
-
# ClassConfiguration tracks
|
9
|
-
# Configurable class.
|
8
|
+
# ClassConfiguration tracks configurations defined by a Configurable class.
|
10
9
|
class ClassConfiguration
|
11
10
|
include Enumerable
|
12
11
|
|
13
|
-
|
12
|
+
config_templates_dir = File.expand_path File.dirname(__FILE__) + "/../generator/generators/config/templates"
|
13
|
+
|
14
|
+
# The path to the :doc template (see inspect)
|
15
|
+
DOC_TEMPLATE_PATH = File.join(config_templates_dir, 'doc.erb')
|
16
|
+
|
17
|
+
# The path to the :nodoc template (see inspect)
|
18
|
+
NODOC_TEMPLATE_PATH = File.join(config_templates_dir, 'nodoc.erb')
|
19
|
+
|
20
|
+
# The Configurable class receiving new configurations
|
14
21
|
attr_reader :receiver
|
15
22
|
|
16
|
-
#
|
23
|
+
# An Assignments tracking the assignment of config keys to receivers
|
17
24
|
attr_reader :assignments
|
18
25
|
|
19
|
-
# A map of
|
26
|
+
# A map of [key, Configuration] pairs
|
20
27
|
attr_reader :map
|
21
|
-
|
28
|
+
|
29
|
+
# Generates a new ClassConfiguration for the receiver. If a parent is
|
30
|
+
# provided, configurations will be inherited from it.
|
22
31
|
def initialize(receiver, parent=nil)
|
23
32
|
@receiver = receiver
|
24
33
|
|
@@ -34,9 +43,9 @@ module Tap
|
|
34
43
|
end
|
35
44
|
end
|
36
45
|
|
37
|
-
# Initializes a Configuration using the inputs and sets
|
38
|
-
#
|
39
|
-
#
|
46
|
+
# Initializes a Configuration using the inputs and sets using name
|
47
|
+
# as a key. Any existing config by the same name is overridden.
|
48
|
+
# Returns the new config.
|
40
49
|
def add(name, default=nil, attributes={})
|
41
50
|
self[name] = Configuration.new(name.to_sym, default, attributes)
|
42
51
|
end
|
@@ -46,12 +55,12 @@ module Tap
|
|
46
55
|
self[key] = nil
|
47
56
|
end
|
48
57
|
|
49
|
-
# Gets the
|
58
|
+
# Gets the config specified by key. The key is symbolized.
|
50
59
|
def [](key)
|
51
60
|
map[key.to_sym]
|
52
61
|
end
|
53
62
|
|
54
|
-
# Assigns the
|
63
|
+
# Assigns the config to key. A nil config unassigns the
|
55
64
|
# configuration key. The key is symbolized.
|
56
65
|
def []=(key, config)
|
57
66
|
key = key.to_sym
|
@@ -91,7 +100,7 @@ module Tap
|
|
91
100
|
end
|
92
101
|
|
93
102
|
# Calls block once for each [receiver, key, config] in self,
|
94
|
-
# passing those elements as parameters
|
103
|
+
# passing those elements as parameters in the order in
|
95
104
|
# which they were assigned.
|
96
105
|
def each
|
97
106
|
assignments.each do |receiver, key|
|
@@ -100,7 +109,7 @@ module Tap
|
|
100
109
|
end
|
101
110
|
|
102
111
|
# Calls block once for each [key, config] pair in self,
|
103
|
-
# passing those elements as parameters
|
112
|
+
# passing those elements as parameters in the order in
|
104
113
|
# which they were assigned.
|
105
114
|
def each_pair
|
106
115
|
assignments.each do |receiver, key|
|
@@ -114,7 +123,7 @@ module Tap
|
|
114
123
|
InstanceConfiguration.new(self, receiver, store)
|
115
124
|
end
|
116
125
|
|
117
|
-
# Returns a hash of the
|
126
|
+
# Returns a hash of the [key, config.default] pairs in self.
|
118
127
|
def to_hash
|
119
128
|
hash = {}
|
120
129
|
each_pair {|key, config| hash[key] = config.default }
|
@@ -130,36 +139,16 @@ module Tap
|
|
130
139
|
code_comments
|
131
140
|
end
|
132
141
|
|
133
|
-
#
|
134
|
-
|
135
|
-
|
136
|
-
#
|
137
|
-
NODOC_TEMPLATE_PATH = File.expand_path File.dirname(__FILE__) + "/../generator/generators/config/templates/nodoc.erb"
|
138
|
-
|
139
|
-
# Formats the configurations using the specified template. Two default
|
140
|
-
# templates are defined, <tt>:doc</tt> and <tt>:nodoc</tt>. These map
|
141
|
-
# to the contents of DOC_TEMPLATE_PATH and NODOC_TEMPLATE_PATH and
|
142
|
-
# correspond to the documented and undocumented config generator templates.
|
143
|
-
#
|
144
|
-
# == Custom Templates
|
145
|
-
#
|
146
|
-
# format_str initializes a Templater which formats each [receiver, configurations]
|
147
|
-
# pair in turn, and puts the output to the target using <tt><<</tt>. The
|
148
|
-
# templater is assigned the following attributes for use in formatting:
|
149
|
-
#
|
150
|
-
# receiver:: The receiver
|
151
|
-
# configurations:: An array of configurations and associated comments
|
152
|
-
#
|
153
|
-
# In the template these can be accessed as any ERB locals, for example:
|
154
|
-
#
|
155
|
-
# <%= receiver.to_s %>
|
156
|
-
# <% configurations.each do |key, config, comment| %>
|
157
|
-
# ...
|
158
|
-
# <% end %>
|
142
|
+
# Inspects the configurations using the specified template. Templates
|
143
|
+
# are used for format each [receiver, configurations] pair in self.
|
144
|
+
# See DEFAULT_TEMPLATE as a model. The results of each template cycle
|
145
|
+
# are pushed to target.
|
159
146
|
#
|
160
|
-
#
|
161
|
-
#
|
162
|
-
|
147
|
+
# Two default templates are defined, <tt>:doc</tt> and <tt>:nodoc</tt>.
|
148
|
+
# These map to the contents of DOC_TEMPLATE_PATH and NODOC_TEMPLATE_PATH
|
149
|
+
# and correspond to the documented and undocumented
|
150
|
+
# Tap::Generator::Generators::ConfigGenerator templates.
|
151
|
+
def inspect(template=:doc, target="")
|
163
152
|
Lazydoc.resolve_comments(code_comments)
|
164
153
|
|
165
154
|
template = case template
|
@@ -9,14 +9,14 @@ module Tap
|
|
9
9
|
# c = Combinator.new [1,2], [3,4]
|
10
10
|
# c.to_a # => [[1,3], [1,4], [2,3], [2,4]]
|
11
11
|
#
|
12
|
-
# Combinators can take any object that responds to
|
12
|
+
# Combinators can take any object that responds to each as an
|
13
13
|
# input set; normally arrays are used.
|
14
14
|
#
|
15
15
|
# === Implementation
|
16
16
|
#
|
17
17
|
# Combinator iteratively combines each element from the first set (a)
|
18
18
|
# with each element from the second set (b). When more than two sets
|
19
|
-
# are given, the
|
19
|
+
# are given, the second and remaining sets are bundled into a
|
20
20
|
# Combinator, which then acts as the second set.
|
21
21
|
#
|
22
22
|
# c = Combinator.new [1,2], [3,4], [5,6]
|
@@ -35,14 +35,14 @@ module Tap
|
|
35
35
|
class Combinator
|
36
36
|
include Enumerable
|
37
37
|
|
38
|
-
# The first set
|
38
|
+
# The first set
|
39
39
|
attr_reader :a
|
40
40
|
|
41
|
-
# The second set
|
41
|
+
# The second set
|
42
42
|
attr_reader :b
|
43
43
|
|
44
|
-
# Creates a new Combinator.
|
45
|
-
#
|
44
|
+
# Creates a new Combinator. Each input must respond
|
45
|
+
# to each, or be nil.
|
46
46
|
def initialize(*sets)
|
47
47
|
@a = make_set(sets.shift)
|
48
48
|
@b = make_set(*sets)
|
@@ -71,7 +71,7 @@ module Tap
|
|
71
71
|
end
|
72
72
|
|
73
73
|
# Passes each combination as an array to the input block.
|
74
|
-
def each
|
74
|
+
def each # :yields: combination
|
75
75
|
case
|
76
76
|
when !(@a.empty? || @b.empty?)
|
77
77
|
@a.each do |a|
|
@@ -21,7 +21,7 @@ module Tap
|
|
21
21
|
# c.config.class # => InstanceConfiguration
|
22
22
|
# c.config # => {:one => 'one', :two => 'two', :three => 'three'}
|
23
23
|
#
|
24
|
-
# The <tt>config</tt> object acts as a
|
24
|
+
# The <tt>config</tt> object acts as a forwarding hash; declared configurations
|
25
25
|
# map to accessors while undeclared configurations are stored internally:
|
26
26
|
#
|
27
27
|
# c.config[:one] = 'ONE'
|
@@ -33,8 +33,8 @@ module Tap
|
|
33
33
|
# c.config[:undeclared] = 'value'
|
34
34
|
# c.config.store # => {:undeclared => 'value'}
|
35
35
|
#
|
36
|
-
# The writer
|
37
|
-
# The Validation module provides a number of common validation
|
36
|
+
# The writer for a configuration can be defined by providing a block to config.
|
37
|
+
# The Validation module provides a number of common validation/transform
|
38
38
|
# blocks which can be accessed through the class method 'c':
|
39
39
|
#
|
40
40
|
# class SubClass < ConfigClass
|
@@ -55,21 +55,21 @@ module Tap
|
|
55
55
|
# s.two = nil # !> ValidationError
|
56
56
|
# s.two = 'str' # !> ValidationError
|
57
57
|
#
|
58
|
-
# As shown above, configurations are inherited from the parent and
|
58
|
+
# As shown above, configurations are inherited from the parent and may be
|
59
59
|
# overridden in subclasses. See ConfigurableClass for more details.
|
60
60
|
#
|
61
61
|
module Configurable
|
62
62
|
|
63
63
|
# Extends including classes with ConfigurableClass
|
64
|
-
def self.included(mod)
|
64
|
+
def self.included(mod) # :nodoc:
|
65
65
|
mod.extend Support::ConfigurableClass if mod.kind_of?(Class)
|
66
66
|
end
|
67
67
|
|
68
|
-
#
|
68
|
+
# An InstanceConfiguration with configurations for self
|
69
69
|
attr_reader :config
|
70
70
|
|
71
|
-
# Reconfigures self with the given
|
72
|
-
#
|
71
|
+
# Reconfigures self with the given overrides. Only the specified configs
|
72
|
+
# are modified. Keys are symbolized.
|
73
73
|
#
|
74
74
|
# Returns self.
|
75
75
|
def reconfigure(overrides={})
|
@@ -81,9 +81,9 @@ module Tap
|
|
81
81
|
self
|
82
82
|
end
|
83
83
|
|
84
|
-
# Reinitializes
|
85
|
-
#
|
86
|
-
# separate from the original object
|
84
|
+
# Reinitializes configurations in the copy such that
|
85
|
+
# the new object has it's own set of configurations,
|
86
|
+
# separate from the original object.
|
87
87
|
def initialize_copy(orig)
|
88
88
|
super
|
89
89
|
initialize_config(orig.config)
|
@@ -91,9 +91,8 @@ module Tap
|
|
91
91
|
|
92
92
|
protected
|
93
93
|
|
94
|
-
# Initializes config to an InstanceConfiguration
|
95
|
-
#
|
96
|
-
# overrides. Override keys are symbolized.
|
94
|
+
# Initializes config to an InstanceConfiguration. Default config values
|
95
|
+
# are overridden as specified by overrides. Keys are symbolized.
|
97
96
|
def initialize_config(overrides={})
|
98
97
|
class_config = self.class.configurations
|
99
98
|
@config = class_config.instance_config
|
@@ -7,9 +7,9 @@ module Tap
|
|
7
7
|
module Support
|
8
8
|
autoload(:Templater, 'tap/support/templater')
|
9
9
|
|
10
|
-
# ConfigurableClass
|
11
|
-
#
|
12
|
-
#
|
10
|
+
# ConfigurableClass defines class methods used by a Configurable class to
|
11
|
+
# declare configurations. In addition to registering key-value pairs,
|
12
|
+
# these methods generate readers and writers, much like attr_accessor.
|
13
13
|
#
|
14
14
|
# class ConfigurableClass
|
15
15
|
# extend ConfigurableClass
|
@@ -22,31 +22,6 @@ module Tap
|
|
22
22
|
# c.respond_to?('one') # => true
|
23
23
|
# c.respond_to?('one=') # => true
|
24
24
|
#
|
25
|
-
# If a block is given, the block will be used to create the writer method
|
26
|
-
# for the config. Used in this manner, config defines a <tt>config_key=</tt> method
|
27
|
-
# wherein <tt>@config_key</tt> will be set to the return value of the block.
|
28
|
-
#
|
29
|
-
# class AnotherConfigurableClass
|
30
|
-
# extend ConfigurableClass
|
31
|
-
# config(:one, 'one') {|value| value.upcase }
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# ac = AnotherConfigurableClass.new
|
35
|
-
# ac.one = 'value'
|
36
|
-
# ac.one # => 'VALUE'
|
37
|
-
#
|
38
|
-
# The block has class-context in this case. To have instance-context, use the
|
39
|
-
# config_attr method which defines the writer method using the block directly.
|
40
|
-
#
|
41
|
-
# class YetAnotherConfigurableClass
|
42
|
-
# extend ConfigurableClass
|
43
|
-
# config_attr(:one, 'one') {|value| @one = value.reverse }
|
44
|
-
# end
|
45
|
-
#
|
46
|
-
# ac = YetAnotherConfigurableClass.new
|
47
|
-
# ac.one = 'value'
|
48
|
-
# ac.one # => 'eulav'
|
49
|
-
#
|
50
25
|
module ConfigurableClass
|
51
26
|
include Tap::Support::LazyAttributes
|
52
27
|
|
@@ -54,7 +29,7 @@ module Tap
|
|
54
29
|
attr_reader :configurations
|
55
30
|
|
56
31
|
# Sets the source_file for base and initializes base.configurations.
|
57
|
-
def self.extended(base)
|
32
|
+
def self.extended(base) # :nodoc:
|
58
33
|
caller.each_with_index do |line, index|
|
59
34
|
case line
|
60
35
|
when /\/configurable.rb/ then next
|
@@ -70,7 +45,7 @@ module Tap
|
|
70
45
|
# When subclassed, the parent.configurations are duplicated and passed to
|
71
46
|
# the child class where they can be extended/modified without affecting
|
72
47
|
# the configurations of the parent class.
|
73
|
-
def inherited(child)
|
48
|
+
def inherited(child) # :nodoc:
|
74
49
|
unless child.instance_variable_defined?(:@source_file)
|
75
50
|
caller.first =~ Lazydoc::CALLER_REGEXP
|
76
51
|
child.instance_variable_set(:@source_file, File.expand_path($1))
|
@@ -80,6 +55,7 @@ module Tap
|
|
80
55
|
super
|
81
56
|
end
|
82
57
|
|
58
|
+
# Returns the lazydoc for self.
|
83
59
|
def lazydoc(resolve=true)
|
84
60
|
Lazydoc.resolve_comments(configurations.code_comments) if resolve
|
85
61
|
super
|
@@ -1,8 +1,12 @@
|
|
1
1
|
module Tap
|
2
2
|
module Support
|
3
|
+
|
4
|
+
# Represents a configuration declared by a Configurable class.
|
3
5
|
class Configuration
|
4
6
|
class << self
|
5
|
-
|
7
|
+
|
8
|
+
# Matches a short option
|
9
|
+
SHORT_OPTION = /^-[A-z]$/
|
6
10
|
|
7
11
|
# Turns the input string into a short-format option. Raises
|
8
12
|
# an error if the option does not match SHORT_REGEXP.
|
@@ -13,11 +17,12 @@ module Tap
|
|
13
17
|
def shortify(str)
|
14
18
|
str = str.to_s
|
15
19
|
str = "-#{str}" unless str[0] == ?-
|
16
|
-
raise "invalid short option: #{str}" unless str =~
|
20
|
+
raise "invalid short option: #{str}" unless str =~ SHORT_OPTION
|
17
21
|
str
|
18
22
|
end
|
19
|
-
|
20
|
-
|
23
|
+
|
24
|
+
# Matches a long option
|
25
|
+
LONG_OPTION = /^--(\[no-\])?([A-z][\w-]*)$/
|
21
26
|
|
22
27
|
# Turns the input string into a long-format option. Raises
|
23
28
|
# an error if the option does not match LONG_REGEXP.
|
@@ -33,7 +38,7 @@ module Tap
|
|
33
38
|
str = "--#{str}" unless str.index("--")
|
34
39
|
str.gsub!(/_/, '-') if hyphenize
|
35
40
|
|
36
|
-
raise "invalid long option: #{str}" unless str =~
|
41
|
+
raise "invalid long option: #{str}" unless str =~ LONG_OPTION
|
37
42
|
|
38
43
|
if switch_notation && $1.nil?
|
39
44
|
str = "--[no-]#{$2}"
|
@@ -43,12 +48,24 @@ module Tap
|
|
43
48
|
end
|
44
49
|
end
|
45
50
|
|
51
|
+
# The name of the configuration
|
46
52
|
attr_reader :name
|
53
|
+
|
54
|
+
# The reader method, by default name
|
47
55
|
attr_reader :reader
|
56
|
+
|
57
|
+
# The writer method, by default name=
|
48
58
|
attr_reader :writer
|
59
|
+
|
60
|
+
# True if the default value may be duplicated
|
49
61
|
attr_reader :duplicable
|
62
|
+
|
63
|
+
# An array of optional metadata for self
|
50
64
|
attr_reader :attributes
|
51
|
-
|
65
|
+
|
66
|
+
# Initializes a new Configuration with the specified name and default
|
67
|
+
# value. Options may specify an alternate reader/writer; any
|
68
|
+
# additional options are set as attributes.
|
52
69
|
def initialize(name, default=nil, options={})
|
53
70
|
@name = name
|
54
71
|
self.default = default
|
@@ -59,11 +76,12 @@ module Tap
|
|
59
76
|
end
|
60
77
|
|
61
78
|
# Sets the default value for self and determines if the
|
62
|
-
# default is duplicable
|
63
|
-
# Numeric, and
|
79
|
+
# default is duplicable. Non-duplicable values include
|
80
|
+
# nil, true, false, Symbol, Numeric, and any object that
|
81
|
+
# does not respond to dup.
|
64
82
|
def default=(value)
|
65
83
|
@duplicable = case value
|
66
|
-
when nil, true, false, Symbol, Numeric then false
|
84
|
+
when nil, true, false, Symbol, Numeric, Method then false
|
67
85
|
else value.respond_to?(:dup)
|
68
86
|
end
|
69
87
|
|
@@ -88,22 +106,29 @@ module Tap
|
|
88
106
|
@writer = value == nil ? value : value.to_sym
|
89
107
|
end
|
90
108
|
|
109
|
+
# The argument name for self: either attributes[:arg_name]
|
110
|
+
# or name.to_s.upcase
|
91
111
|
def arg_name
|
92
112
|
attributes[:arg_name] || name.to_s.upcase
|
93
113
|
end
|
94
114
|
|
115
|
+
# The argument type for self: either attributes[:arg_type]
|
116
|
+
# or :mandatory
|
95
117
|
def arg_type
|
96
118
|
attributes[:arg_type] || :mandatory
|
97
119
|
end
|
98
120
|
|
121
|
+
# The long version of name.
|
99
122
|
def long(switch_notation=false, hyphenize=true)
|
100
123
|
Configuration.longify(attributes[:long] || name.to_s, switch_notation, hyphenize)
|
101
124
|
end
|
102
125
|
|
126
|
+
# The short version of name.
|
103
127
|
def short
|
104
128
|
attributes[:short] ? Configuration.shortify(attributes[:short]) : nil
|
105
129
|
end
|
106
130
|
|
131
|
+
# The description for self: attributes[:desc]
|
107
132
|
def desc
|
108
133
|
attributes[:desc]
|
109
134
|
end
|
@@ -119,6 +144,8 @@ module Tap
|
|
119
144
|
self.default(false) == another.default(false)
|
120
145
|
end
|
121
146
|
|
147
|
+
# Returns self as an argv that can be used to register
|
148
|
+
# an option with OptionParser.
|
122
149
|
def to_optparse_argv
|
123
150
|
argtype = case arg_type
|
124
151
|
when :optional
|
data/lib/tap/support/constant.rb
CHANGED
@@ -1,18 +1,79 @@
|
|
1
|
-
require 'tap/support/
|
2
|
-
class String # :nodoc:
|
3
|
-
include Tap::Support::ConstantUtils
|
4
|
-
end
|
1
|
+
require 'tap/support/string_ext'
|
5
2
|
|
6
3
|
module Tap
|
7
4
|
module Support
|
5
|
+
|
6
|
+
# A Constant serves as a placeholder for an actual constant, sort of like
|
7
|
+
# autoload. Use the constantize method to retrieve the actual constant;
|
8
|
+
# if it doesn't exist, constantize requires require_path and tries again.
|
9
|
+
#
|
10
|
+
# Object.const_defined?(:Net) # => false
|
11
|
+
# $".include?('net/http') # => false
|
12
|
+
#
|
13
|
+
# http = Constant.new('Net::HTTP', 'net/http')
|
14
|
+
# http.constantize # => Net::HTTP
|
15
|
+
# $".include?('net/http') # => true
|
16
|
+
#
|
8
17
|
class Constant
|
18
|
+
class << self
|
19
|
+
|
20
|
+
# Tries to find a declared constant under base with the specified
|
21
|
+
# const_name. When a constant is missing, constantize yields
|
22
|
+
# the current base and any non-existant constant names the block,
|
23
|
+
# if given, or raises a NameError. The block is expected
|
24
|
+
# to return the proper constant.
|
25
|
+
#
|
26
|
+
# module ConstName; end
|
27
|
+
#
|
28
|
+
# Constant.constantize('ConstName') # => ConstName
|
29
|
+
# Constant.constantize('Non::Existant') { ConstName } # => ConstName
|
30
|
+
#
|
31
|
+
def constantize(const_name, base=Object) # :yields: base, missing_const_names
|
32
|
+
unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ const_name
|
33
|
+
raise NameError, "#{const_name.inspect} is not a valid constant name!"
|
34
|
+
end
|
35
|
+
|
36
|
+
constants = $1.split(/::/)
|
37
|
+
while !constants.empty?
|
38
|
+
unless const_is_defined?(base, constants[0])
|
39
|
+
if block_given?
|
40
|
+
return yield(base, constants)
|
41
|
+
else
|
42
|
+
raise NameError.new("uninitialized constant #{const_name}", constants[0])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
base = base.const_get(constants.shift)
|
46
|
+
end
|
47
|
+
base
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# helper method. Determines if a constant named
|
53
|
+
# name is defined in const. The implementation
|
54
|
+
# (annoyingly) has to be different for ruby 1.9
|
55
|
+
# due to changes in the API.
|
56
|
+
case RUBY_VERSION
|
57
|
+
when /^1.9/
|
58
|
+
def const_is_defined?(const, name) # :nodoc:
|
59
|
+
const.const_defined?(name, false)
|
60
|
+
end
|
61
|
+
else
|
62
|
+
def const_is_defined?(const, name) # :nodoc:
|
63
|
+
const.const_defined?(name)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
9
67
|
|
10
|
-
# The
|
68
|
+
# The constant name
|
11
69
|
attr_reader :name
|
12
70
|
|
13
|
-
# The path to load to initialize
|
71
|
+
# The path to load to initialize a missing constant
|
14
72
|
attr_reader :require_path
|
15
|
-
|
73
|
+
|
74
|
+
# Initializes a new Constant with the specified constant
|
75
|
+
# name and require_path. The name should be a valid
|
76
|
+
# constant name.
|
16
77
|
def initialize(name, require_path=nil)
|
17
78
|
@name = name
|
18
79
|
@require_path = require_path
|
@@ -48,9 +109,9 @@ module Tap
|
|
48
109
|
@nesting_depth ||= nesting.split(/::/).length
|
49
110
|
end
|
50
111
|
|
51
|
-
# Returns the document for require_path
|
112
|
+
# Returns the Lazydoc document for require_path.
|
52
113
|
def document
|
53
|
-
require_path ?
|
114
|
+
require_path ? Lazydoc[require_path] : nil
|
54
115
|
end
|
55
116
|
|
56
117
|
# True if another is a Constant with the same name
|
@@ -63,12 +124,13 @@ module Tap
|
|
63
124
|
|
64
125
|
# Looks up and returns the constant indicated by name.
|
65
126
|
# If the constant cannot be found, the constantize
|
66
|
-
# requires require_path and tries again.
|
67
|
-
#
|
127
|
+
# requires require_path and tries again.
|
128
|
+
#
|
129
|
+
# Raises a NameError if the constant cannot be found.
|
68
130
|
def constantize
|
69
|
-
name
|
131
|
+
Constant.constantize(name) do
|
70
132
|
require require_path if require_path
|
71
|
-
|
133
|
+
Constant.constantize(name)
|
72
134
|
end
|
73
135
|
end
|
74
136
|
|