baretest 0.2.4 → 0.4.0.pre1
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/LICENSE.txt +6 -6
- data/MANIFEST.txt +40 -18
- data/README.rdoc +8 -1
- data/bin/baretest +126 -118
- data/doc/baretest.rdoc +1 -1
- data/doc/mocking_stubbing_test_doubles.rdoc +31 -3
- data/doc/news/news-0.3.0.rdoc +7 -0
- data/doc/quickref.rdoc +74 -28
- data/doc/whats_going_on.rdoc +5 -0
- data/doc/writing_tests.rdoc +25 -13
- data/examples/components/rack-test.rb +17 -0
- data/examples/{tests/irb_mode → irb_mode}/failures.rb +0 -0
- data/examples/rake/test.rake +40 -0
- data/examples/tests/01_basics_I.rb +34 -0
- data/examples/tests/02_basics_II_helpers.rb +25 -0
- data/examples/tests/03_basics_III_setup_and_teardown.rb +53 -0
- data/examples/tests/04_advanced_I_dependencies.rb +31 -0
- data/examples/tests/05_advanced_II_tags.rb +12 -0
- data/examples/tests/06_advanced_III_requires.rb +21 -0
- data/examples/tests/07_advanced_IV_components.rb +48 -0
- data/examples/tests/08_expert_I_setup_variants.rb +46 -0
- data/lib/baretest.rb +142 -21
- data/lib/baretest/assertion.rb +83 -92
- data/lib/baretest/assertion/context.rb +9 -0
- data/lib/baretest/assertion/support.rb +88 -61
- data/lib/baretest/commandline.rb +268 -0
- data/lib/baretest/formatter.rb +58 -0
- data/lib/baretest/invalidselectors.rb +24 -0
- data/lib/baretest/irb_mode.rb +100 -58
- data/lib/baretest/persistence.rb +94 -0
- data/lib/baretest/run.rb +138 -37
- data/lib/baretest/run/cli.rb +97 -43
- data/lib/baretest/run/minimal.rb +2 -1
- data/lib/baretest/run/none.rb +21 -0
- data/lib/baretest/run/xml.rb +21 -19
- data/lib/baretest/setup.rb +2 -0
- data/lib/baretest/status.rb +93 -0
- data/lib/baretest/suite.rb +185 -59
- data/lib/baretest/uid.rb +51 -0
- data/lib/baretest/use/mocha.rb +24 -0
- data/lib/baretest/use/rack_test.rb +9 -0
- data/lib/baretest/use/rr.rb +17 -0
- data/lib/baretest/version.rb +18 -4
- data/lib/command.rb +36 -0
- data/lib/command/argument.rb +11 -0
- data/lib/command/decoratinghash.rb +31 -0
- data/lib/command/definition.rb +294 -0
- data/lib/command/directorynotfounderror.rb +11 -0
- data/lib/command/env.rb +11 -0
- data/lib/command/filenotfounderror.rb +11 -0
- data/lib/command/kernel.rb +14 -0
- data/lib/command/nodirectoryerror.rb +11 -0
- data/lib/command/nofileerror.rb +11 -0
- data/lib/command/option.rb +16 -0
- data/lib/command/parser.rb +145 -0
- data/lib/command/result.rb +11 -0
- data/lib/command/types.rb +33 -0
- data/lib/command/version.rb +28 -0
- data/test/setup.rb +3 -0
- data/test/suite/lib/baretest.rb +0 -178
- data/test/suite/lib/baretest/assertion.rb +133 -112
- data/test/suite/lib/baretest/assertion/context.rb +40 -0
- data/test/suite/lib/baretest/assertion/failure.rb +19 -0
- data/test/suite/lib/baretest/assertion/skip.rb +19 -0
- data/test/suite/lib/baretest/assertion/support.rb +366 -84
- data/test/suite/lib/baretest/run.rb +114 -15
- data/test/suite/lib/baretest/suite.rb +70 -29
- metadata +46 -24
- data/examples/test.rake +0 -65
- data/examples/tests/mock_developer/test/helper/mocks.rb +0 -0
- data/examples/tests/mock_developer/test/setup.rb +0 -57
- data/examples/tests/mock_developer/test/suite/mock_demo.rb +0 -19
- data/examples/tests/overview/test.rb +0 -89
- data/examples/tests/variations/variations_01.rb +0 -14
- data/examples/tests/variations/variations_02.rb +0 -19
- data/examples/tests/variations/variations_03.rb +0 -19
- data/lib/baretest/mocha.rb +0 -18
- data/lib/baretest/rr.rb +0 -16
- data/lib/baretest/run/errors.rb +0 -49
- data/lib/baretest/skipped.rb +0 -15
- data/lib/baretest/skipped/assertion.rb +0 -20
- data/lib/baretest/skipped/suite.rb +0 -49
- data/test/external/bootstraptest.rb +0 -5
- data/test/external/bootstrapwrap.rb +0 -2
- data/test/helper/mocks.rb +0 -0
data/lib/baretest/uid.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2010 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
module BareTest
|
10
|
+
|
11
|
+
# Generate a unique ID.
|
12
|
+
# Not using uuid simply to avoid two dependencies (uuid, and uuid's dependency
|
13
|
+
# 'macaddr').
|
14
|
+
class UID
|
15
|
+
|
16
|
+
# :nodoc:
|
17
|
+
Epoch = Time.utc(2000,1,1).to_i
|
18
|
+
|
19
|
+
# The numeric value of the uid (an Integer)
|
20
|
+
attr_reader :value
|
21
|
+
|
22
|
+
# Returns a 32byte long String containing a new 16 byte random value
|
23
|
+
# in hex representation
|
24
|
+
def self.hex_uid
|
25
|
+
new.hex
|
26
|
+
end
|
27
|
+
|
28
|
+
# Create a 128bit (16 Byte) long random number
|
29
|
+
def initialize
|
30
|
+
now = Time.now
|
31
|
+
|
32
|
+
# Works for the next 100 years - should be enough
|
33
|
+
# after that, it'll wrap around.
|
34
|
+
time_part_52 = (((now.to_i-Epoch) & 0xffffffff) << 20) + now.usec
|
35
|
+
|
36
|
+
# Not solid, but for the purposes, should work
|
37
|
+
process_part32 = (Thread.current.object_id ^ Process.pid) & 0xfffffffff
|
38
|
+
|
39
|
+
# Add a bit of random noise
|
40
|
+
random_part44 = Kernel.rand(0x100000000000)
|
41
|
+
|
42
|
+
@value = (random_part44 << 84) + (process_part32 << 52) + time_part_52
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns a 32byte long String containing the 16 byte random value
|
46
|
+
# in hex representation
|
47
|
+
def hex
|
48
|
+
"%032x" % @value
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Original by dominikh
|
2
|
+
# Adapted to :use framework by apeiros
|
3
|
+
|
4
|
+
# This file provides integration with the "mocha" mocking framework.
|
5
|
+
|
6
|
+
|
7
|
+
# Load this file and get integration with the "rr" mocking framework.
|
8
|
+
|
9
|
+
BareTest.new_component :mocha do
|
10
|
+
require 'mocha'
|
11
|
+
|
12
|
+
BareTest::Assertion::Context.send :include Mocha::API
|
13
|
+
|
14
|
+
teardown do
|
15
|
+
begin
|
16
|
+
mocha_verify
|
17
|
+
rescue Mocha::ExpectationError => e
|
18
|
+
@reason = e.message
|
19
|
+
@status = :failure
|
20
|
+
ensure
|
21
|
+
mocha_teardown
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Original by Tass`
|
2
|
+
# Adapted to :use framework by apeiros
|
3
|
+
|
4
|
+
BareTest.new_component :rr do
|
5
|
+
require 'rr'
|
6
|
+
|
7
|
+
BareTest::Assertion::Context.send :include, RR::Adapters::RRMethods
|
8
|
+
|
9
|
+
teardown do
|
10
|
+
begin
|
11
|
+
::RR.verify
|
12
|
+
rescue ::RR::Errors => e
|
13
|
+
@reason = e.message
|
14
|
+
@status = :failure
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/baretest/version.rb
CHANGED
@@ -12,17 +12,31 @@ module BareTest
|
|
12
12
|
module VERSION
|
13
13
|
|
14
14
|
# The major version number
|
15
|
-
MAJOR
|
15
|
+
MAJOR = 0
|
16
16
|
|
17
17
|
# The minor version number
|
18
|
-
MINOR
|
18
|
+
MINOR = 4
|
19
19
|
|
20
20
|
# The tiny version number
|
21
|
-
TINY
|
21
|
+
TINY = 0
|
22
|
+
|
23
|
+
# Prerelease number - nil for release versions
|
24
|
+
PRERELEASE = 1
|
25
|
+
|
26
|
+
# The version as a string
|
27
|
+
STRING = %{#{MAJOR}.#{MINOR||0}.#{TINY||0}#{".pre#{PRERELEASE}" if PRERELEASE}}
|
28
|
+
|
29
|
+
# The version as an array
|
30
|
+
ARRAY = [MAJOR || 0, MINOR || 0, TINY || 0, PRERELEASE].compact
|
22
31
|
|
23
32
|
# The version as a string
|
24
33
|
def self.to_s
|
25
|
-
|
34
|
+
STRING
|
35
|
+
end
|
36
|
+
|
37
|
+
# The version as an array
|
38
|
+
def self.to_a
|
39
|
+
ARRAY
|
26
40
|
end
|
27
41
|
end
|
28
42
|
end
|
data/lib/command.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2010 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
require 'command/kernel'
|
10
|
+
require 'command/nofileerror'
|
11
|
+
require 'command/nodirectoryerror'
|
12
|
+
require 'command/filenotfounderror'
|
13
|
+
require 'command/directorynotfounderror'
|
14
|
+
require 'command/types'
|
15
|
+
require 'command/argument'
|
16
|
+
require 'command/option'
|
17
|
+
require 'command/env'
|
18
|
+
require 'command/result'
|
19
|
+
require 'command/decoratinghash'
|
20
|
+
require 'command/definition'
|
21
|
+
require 'command/parser'
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
module Command
|
26
|
+
def self.define(*args, &block)
|
27
|
+
@main = Definition.new(*args, &block)
|
28
|
+
@main
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.with(argv, &block)
|
32
|
+
parser = Parser.new($command, argv)
|
33
|
+
parser.instance_eval(&block)
|
34
|
+
parser
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2009-2010 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
module Command
|
10
|
+
class DecoratingHash < Hash
|
11
|
+
attr_accessor :target
|
12
|
+
|
13
|
+
def self.new(target)
|
14
|
+
obj = super() do |h,k| h.target && h.target[k] end
|
15
|
+
obj.target = target
|
16
|
+
obj
|
17
|
+
end
|
18
|
+
|
19
|
+
alias own_size size unless method_defined? :own_size
|
20
|
+
alias own_length own_size
|
21
|
+
|
22
|
+
def size
|
23
|
+
@target ? keys.size : super
|
24
|
+
end
|
25
|
+
alias length size
|
26
|
+
|
27
|
+
def keys
|
28
|
+
@target ? (super | @target.keys) : super
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,294 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2010 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
module Command
|
10
|
+
class Definition
|
11
|
+
RequiredOptionArgument = /[A-Z][A-Z_]*/
|
12
|
+
OptionArgument = /\[#{RequiredOptionArgument}\]|#{RequiredOptionArgument}/
|
13
|
+
ShortOption = /\A-[A-Za-z](?: #{OptionArgument})?\z/
|
14
|
+
NegationSequence = /\[(?:no-|with-|without-)\]/
|
15
|
+
LongOption = /\A--
|
16
|
+
(?:
|
17
|
+
#{NegationSequence}?[A-Za-z][A-Za-z0-9_-]* |
|
18
|
+
[A-Za-z][A-Za-z0-9_-]*#{NegationSequence}[A-Za-z0-9][A-Za-z0-9_-]
|
19
|
+
)
|
20
|
+
(?:\x20#{OptionArgument})?\z
|
21
|
+
/x
|
22
|
+
|
23
|
+
def self.create_argument(*args)
|
24
|
+
name = Symbol === args.first && args.shift
|
25
|
+
usage = args.shift
|
26
|
+
bare = usage[/\w+/]
|
27
|
+
type = Symbol === args.first && args.shift
|
28
|
+
description = args.shift
|
29
|
+
|
30
|
+
Argument.new(name, bare, usage, type, description)
|
31
|
+
end
|
32
|
+
|
33
|
+
# valid arguments:
|
34
|
+
# name # --> copy from parent
|
35
|
+
# name, short[, long][, type][, description]
|
36
|
+
# name, long[, type][, description]
|
37
|
+
#
|
38
|
+
# short can be
|
39
|
+
# * '-?' (short option without argument)
|
40
|
+
# * '-? REQUIRED' (short option with required argument)
|
41
|
+
# * '-? [OPTIONAL]' (short option with optional
|
42
|
+
# where ? is any of A-Za-z
|
43
|
+
# examples:
|
44
|
+
# * '-a'
|
45
|
+
# * '-a [OPTIONAL_ARG]'
|
46
|
+
# * '-a REQUIRED_ARG'
|
47
|
+
#
|
48
|
+
# long can be
|
49
|
+
# * '--?' (short option without argument)
|
50
|
+
# * '--? REQUIRED' (short option with required argument)
|
51
|
+
# * '--? [OPTIONAL]' (short option with optional
|
52
|
+
# where ? is [A-Za-z0-9][A-Za-z0-9-_]*
|
53
|
+
# It may contain a negation sequence, which is one of '[no-]', '[with-]', '[without-]'
|
54
|
+
# examples:
|
55
|
+
# * '--colored'
|
56
|
+
# * '--[no-]colors'
|
57
|
+
# * '--port PORT'
|
58
|
+
# * '--foo [OPTIONAL_ARG]'
|
59
|
+
#
|
60
|
+
# Only one of short and long may have the argument declared.
|
61
|
+
# Usually you'll have the argument in long and only have it in short if
|
62
|
+
# there's no long at all.
|
63
|
+
#
|
64
|
+
# type can be
|
65
|
+
# * :Virtual
|
66
|
+
# * :Boolean
|
67
|
+
# * :String (default)
|
68
|
+
# * :Integer
|
69
|
+
# * :Float
|
70
|
+
# * :Octal
|
71
|
+
# * :Hex
|
72
|
+
# * :File - requires the provided path to exist and be a file
|
73
|
+
# * :Directory - requires the provided path to exist and be a directory
|
74
|
+
# * :Path
|
75
|
+
#
|
76
|
+
# Exceptions (incomplete):
|
77
|
+
# * ArgumentError with single argument if it doesn't identify an inheritable option
|
78
|
+
# * ArgumentError on invalid short definition
|
79
|
+
# * ArgumentError on invalid long definition
|
80
|
+
# * ArgumentError on option argument declaration in both, short and long definition
|
81
|
+
# * ArgumentError on invalid/unsupported type
|
82
|
+
def self.create_option(name, *args)
|
83
|
+
case args.first when nil, /\A-[^- ]/ then
|
84
|
+
short = args.shift
|
85
|
+
end
|
86
|
+
case args.first when nil, /\A--[^- ]/ then
|
87
|
+
long = args.shift
|
88
|
+
end
|
89
|
+
case args.first when nil, Symbol then
|
90
|
+
type = args.shift
|
91
|
+
end
|
92
|
+
declaration = short ? [short,long].compact.join(", ") : " #{long}"
|
93
|
+
description = args.shift
|
94
|
+
|
95
|
+
raise ArgumentError, "Too many arguments" unless args.empty?
|
96
|
+
raise ArgumentError, "Invalid short declaration: #{short.inspect}" unless (short.nil? || short =~ ShortOption)
|
97
|
+
raise ArgumentError, "Invalid long declaration: #{long.inspect}" unless (long.nil? || long =~ LongOption)
|
98
|
+
raise ArgumentError, "Argument declaration must only be in one of short and long" if (short && long && short =~ /\s/ && long =~ /\s/)
|
99
|
+
|
100
|
+
necessity = :none
|
101
|
+
extract_argument = nil
|
102
|
+
extract_argument = short if short =~ /\s/
|
103
|
+
extract_argument = long if long =~ /\s/
|
104
|
+
if extract_argument then
|
105
|
+
flag, *argument = extract_argument.split(/ /)
|
106
|
+
extract_argument.replace(flag) # long/short should only contain the flag, not the argument declaration as well
|
107
|
+
raise ArgumentError, "Multiple arguments for an option not yet supported" if argument.size > 1
|
108
|
+
if argument.empty?
|
109
|
+
necessity = :none
|
110
|
+
elsif argument.first =~ /\A\[.*\]\z/ then
|
111
|
+
necessity = :optional
|
112
|
+
else
|
113
|
+
necessity = :required
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
negated = nil
|
118
|
+
if long =~ NegationSequence then
|
119
|
+
negated = long.delete('[]')
|
120
|
+
long = long.gsub(NegationSequence, '')
|
121
|
+
end
|
122
|
+
|
123
|
+
Option.new(name, short, long, negated, necessity, type, declaration, description)
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
attr_reader :arguments
|
128
|
+
attr_reader :arguments_by_name
|
129
|
+
attr_reader :default_options
|
130
|
+
attr_reader :options_by_name
|
131
|
+
attr_reader :options_by_flag
|
132
|
+
attr_reader :commands_by_name
|
133
|
+
attr_reader :default_command
|
134
|
+
attr_reader :argument_position
|
135
|
+
attr_reader :env_by_variable
|
136
|
+
attr_reader :parent # parent= must update the DecoratingHashes
|
137
|
+
|
138
|
+
def initialize(parent=nil, default_command=nil, default_options={}, &block)
|
139
|
+
@default_command = default_command
|
140
|
+
@default_options = DecoratingHash.new(@parent && @parent.default_options).update(default_options)
|
141
|
+
@elements = []
|
142
|
+
@parent = parent
|
143
|
+
@arguments_by_name = DecoratingHash.new(@parent && @parent.arguments_by_name)
|
144
|
+
@options_by_name = DecoratingHash.new(@parent && @parent.options_by_name)
|
145
|
+
@options_by_flag = DecoratingHash.new(@parent && @parent.options_by_flag)
|
146
|
+
@commands_by_name = DecoratingHash.new(@parent && @parent.commands_by_name)
|
147
|
+
@env_by_variable = DecoratingHash.new(@parent && @parent.env_by_variable)
|
148
|
+
@argument_position = {}
|
149
|
+
@text = []
|
150
|
+
@placeholders = {}
|
151
|
+
@content_for = [@elements]
|
152
|
+
instance_eval(&block) if block
|
153
|
+
end
|
154
|
+
|
155
|
+
def [](command)
|
156
|
+
command ? @commands_by_name[command] : self
|
157
|
+
end
|
158
|
+
|
159
|
+
def content_for(placeholder)
|
160
|
+
@placeholders[placeholder] ||= []
|
161
|
+
@content_for << @placeholders[placeholder]
|
162
|
+
yield(self)
|
163
|
+
@content_for.pop
|
164
|
+
end
|
165
|
+
|
166
|
+
def usage_text(elements=@elements)
|
167
|
+
longest_arg_bare = elements.grep(Argument).max { |a,b|
|
168
|
+
a.bare.size <=> b.bare.size
|
169
|
+
}
|
170
|
+
longest_option = elements.grep(Option).max { |a,b|
|
171
|
+
a.declaration.size <=> b.declaration.size
|
172
|
+
}
|
173
|
+
longest_env_name = elements.grep(Env).max { |a,b|
|
174
|
+
a.variable.size <=> b.variable.size
|
175
|
+
}
|
176
|
+
longest_arg_bare = longest_arg_bare && longest_arg_bare.bare.size
|
177
|
+
longest_option = longest_option && longest_option.declaration.size
|
178
|
+
longest_env_name = longest_env_name && longest_env_name.variable.size
|
179
|
+
arguments = elements.grep(Argument)
|
180
|
+
|
181
|
+
elements.map { |e|
|
182
|
+
case e
|
183
|
+
when :usage
|
184
|
+
"Usage: #{File.basename($0)} #{arguments.map{|a|a.usage}.join(' ')}\n"
|
185
|
+
when Symbol # placeholder
|
186
|
+
usage_text(@placeholders[e])
|
187
|
+
when Option
|
188
|
+
sprintf " %*s%s\n",
|
189
|
+
-(longest_option+2),
|
190
|
+
e.declaration,
|
191
|
+
e.description
|
192
|
+
when Env
|
193
|
+
sprintf "* %*s%s\n",
|
194
|
+
-longest_env_name-2,
|
195
|
+
e.variable,
|
196
|
+
@options_by_name[e.name].description
|
197
|
+
when String
|
198
|
+
e+"\n"
|
199
|
+
when Argument
|
200
|
+
indent = "\n "+(" "*longest_arg_bare)
|
201
|
+
sprintf " %*s%s\n",
|
202
|
+
-(longest_arg_bare+3),
|
203
|
+
"#{e.bare}:",
|
204
|
+
e.description.to_s.gsub(/\n/, indent)
|
205
|
+
when Definition
|
206
|
+
else
|
207
|
+
"unimplemented(#{e.class})"
|
208
|
+
end
|
209
|
+
}.join('')
|
210
|
+
end
|
211
|
+
|
212
|
+
def usage
|
213
|
+
@content_for.last << :usage
|
214
|
+
end
|
215
|
+
|
216
|
+
def argument(*args)
|
217
|
+
unless @argument_position[args.first]
|
218
|
+
@argument_position[args.first] = @argument_position.size
|
219
|
+
end
|
220
|
+
|
221
|
+
if args.size == 1 then
|
222
|
+
argument = @arguments_by_name[args.first]
|
223
|
+
raise ArgumentError, "No argument with name #{args.first.inspect} in any parent found." unless argument
|
224
|
+
else
|
225
|
+
argument = self.class.create_argument(*args)
|
226
|
+
@arguments_by_name[argument.name] = argument
|
227
|
+
end
|
228
|
+
@content_for.last << argument
|
229
|
+
|
230
|
+
argument
|
231
|
+
end
|
232
|
+
|
233
|
+
def virtual_argument(*args)
|
234
|
+
if args.size == 1 then
|
235
|
+
argument = @arguments_by_name[args.first]
|
236
|
+
raise ArgumentError, "No argument with name #{args.first.inspect} in any parent found." unless argument
|
237
|
+
else
|
238
|
+
argument = self.class.create_argument(*args)
|
239
|
+
@arguments_by_name[argument.name] = argument
|
240
|
+
end
|
241
|
+
|
242
|
+
@content_for.last << argument
|
243
|
+
argument
|
244
|
+
end
|
245
|
+
|
246
|
+
def option(*args)
|
247
|
+
if args.size == 1 then
|
248
|
+
inherited_option = @options_by_name[args.first]
|
249
|
+
raise ArgumentError, "No inherited option #{args.first.inspect}" unless inherited_option
|
250
|
+
@content_for.last << inherited_option
|
251
|
+
|
252
|
+
inherited_option
|
253
|
+
else
|
254
|
+
option = self.class.create_option(*args)
|
255
|
+
|
256
|
+
@options_by_name[option.name] = option
|
257
|
+
@options_by_flag[option.short] = option
|
258
|
+
@options_by_flag[option.long] = option
|
259
|
+
@options_by_flag[option.negated] = option
|
260
|
+
@content_for.last << option
|
261
|
+
|
262
|
+
option
|
263
|
+
end
|
264
|
+
end
|
265
|
+
alias o option
|
266
|
+
|
267
|
+
def text(*args)
|
268
|
+
if args.size == 2 then
|
269
|
+
indent, text = *args
|
270
|
+
text = text.gsub(/^/, indent)
|
271
|
+
else
|
272
|
+
text = args.first
|
273
|
+
end
|
274
|
+
@text << text
|
275
|
+
@content_for.last << text
|
276
|
+
end
|
277
|
+
|
278
|
+
def placeholder(identifier)
|
279
|
+
@content_for.last << identifier
|
280
|
+
end
|
281
|
+
|
282
|
+
def env_option(name, variable)
|
283
|
+
env = Env.new(name, variable)
|
284
|
+
@env_by_variable[variable] = env
|
285
|
+
@content_for.last << env
|
286
|
+
end
|
287
|
+
|
288
|
+
def command(*args, &block)
|
289
|
+
definition = Definition.new(self, *args, &block)
|
290
|
+
@commands_by_name[args.first] = definition
|
291
|
+
@content_for.last << definition
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|