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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +98 -0
  3. data/LICENSE.md +16 -24
  4. data/README.md +307 -59
  5. data/docs/guide.md +44 -4
  6. data/lib/toys-core.rb +58 -49
  7. data/lib/toys/acceptor.rb +672 -0
  8. data/lib/toys/alias.rb +106 -0
  9. data/lib/toys/arg_parser.rb +624 -0
  10. data/lib/toys/cli.rb +422 -181
  11. data/lib/toys/compat.rb +83 -0
  12. data/lib/toys/completion.rb +442 -0
  13. data/lib/toys/context.rb +354 -0
  14. data/lib/toys/core_version.rb +18 -26
  15. data/lib/toys/dsl/flag.rb +213 -56
  16. data/lib/toys/dsl/flag_group.rb +237 -51
  17. data/lib/toys/dsl/positional_arg.rb +210 -0
  18. data/lib/toys/dsl/tool.rb +968 -317
  19. data/lib/toys/errors.rb +46 -28
  20. data/lib/toys/flag.rb +821 -0
  21. data/lib/toys/flag_group.rb +282 -0
  22. data/lib/toys/input_file.rb +18 -26
  23. data/lib/toys/loader.rb +110 -100
  24. data/lib/toys/middleware.rb +24 -31
  25. data/lib/toys/mixin.rb +90 -59
  26. data/lib/toys/module_lookup.rb +125 -0
  27. data/lib/toys/positional_arg.rb +184 -0
  28. data/lib/toys/source_info.rb +192 -0
  29. data/lib/toys/standard_middleware/add_verbosity_flags.rb +38 -43
  30. data/lib/toys/standard_middleware/handle_usage_errors.rb +39 -40
  31. data/lib/toys/standard_middleware/set_default_descriptions.rb +111 -89
  32. data/lib/toys/standard_middleware/show_help.rb +130 -113
  33. data/lib/toys/standard_middleware/show_root_version.rb +29 -35
  34. data/lib/toys/standard_mixins/exec.rb +116 -78
  35. data/lib/toys/standard_mixins/fileutils.rb +16 -24
  36. data/lib/toys/standard_mixins/gems.rb +29 -30
  37. data/lib/toys/standard_mixins/highline.rb +34 -41
  38. data/lib/toys/standard_mixins/terminal.rb +72 -26
  39. data/lib/toys/template.rb +51 -35
  40. data/lib/toys/tool.rb +1161 -206
  41. data/lib/toys/utils/completion_engine.rb +171 -0
  42. data/lib/toys/utils/exec.rb +279 -182
  43. data/lib/toys/utils/gems.rb +58 -49
  44. data/lib/toys/utils/help_text.rb +117 -111
  45. data/lib/toys/utils/terminal.rb +69 -62
  46. data/lib/toys/wrappable_string.rb +162 -0
  47. metadata +24 -22
  48. data/lib/toys/definition/acceptor.rb +0 -191
  49. data/lib/toys/definition/alias.rb +0 -112
  50. data/lib/toys/definition/arg.rb +0 -140
  51. data/lib/toys/definition/flag.rb +0 -370
  52. data/lib/toys/definition/flag_group.rb +0 -205
  53. data/lib/toys/definition/source_info.rb +0 -190
  54. data/lib/toys/definition/tool.rb +0 -842
  55. data/lib/toys/dsl/arg.rb +0 -132
  56. data/lib/toys/runner.rb +0 -188
  57. data/lib/toys/standard_middleware.rb +0 -47
  58. data/lib/toys/utils/module_lookup.rb +0 -135
  59. data/lib/toys/utils/wrappable_string.rb +0 -165
@@ -1,32 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright 2018 Daniel Azuma
3
+ # Copyright 2019 Daniel Azuma
4
4
  #
5
- # All rights reserved.
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
- # Redistribution and use in source and binary forms, with or without
8
- # modification, are permitted provided that the following conditions are met:
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
- # * Redistributions of source code must retain the above copyright notice,
11
- # this list of conditions and the following disclaimer.
12
- # * Redistributions in binary form must reproduce the above copyright notice,
13
- # this list of conditions and the following disclaimer in the documentation
14
- # and/or other materials provided with the distribution.
15
- # * Neither the name of the copyright holder, nor the names of any other
16
- # contributors to this software, may be used to endorse or promote products
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} and related methods.
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, tool_definition, flag_group)
47
+ def initialize(tool_dsl, tool, flag_group)
43
48
  @tool_dsl = tool_dsl
44
- @tool_definition = tool_definition
49
+ @tool = tool
45
50
  @flag_group = flag_group
46
51
  end
47
52
 
48
53
  ##
49
- # Add a flag to the current tool. Each flag must specify a key which
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::Tool#get}.
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
- # @param [String,Symbol] key The key to use to retrieve the value from
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...] flags The flags in OptionParser format.
65
- # @param [Object] accept An acceptor that validates and/or converts the
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] default The default value. This is the value that will
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] handler An optional handler for setting/updating the
73
- # value. If given, it should take two arguments, the new given value
74
- # and the previous value, and it should return the new value that
75
- # should be set. The default handler simply replaces the previous
76
- # value. i.e. the default is effectively `-> (val, _prev) { val }`.
77
- # @param [Boolean] report_collisions Raise an exception if a flag is
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::Utils::WrappableString] desc Short
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::Utils::WrappableString>] long_desc
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] display_name A display name for this flag, used in help
210
+ # @param display_name [String] A display name for this flag, used in help
89
211
  # text and error messages.
90
- # @yieldparam flag_dsl [Toys::DSL::Flag] An object that lets you
91
- # configure this flag in a block.
92
- # @return [Toys::DSL::Tool] self, for chaining.
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, report_collisions,
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(@tool_definition, key)
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