toys-core 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +98 -0
- data/LICENSE.md +16 -24
- data/README.md +307 -59
- data/docs/guide.md +44 -4
- data/lib/toys-core.rb +58 -49
- data/lib/toys/acceptor.rb +672 -0
- data/lib/toys/alias.rb +106 -0
- data/lib/toys/arg_parser.rb +624 -0
- data/lib/toys/cli.rb +422 -181
- data/lib/toys/compat.rb +83 -0
- data/lib/toys/completion.rb +442 -0
- data/lib/toys/context.rb +354 -0
- data/lib/toys/core_version.rb +18 -26
- data/lib/toys/dsl/flag.rb +213 -56
- data/lib/toys/dsl/flag_group.rb +237 -51
- data/lib/toys/dsl/positional_arg.rb +210 -0
- data/lib/toys/dsl/tool.rb +968 -317
- data/lib/toys/errors.rb +46 -28
- data/lib/toys/flag.rb +821 -0
- data/lib/toys/flag_group.rb +282 -0
- data/lib/toys/input_file.rb +18 -26
- data/lib/toys/loader.rb +110 -100
- data/lib/toys/middleware.rb +24 -31
- data/lib/toys/mixin.rb +90 -59
- data/lib/toys/module_lookup.rb +125 -0
- data/lib/toys/positional_arg.rb +184 -0
- data/lib/toys/source_info.rb +192 -0
- data/lib/toys/standard_middleware/add_verbosity_flags.rb +38 -43
- data/lib/toys/standard_middleware/handle_usage_errors.rb +39 -40
- data/lib/toys/standard_middleware/set_default_descriptions.rb +111 -89
- data/lib/toys/standard_middleware/show_help.rb +130 -113
- data/lib/toys/standard_middleware/show_root_version.rb +29 -35
- data/lib/toys/standard_mixins/exec.rb +116 -78
- data/lib/toys/standard_mixins/fileutils.rb +16 -24
- data/lib/toys/standard_mixins/gems.rb +29 -30
- data/lib/toys/standard_mixins/highline.rb +34 -41
- data/lib/toys/standard_mixins/terminal.rb +72 -26
- data/lib/toys/template.rb +51 -35
- data/lib/toys/tool.rb +1161 -206
- data/lib/toys/utils/completion_engine.rb +171 -0
- data/lib/toys/utils/exec.rb +279 -182
- data/lib/toys/utils/gems.rb +58 -49
- data/lib/toys/utils/help_text.rb +117 -111
- data/lib/toys/utils/terminal.rb +69 -62
- data/lib/toys/wrappable_string.rb +162 -0
- metadata +24 -22
- data/lib/toys/definition/acceptor.rb +0 -191
- data/lib/toys/definition/alias.rb +0 -112
- data/lib/toys/definition/arg.rb +0 -140
- data/lib/toys/definition/flag.rb +0 -370
- data/lib/toys/definition/flag_group.rb +0 -205
- data/lib/toys/definition/source_info.rb +0 -190
- data/lib/toys/definition/tool.rb +0 -842
- data/lib/toys/dsl/arg.rb +0 -132
- data/lib/toys/runner.rb +0 -188
- data/lib/toys/standard_middleware.rb +0 -47
- data/lib/toys/utils/module_lookup.rb +0 -135
- data/lib/toys/utils/wrappable_string.rb +0 -165
data/lib/toys/dsl/flag_group.rb
CHANGED
@@ -1,32 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright
|
3
|
+
# Copyright 2019 Daniel Azuma
|
4
4
|
#
|
5
|
-
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
6
11
|
#
|
7
|
-
#
|
8
|
-
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
9
14
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
# derived from this software without specific prior written permission.
|
18
|
-
#
|
19
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
-
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
-
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
-
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
-
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
-
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
-
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
-
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
-
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
-
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
-
# POSSIBILITY OF SUCH DAMAGE.
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
20
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
21
|
+
# IN THE SOFTWARE.
|
30
22
|
;
|
31
23
|
|
32
24
|
module Toys
|
@@ -35,74 +27,268 @@ module Toys
|
|
35
27
|
# DSL for a flag group definition block. Lets you create flags in a group.
|
36
28
|
#
|
37
29
|
# These directives are available inside a block passed to
|
38
|
-
# {Toys::DSL::Tool#flag_group}
|
30
|
+
# {Toys::DSL::Tool#flag_group}, {Toys::DSL::Tool#all_required},
|
31
|
+
# {Toys::DSL::Tool#at_most_one}, {Toys::DSL::Tool#at_least_one}, or
|
32
|
+
# {Toys::DSL::Tool#exactly_one}.
|
33
|
+
#
|
34
|
+
# ## Example
|
35
|
+
#
|
36
|
+
# tool "login" do
|
37
|
+
# all_required do
|
38
|
+
# # The directives in here are defined by this class
|
39
|
+
# flag :username, "--username=VAL", desc: "Set username (required)"
|
40
|
+
# flag :password, "--password=VAL", desc: "Set password (required)"
|
41
|
+
# end
|
42
|
+
# # ...
|
43
|
+
# end
|
39
44
|
#
|
40
45
|
class FlagGroup
|
41
46
|
## @private
|
42
|
-
def initialize(tool_dsl,
|
47
|
+
def initialize(tool_dsl, tool, flag_group)
|
43
48
|
@tool_dsl = tool_dsl
|
44
|
-
@
|
49
|
+
@tool = tool
|
45
50
|
@flag_group = flag_group
|
46
51
|
end
|
47
52
|
|
48
53
|
##
|
49
|
-
# Add a flag to the current
|
54
|
+
# Add a flag to the current group. Each flag must specify a key which
|
50
55
|
# the script may use to obtain the flag value from the context.
|
51
56
|
# You may then provide the flags themselves in OptionParser form.
|
52
57
|
#
|
53
58
|
# If the given key is a symbol representing a valid method name, then a
|
54
59
|
# helper method is automatically added to retrieve the value. Otherwise,
|
55
60
|
# if the key is a string or does not represent a valid method name, the
|
56
|
-
# tool can retrieve the value by calling {Toys::
|
61
|
+
# tool can retrieve the value by calling {Toys::Context#get}.
|
57
62
|
#
|
58
63
|
# Attributes of the flag may be passed in as arguments to this method, or
|
59
64
|
# set in a block passed to this method. If you provide a block, you can
|
60
65
|
# use directives in {Toys::DSL::Flag} within the block.
|
61
66
|
#
|
62
|
-
#
|
67
|
+
# ## Flag syntax
|
68
|
+
#
|
69
|
+
# The flags themselves should be provided in OptionParser form. Following
|
70
|
+
# are examples of valid syntax.
|
71
|
+
#
|
72
|
+
# * `-a` : A short boolean switch. When this appears as an argument,
|
73
|
+
# the value is set to `true`.
|
74
|
+
# * `--abc` : A long boolean switch. When this appears as an argument,
|
75
|
+
# the value is set to `true`.
|
76
|
+
# * `-aVAL` or `-a VAL` : A short flag that takes a required value.
|
77
|
+
# These two forms are treated identically. If this argument appears
|
78
|
+
# with a value attached (e.g. `-afoo`), the attached string (e.g.
|
79
|
+
# `"foo"`) is taken as the value. Otherwise, the following argument
|
80
|
+
# is taken as the value (e.g. for `-a foo`, the value is set to
|
81
|
+
# `"foo"`.) The following argument is treated as the value even if it
|
82
|
+
# looks like a flag (e.g. `-a -a` causes the string `"-a"` to be
|
83
|
+
# taken as the value.)
|
84
|
+
# * `-a[VAL]` : A short flag that takes an optional value. If this
|
85
|
+
# argument appears with a value attached (e.g. `-afoo`), the attached
|
86
|
+
# string (e.g. `"foo"`) is taken as the value. Otherwise, the value
|
87
|
+
# is set to `true`. The following argument is never interpreted as
|
88
|
+
# the value. (Compare with `-a [VAL]`.)
|
89
|
+
# * `-a [VAL]` : A short flag that takes an optional value. If this
|
90
|
+
# argument appears with a value attached (e.g. `-afoo`), the attached
|
91
|
+
# string (e.g. `"foo"`) is taken as the value. Otherwise, if the
|
92
|
+
# following argument does not look like a flag (i.e. it does not
|
93
|
+
# begin with a hyphen), it is taken as the value. (e.g. `-a foo`
|
94
|
+
# causes the string `"foo"` to be taken as the value.). If there is
|
95
|
+
# no following argument, or the following argument looks like a flag,
|
96
|
+
# the value is set to `true`. (Compare with `-a[VAL]`.)
|
97
|
+
# * `--abc=VAL` or `--abc VAL` : A long flag that takes a required
|
98
|
+
# value. These two forms are treated identically. If this argument
|
99
|
+
# appears with a value attached (e.g. `--abc=foo`), the attached
|
100
|
+
# string (e.g. `"foo"`) is taken as the value. Otherwise, the
|
101
|
+
# following argument is taken as the value (e.g. for `--abc foo`, the
|
102
|
+
# value is set to `"foo"`.) The following argument is treated as the
|
103
|
+
# value even if it looks like a flag (e.g. `--abc --abc` causes the
|
104
|
+
# string `"--abc"` to be taken as the value.)
|
105
|
+
# * `--abc[=VAL]` : A long flag that takes an optional value. If this
|
106
|
+
# argument appears with a value attached (e.g. `--abc=foo`), the
|
107
|
+
# attached string (e.g. `"foo"`) is taken as the value. Otherwise,
|
108
|
+
# the value is set to `true`. The following argument is never
|
109
|
+
# interpreted as the value. (Compare with `--abc [VAL]`.)
|
110
|
+
# * `--abc [VAL]` : A long flag that takes an optional value. If this
|
111
|
+
# argument appears with a value attached (e.g. `--abc=foo`), the
|
112
|
+
# attached string (e.g. `"foo"`) is taken as the value. Otherwise, if
|
113
|
+
# the following argument does not look like a flag (i.e. it does not
|
114
|
+
# begin with a hyphen), it is taken as the value. (e.g. `--abc foo`
|
115
|
+
# causes the string `"foo"` to be taken as the value.). If there is
|
116
|
+
# no following argument, or the following argument looks like a flag,
|
117
|
+
# the value is set to `true`. (Compare with `--abc=[VAL]`.)
|
118
|
+
# * `--[no-]abc` : A long boolean switch that can be turned either on
|
119
|
+
# or off. This effectively creates two flags, `--abc` which sets the
|
120
|
+
# value to `true`, and `--no-abc` which sets the falue to `false`.
|
121
|
+
#
|
122
|
+
# ## Default flag syntax
|
123
|
+
#
|
124
|
+
# If no flag syntax strings are provided, a default syntax will be
|
125
|
+
# inferred based on the key and other options.
|
126
|
+
#
|
127
|
+
# Specifically, if the key has one character, then that character will be
|
128
|
+
# chosen as a short flag. If the key has multiple characters, a long flag
|
129
|
+
# will be generated.
|
130
|
+
#
|
131
|
+
# Furthermore, if a custom completion, a non-boolean acceptor, or a
|
132
|
+
# non-boolean default value is provided in the options, then the flag
|
133
|
+
# will be considered to take a value. Otherwise, it will be considered to
|
134
|
+
# be a boolean switch.
|
135
|
+
#
|
136
|
+
# For example, the following pairs of flags are identical:
|
137
|
+
#
|
138
|
+
# flag :a
|
139
|
+
# flag :a, "-a"
|
140
|
+
#
|
141
|
+
# flag :abc_def
|
142
|
+
# flag :abc_def, "--abc-def"
|
143
|
+
#
|
144
|
+
# flag :number, accept: Integer
|
145
|
+
# flag :number, "--number=VAL", accept: Integer
|
146
|
+
#
|
147
|
+
# ## More examples
|
148
|
+
#
|
149
|
+
# A flag that sets its value to the number of times it appears on the
|
150
|
+
# command line:
|
151
|
+
#
|
152
|
+
# flag :verbose, "-v", "--verbose",
|
153
|
+
# default: 0, handler: ->(_val, count) { count + 1 }
|
154
|
+
#
|
155
|
+
# An example using block form:
|
156
|
+
#
|
157
|
+
# flag :shout do
|
158
|
+
# flags "-s", "--shout"
|
159
|
+
# default false
|
160
|
+
# desc "Say it louder"
|
161
|
+
# long_desc "This flag says it lowder.",
|
162
|
+
# "You might use this when people can't hear you.",
|
163
|
+
# "",
|
164
|
+
# "Example:",
|
165
|
+
# [" toys say --shout hello"]
|
166
|
+
# end
|
167
|
+
#
|
168
|
+
# @param key [String,Symbol] The key to use to retrieve the value from
|
63
169
|
# the execution context.
|
64
|
-
# @param [String...]
|
65
|
-
# @param [Object]
|
170
|
+
# @param flags [String...] The flags in OptionParser format.
|
171
|
+
# @param accept [Object] An acceptor that validates and/or converts the
|
66
172
|
# value. You may provide either the name of an acceptor you have
|
67
173
|
# defined, or one of the default acceptors provided by OptionParser.
|
68
174
|
# Optional. If not specified, accepts any value as a string.
|
69
|
-
# @param [Object]
|
175
|
+
# @param default [Object] The default value. This is the value that will
|
70
176
|
# be set in the context if this flag is not provided on the command
|
71
177
|
# line. Defaults to `nil`.
|
72
|
-
# @param [Proc,nil]
|
73
|
-
# value.
|
74
|
-
#
|
75
|
-
# should be set.
|
76
|
-
#
|
77
|
-
#
|
178
|
+
# @param handler [Proc,nil,:set,:push] An optional handler for
|
179
|
+
# setting/updating the value. A handler is a proc taking two
|
180
|
+
# arguments, the given value and the previous value, returning the
|
181
|
+
# new value that should be set. You may also specify a predefined
|
182
|
+
# named handler. The `:set` handler (the default) replaces the
|
183
|
+
# previous value (effectively `-> (val, _prev) { val }`). The
|
184
|
+
# `:push` handler expects the previous value to be an array and
|
185
|
+
# pushes the given value onto it; it should be combined with setting
|
186
|
+
# `default: []` and is intended for "multi-valued" flags.
|
187
|
+
# @param complete_flags [Object] A specifier for shell tab completion
|
188
|
+
# for flag names associated with this flag. By default, a
|
189
|
+
# {Toys::Flag::DefaultCompletion} is used, which provides the flag's
|
190
|
+
# names as completion candidates. To customize completion, set this
|
191
|
+
# to the name of a previously defined completion, a hash of options
|
192
|
+
# to pass to the constructor for {Toys::Flag::DefaultCompletion}, or
|
193
|
+
# any other spec recognized by {Toys::Completion.create}.
|
194
|
+
# @param complete_values [Object] A specifier for shell tab completion
|
195
|
+
# for flag values associated with this flag. This is the empty
|
196
|
+
# completion by default. To customize completion, set this to the
|
197
|
+
# name of a previously defined completion, or any spec recognized by
|
198
|
+
# {Toys::Completion.create}.
|
199
|
+
# @param report_collisions [Boolean] Raise an exception if a flag is
|
78
200
|
# requested that is already in use or marked as unusable. Default is
|
79
201
|
# true.
|
80
|
-
# @param [String,Array<String>,Toys::
|
202
|
+
# @param desc [String,Array<String>,Toys::WrappableString] Short
|
81
203
|
# description for the flag. See {Toys::DSL::Tool#desc} for a
|
82
204
|
# description of the allowed formats. Defaults to the empty string.
|
83
|
-
# @param [Array<String,Array<String>,Toys::
|
205
|
+
# @param long_desc [Array<String,Array<String>,Toys::WrappableString>]
|
84
206
|
# Long description for the flag. See {Toys::DSL::Tool#long_desc} for
|
85
207
|
# a description of the allowed formats. (But note that this param
|
86
208
|
# takes an Array of description lines, rather than a series of
|
87
209
|
# arguments.) Defaults to the empty array.
|
88
|
-
# @param [String]
|
210
|
+
# @param display_name [String] A display name for this flag, used in help
|
89
211
|
# text and error messages.
|
90
|
-
# @
|
91
|
-
#
|
92
|
-
# @return [
|
212
|
+
# @param block [Proc] Configures the flag. See {Toys::DSL::Flag} for the
|
213
|
+
# directives that can be called in this block.
|
214
|
+
# @return [self]
|
93
215
|
#
|
94
216
|
def flag(key, *flags,
|
95
|
-
accept: nil, default: nil, handler: nil,
|
96
|
-
report_collisions: true,
|
97
|
-
desc: nil, long_desc: nil, display_name: nil,
|
217
|
+
accept: nil, default: nil, handler: nil, complete_flags: nil, complete_values: nil,
|
218
|
+
report_collisions: true, desc: nil, long_desc: nil, display_name: nil,
|
98
219
|
&block)
|
99
|
-
flag_dsl = DSL::Flag.new(flags, accept, default, handler,
|
100
|
-
@flag_group, desc, long_desc, display_name)
|
220
|
+
flag_dsl = DSL::Flag.new(flags, accept, default, handler, complete_flags, complete_values,
|
221
|
+
report_collisions, @flag_group, desc, long_desc, display_name)
|
101
222
|
flag_dsl.instance_exec(flag_dsl, &block) if block
|
102
|
-
flag_dsl._add_to(@
|
223
|
+
flag_dsl._add_to(@tool, key)
|
103
224
|
DSL::Tool.maybe_add_getter(@tool_dsl, key)
|
104
225
|
self
|
105
226
|
end
|
227
|
+
|
228
|
+
##
|
229
|
+
# Set the short description for the current flag group. The short
|
230
|
+
# description is displayed as the group title in online help.
|
231
|
+
#
|
232
|
+
# The description is a {Toys::WrappableString}, which may be word-wrapped
|
233
|
+
# when displayed in a help screen. You may pass a {Toys::WrappableString}
|
234
|
+
# directly to this method, or you may pass any input that can be used to
|
235
|
+
# construct a wrappable string:
|
236
|
+
#
|
237
|
+
# * If you pass a String, its whitespace will be compacted (i.e. tabs,
|
238
|
+
# newlines, and multiple consecutive whitespace will be turned into a
|
239
|
+
# single space), and it will be word-wrapped on whitespace.
|
240
|
+
# * If you pass an Array of Strings, each string will be considered a
|
241
|
+
# literal word that cannot be broken, and wrapping will be done
|
242
|
+
# across the strings in the array. In this case, whitespace is not
|
243
|
+
# compacted.
|
244
|
+
#
|
245
|
+
# ## Examples
|
246
|
+
#
|
247
|
+
# If you pass in a sentence as a simple string, it may be word wrapped
|
248
|
+
# when displayed:
|
249
|
+
#
|
250
|
+
# desc "This sentence may be wrapped."
|
251
|
+
#
|
252
|
+
# To specify a sentence that should never be word-wrapped, pass it as the
|
253
|
+
# sole element of a string array:
|
254
|
+
#
|
255
|
+
# desc ["This sentence will not be wrapped."]
|
256
|
+
#
|
257
|
+
# @param desc [String,Array<String>,Toys::WrappableString]
|
258
|
+
# @return [self]
|
259
|
+
#
|
260
|
+
def desc(desc)
|
261
|
+
@flag_group.desc = desc
|
262
|
+
self
|
263
|
+
end
|
264
|
+
|
265
|
+
##
|
266
|
+
# Add to the long description for the current flag group. The long
|
267
|
+
# description is displayed with the flag group in online help. This
|
268
|
+
# directive may be given multiple times, and the results are cumulative.
|
269
|
+
#
|
270
|
+
# A long description is a series of descriptions, which are generally
|
271
|
+
# displayed in a series of lines/paragraphs. Each individual description
|
272
|
+
# uses the form described in the {#desc} documentation, and may be
|
273
|
+
# word-wrapped when displayed. To insert a blank line, include an empty
|
274
|
+
# string as one of the descriptions.
|
275
|
+
#
|
276
|
+
# ## Example
|
277
|
+
#
|
278
|
+
# long_desc "This initial paragraph might get word wrapped.",
|
279
|
+
# "This next paragraph is followed by a blank line.",
|
280
|
+
# "",
|
281
|
+
# ["This line will not be wrapped."],
|
282
|
+
# [" This indent is preserved."]
|
283
|
+
# long_desc "This line is appended to the description."
|
284
|
+
#
|
285
|
+
# @param long_desc [String,Array<String>,Toys::WrappableString...]
|
286
|
+
# @return [self]
|
287
|
+
#
|
288
|
+
def long_desc(*long_desc)
|
289
|
+
@flag_group.append_long_desc(long_desc)
|
290
|
+
self
|
291
|
+
end
|
106
292
|
end
|
107
293
|
end
|
108
294
|
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 Daniel Azuma
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
20
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
21
|
+
# IN THE SOFTWARE.
|
22
|
+
;
|
23
|
+
|
24
|
+
module Toys
|
25
|
+
module DSL
|
26
|
+
##
|
27
|
+
# DSL for an arg definition block. Lets you set arg attributes in a block
|
28
|
+
# instead of a long series of keyword arguments.
|
29
|
+
#
|
30
|
+
# These directives are available inside a block passed to
|
31
|
+
# {Toys::DSL::Tool#required_arg}, {Toys::DSL::Tool#optional_arg}, or
|
32
|
+
# {Toys::DSL::Tool#remaining_args}.
|
33
|
+
#
|
34
|
+
# ## Example
|
35
|
+
#
|
36
|
+
# tool "mytool" do
|
37
|
+
# optional_arg :value do
|
38
|
+
# # The directives in here are defined by this class
|
39
|
+
# accept Integer
|
40
|
+
# desc "An integer value"
|
41
|
+
# end
|
42
|
+
# # ...
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
class PositionalArg
|
46
|
+
## @private
|
47
|
+
def initialize(acceptor, default, completion, display_name, desc, long_desc)
|
48
|
+
@default = default
|
49
|
+
@display_name = display_name
|
50
|
+
@desc = desc
|
51
|
+
@long_desc = long_desc || []
|
52
|
+
accept(acceptor)
|
53
|
+
complete(completion)
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Set the acceptor for this argument's values.
|
58
|
+
# You can pass either the string name of an acceptor defined in this tool
|
59
|
+
# or any of its ancestors, or any other specification recognized by
|
60
|
+
# {Toys::Acceptor.create}.
|
61
|
+
#
|
62
|
+
# @param spec [Object]
|
63
|
+
# @param options [Hash]
|
64
|
+
# @param block [Proc]
|
65
|
+
# @return [self]
|
66
|
+
#
|
67
|
+
def accept(spec = nil, **options, &block)
|
68
|
+
@acceptor_spec = spec
|
69
|
+
@acceptor_options = options
|
70
|
+
@acceptor_block = block
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Set the default value.
|
76
|
+
#
|
77
|
+
# @param default [Object]
|
78
|
+
# @return [self]
|
79
|
+
#
|
80
|
+
def default(default)
|
81
|
+
@default = default
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# Set the shell completion strategy for arg values.
|
87
|
+
# You can pass either the string name of a completion defined in this
|
88
|
+
# tool or any of its ancestors, or any other specification recognized by
|
89
|
+
# {Toys::Completion.create}.
|
90
|
+
#
|
91
|
+
# @param spec [Object]
|
92
|
+
# @param options [Hash]
|
93
|
+
# @param block [Proc]
|
94
|
+
# @return [self]
|
95
|
+
#
|
96
|
+
def complete(spec = nil, **options, &block)
|
97
|
+
@completion_spec = spec
|
98
|
+
@completion_options = options
|
99
|
+
@completion_block = block
|
100
|
+
self
|
101
|
+
end
|
102
|
+
|
103
|
+
##
|
104
|
+
# Set the name of this arg as it appears in help screens.
|
105
|
+
#
|
106
|
+
# @param display_name [String]
|
107
|
+
# @return [self]
|
108
|
+
#
|
109
|
+
def display_name(display_name)
|
110
|
+
@display_name = display_name
|
111
|
+
self
|
112
|
+
end
|
113
|
+
|
114
|
+
##
|
115
|
+
# Set the short description for the current positional argument. The
|
116
|
+
# short description is displayed with the argument in online help.
|
117
|
+
#
|
118
|
+
# The description is a {Toys::WrappableString}, which may be word-wrapped
|
119
|
+
# when displayed in a help screen. You may pass a {Toys::WrappableString}
|
120
|
+
# directly to this method, or you may pass any input that can be used to
|
121
|
+
# construct a wrappable string:
|
122
|
+
#
|
123
|
+
# * If you pass a String, its whitespace will be compacted (i.e. tabs,
|
124
|
+
# newlines, and multiple consecutive whitespace will be turned into a
|
125
|
+
# single space), and it will be word-wrapped on whitespace.
|
126
|
+
# * If you pass an Array of Strings, each string will be considered a
|
127
|
+
# literal word that cannot be broken, and wrapping will be done
|
128
|
+
# across the strings in the array. In this case, whitespace is not
|
129
|
+
# compacted.
|
130
|
+
#
|
131
|
+
# ## Examples
|
132
|
+
#
|
133
|
+
# If you pass in a sentence as a simple string, it may be word wrapped
|
134
|
+
# when displayed:
|
135
|
+
#
|
136
|
+
# desc "This sentence may be wrapped."
|
137
|
+
#
|
138
|
+
# To specify a sentence that should never be word-wrapped, pass it as the
|
139
|
+
# sole element of a string array:
|
140
|
+
#
|
141
|
+
# desc ["This sentence will not be wrapped."]
|
142
|
+
#
|
143
|
+
# @param desc [String,Array<String>,Toys::WrappableString]
|
144
|
+
# @return [self]
|
145
|
+
#
|
146
|
+
def desc(desc)
|
147
|
+
@desc = desc
|
148
|
+
self
|
149
|
+
end
|
150
|
+
|
151
|
+
##
|
152
|
+
# Add to the long description for the current positional argument. The
|
153
|
+
# long description is displayed with the argument in online help. This
|
154
|
+
# directive may be given multiple times, and the results are cumulative.
|
155
|
+
#
|
156
|
+
# A long description is a series of descriptions, which are generally
|
157
|
+
# displayed in a series of lines/paragraphs. Each individual description
|
158
|
+
# uses the form described in the {#desc} documentation, and may be
|
159
|
+
# word-wrapped when displayed. To insert a blank line, include an empty
|
160
|
+
# string as one of the descriptions.
|
161
|
+
#
|
162
|
+
# ## Example
|
163
|
+
#
|
164
|
+
# long_desc "This initial paragraph might get word wrapped.",
|
165
|
+
# "This next paragraph is followed by a blank line.",
|
166
|
+
# "",
|
167
|
+
# ["This line will not be wrapped."],
|
168
|
+
# [" This indent is preserved."]
|
169
|
+
# long_desc "This line is appended to the description."
|
170
|
+
#
|
171
|
+
# @param long_desc [String,Array<String>,Toys::WrappableString...]
|
172
|
+
# @return [self]
|
173
|
+
#
|
174
|
+
def long_desc(*long_desc)
|
175
|
+
@long_desc += long_desc
|
176
|
+
self
|
177
|
+
end
|
178
|
+
|
179
|
+
## @private
|
180
|
+
def _add_required_to(tool, key)
|
181
|
+
acceptor = tool.scalar_acceptor(@acceptor_spec, @acceptor_options, &@acceptor_block)
|
182
|
+
completion = tool.scalar_completion(@completion_spec, @completion_options,
|
183
|
+
&@completion_block)
|
184
|
+
tool.add_required_arg(key,
|
185
|
+
accept: acceptor, complete: completion,
|
186
|
+
display_name: @display_name, desc: @desc, long_desc: @long_desc)
|
187
|
+
end
|
188
|
+
|
189
|
+
## @private
|
190
|
+
def _add_optional_to(tool, key)
|
191
|
+
acceptor = tool.scalar_acceptor(@acceptor_spec, @acceptor_options, &@acceptor_block)
|
192
|
+
completion = tool.scalar_completion(@completion_spec, @completion_options,
|
193
|
+
&@completion_block)
|
194
|
+
tool.add_optional_arg(key,
|
195
|
+
accept: acceptor, default: @default, complete: completion,
|
196
|
+
display_name: @display_name, desc: @desc, long_desc: @long_desc)
|
197
|
+
end
|
198
|
+
|
199
|
+
## @private
|
200
|
+
def _set_remaining_on(tool, key)
|
201
|
+
acceptor = tool.scalar_acceptor(@acceptor_spec, @acceptor_options, &@acceptor_block)
|
202
|
+
completion = tool.scalar_completion(@completion_spec, @completion_options,
|
203
|
+
&@completion_block)
|
204
|
+
tool.set_remaining_args(key,
|
205
|
+
accept: acceptor, default: @default, complete: completion,
|
206
|
+
display_name: @display_name, desc: @desc, long_desc: @long_desc)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|