toys-core 0.3.6 → 0.3.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/lib/toys-core.rb +20 -5
  4. data/lib/toys/cli.rb +39 -32
  5. data/lib/toys/core_version.rb +1 -1
  6. data/lib/toys/{tool → definition}/acceptor.rb +21 -15
  7. data/lib/toys/{utils/line_output.rb → definition/alias.rb} +47 -59
  8. data/lib/toys/{tool/arg_definition.rb → definition/arg.rb} +17 -7
  9. data/lib/toys/{tool/flag_definition.rb → definition/flag.rb} +19 -9
  10. data/lib/toys/definition/tool.rb +574 -0
  11. data/lib/toys/dsl/arg.rb +118 -0
  12. data/lib/toys/dsl/flag.rb +132 -0
  13. data/lib/toys/dsl/tool.rb +521 -0
  14. data/lib/toys/errors.rb +2 -2
  15. data/lib/toys/helpers.rb +3 -3
  16. data/lib/toys/helpers/exec.rb +31 -25
  17. data/lib/toys/helpers/fileutils.rb +8 -2
  18. data/lib/toys/helpers/highline.rb +8 -1
  19. data/lib/toys/{alias.rb → helpers/terminal.rb} +44 -53
  20. data/lib/toys/input_file.rb +61 -0
  21. data/lib/toys/loader.rb +87 -77
  22. data/lib/toys/middleware.rb +3 -3
  23. data/lib/toys/middleware/add_verbosity_flags.rb +22 -20
  24. data/lib/toys/middleware/base.rb +53 -5
  25. data/lib/toys/middleware/handle_usage_errors.rb +9 -12
  26. data/lib/toys/middleware/set_default_descriptions.rb +6 -7
  27. data/lib/toys/middleware/show_help.rb +71 -67
  28. data/lib/toys/middleware/show_root_version.rb +9 -9
  29. data/lib/toys/runner.rb +157 -0
  30. data/lib/toys/template.rb +4 -3
  31. data/lib/toys/templates.rb +2 -2
  32. data/lib/toys/templates/clean.rb +2 -2
  33. data/lib/toys/templates/gem_build.rb +5 -5
  34. data/lib/toys/templates/minitest.rb +2 -2
  35. data/lib/toys/templates/rubocop.rb +2 -2
  36. data/lib/toys/templates/yardoc.rb +2 -2
  37. data/lib/toys/tool.rb +168 -625
  38. data/lib/toys/utils/exec.rb +19 -18
  39. data/lib/toys/utils/gems.rb +140 -0
  40. data/lib/toys/utils/help_text.rb +25 -20
  41. data/lib/toys/utils/terminal.rb +412 -0
  42. data/lib/toys/utils/wrappable_string.rb +3 -1
  43. metadata +15 -24
  44. data/lib/toys/config_dsl.rb +0 -699
  45. data/lib/toys/context.rb +0 -290
  46. data/lib/toys/helpers/spinner.rb +0 -142
@@ -27,6 +27,8 @@
27
27
  # POSSIBILITY OF SUCH DAMAGE.
28
28
  ;
29
29
 
30
+ require "toys/utils/terminal"
31
+
30
32
  module Toys
31
33
  module Utils
32
34
  ##
@@ -99,7 +101,7 @@ module Toys
99
101
  line = ""
100
102
  line_len = 0
101
103
  fragments.each do |frag|
102
- frag_len = ::HighLine.uncolor(frag).size
104
+ frag_len = Utils::Terminal.remove_style_escapes(frag).size
103
105
  if line_len.zero?
104
106
  line = frag
105
107
  line_len = frag_len
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toys-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Azuma
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-21 00:00:00.000000000 Z
11
+ date: 2018-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: highline
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.7'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.7'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: minitest
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -108,17 +94,23 @@ files:
108
94
  - README.md
109
95
  - docs/getting-started.md
110
96
  - lib/toys-core.rb
111
- - lib/toys/alias.rb
112
97
  - lib/toys/cli.rb
113
- - lib/toys/config_dsl.rb
114
- - lib/toys/context.rb
115
98
  - lib/toys/core_version.rb
99
+ - lib/toys/definition/acceptor.rb
100
+ - lib/toys/definition/alias.rb
101
+ - lib/toys/definition/arg.rb
102
+ - lib/toys/definition/flag.rb
103
+ - lib/toys/definition/tool.rb
104
+ - lib/toys/dsl/arg.rb
105
+ - lib/toys/dsl/flag.rb
106
+ - lib/toys/dsl/tool.rb
116
107
  - lib/toys/errors.rb
117
108
  - lib/toys/helpers.rb
118
109
  - lib/toys/helpers/exec.rb
119
110
  - lib/toys/helpers/fileutils.rb
120
111
  - lib/toys/helpers/highline.rb
121
- - lib/toys/helpers/spinner.rb
112
+ - lib/toys/helpers/terminal.rb
113
+ - lib/toys/input_file.rb
122
114
  - lib/toys/loader.rb
123
115
  - lib/toys/middleware.rb
124
116
  - lib/toys/middleware/add_verbosity_flags.rb
@@ -127,6 +119,7 @@ files:
127
119
  - lib/toys/middleware/set_default_descriptions.rb
128
120
  - lib/toys/middleware/show_help.rb
129
121
  - lib/toys/middleware/show_root_version.rb
122
+ - lib/toys/runner.rb
130
123
  - lib/toys/template.rb
131
124
  - lib/toys/templates.rb
132
125
  - lib/toys/templates/clean.rb
@@ -135,13 +128,11 @@ files:
135
128
  - lib/toys/templates/rubocop.rb
136
129
  - lib/toys/templates/yardoc.rb
137
130
  - lib/toys/tool.rb
138
- - lib/toys/tool/acceptor.rb
139
- - lib/toys/tool/arg_definition.rb
140
- - lib/toys/tool/flag_definition.rb
141
131
  - lib/toys/utils/exec.rb
132
+ - lib/toys/utils/gems.rb
142
133
  - lib/toys/utils/help_text.rb
143
- - lib/toys/utils/line_output.rb
144
134
  - lib/toys/utils/module_lookup.rb
135
+ - lib/toys/utils/terminal.rb
145
136
  - lib/toys/utils/wrappable_string.rb
146
137
  homepage: https://github.com/dazuma/toys
147
138
  licenses:
@@ -1,699 +0,0 @@
1
- # Copyright 2018 Daniel Azuma
2
- #
3
- # All rights reserved.
4
- #
5
- # Redistribution and use in source and binary forms, with or without
6
- # modification, are permitted provided that the following conditions are met:
7
- #
8
- # * Redistributions of source code must retain the above copyright notice,
9
- # this list of conditions and the following disclaimer.
10
- # * Redistributions in binary form must reproduce the above copyright notice,
11
- # this list of conditions and the following disclaimer in the documentation
12
- # and/or other materials provided with the distribution.
13
- # * Neither the name of the copyright holder, nor the names of any other
14
- # contributors to this software, may be used to endorse or promote products
15
- # derived from this software without specific prior written permission.
16
- #
17
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
- # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
- # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
- # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
- # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
- # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
- # POSSIBILITY OF SUCH DAMAGE.
28
- ;
29
-
30
- require "toys/context"
31
-
32
- module Toys
33
- ##
34
- # This class defines the DSL for a toys configuration file.
35
- #
36
- # A toys configuration defines one or more named tools. It provides syntax
37
- # for setting the description, defining flags and arguments, specifying
38
- # how to execute the tool, and requesting helper modules and other services.
39
- # It also lets you define subtools, nested arbitrarily deep, using blocks.
40
- #
41
- # Generally ConfigDSL is invoked from the {Loader}. Applications should not
42
- # need to create instances of ConfigDSL directly.
43
- #
44
- # ## Simple example
45
- #
46
- # Create a file called `.toys.rb` in the current directory, with the
47
- # following contents:
48
- #
49
- # tool "greet" do
50
- # desc "Prints a simple greeting"
51
- #
52
- # optional_arg :recipient, default: "world"
53
- #
54
- # script do
55
- # puts "Hello, #{self[:recipient]}!"
56
- # end
57
- # end
58
- #
59
- # Now you can execute it using:
60
- #
61
- # toys greet
62
- #
63
- # or try:
64
- #
65
- # toys greet rubyists
66
- #
67
- class ConfigDSL
68
- # Copy the well-known context key constants here, so that script blocks
69
- # inside config DSL files can access them without qualification.
70
- ::Toys::Context.constants.each do |const|
71
- const_set(const, ::Toys::Context.const_get(const))
72
- end
73
-
74
- ##
75
- # Create an instance of the DSL.
76
- # @private
77
- #
78
- # @param [Array<String>] words Full name of the current tool.
79
- # @param [Array<String>,nil] remaining_words Arguments remaining in the
80
- # current lookup.
81
- # @param [Integer] priority Priority of this configuration
82
- # @param [Toys::Loader] loader Current active loader
83
- # @param [String] path The path to the config file being evaluated
84
- #
85
- # @return [Toys::ConfigDSL]
86
- #
87
- def initialize(words, remaining_words, priority, loader, path)
88
- @words = words
89
- @remaining_words = remaining_words
90
- @priority = priority
91
- @loader = loader
92
- @path = path
93
- end
94
-
95
- ##
96
- # Create an acceptor that can be passed into a flag or arg. An acceptor
97
- # validates and/or converts a string parameter to a Ruby object. This
98
- # acceptor may, for the current tool, be referenced by the name you provide
99
- # when you create a flag or arg.
100
- #
101
- # An acceptor contains a validator, which parses and validates the string
102
- # syntax of an argument, and a converter, which takes the validation
103
- # results and returns a final value for the context data.
104
- #
105
- # The validator may be either a regular expression or a list of valid
106
- # inputs.
107
- #
108
- # If the validator is a regular expression, it is matched against the
109
- # argument string and succeeds only if the expression covers the *entire*
110
- # string. The elements of the MatchData (i.e. the string matched, plus any
111
- # captures) are then passed into the conversion function.
112
- #
113
- # If the validator is an array, the *string form* of the array elements
114
- # (i.e. the results of calling to_s on each element) are considered the
115
- # valid values for the argument. This is useful for enums, for example.
116
- # In this case, the input is converted to the original array element, and
117
- # any converter function you provide is ignored.
118
- #
119
- # If you provide no validator, then no validation takes place and all
120
- # argument strings are considered valid. The string itself is passed on to
121
- # the converter.
122
- #
123
- # The converter should be a proc that takes as its arguments the results
124
- # of validation. For example, if you use a regular expression validator,
125
- # the converter should take a series of strings arguments, the first of
126
- # which is the full input string, and the rest of which are captures.
127
- # If you provide no converter, no conversion is done and the input string
128
- # is considered the final value. You may also provide the converter as a
129
- # block.
130
- #
131
- # @param [String] name The acceptor name.
132
- # @param [Regexp,Array,nil] validator The validator.
133
- # @param [Proc,nil] converter The validator.
134
- #
135
- def acceptor(name, validator = nil, converter = nil, &block)
136
- accept =
137
- case validator
138
- when ::Regexp
139
- Tool::PatternAcceptor.new(name, validator, converter, &block)
140
- when ::Array
141
- Tool::EnumAcceptor.new(name, validator)
142
- when nil
143
- Tool::Acceptor.new(name, converter, &block)
144
- else
145
- raise ToolDefinitionError, "Illegal validator: #{validator.inspect}"
146
- end
147
- _cur_tool.add_acceptor(accept)
148
- self
149
- end
150
-
151
- ##
152
- # Create a subtool. You must provide a block defining the subtool.
153
- #
154
- # If the subtool is already defined (either as a tool or a namespace), the
155
- # old definition is discarded and replaced with the new definition.
156
- #
157
- # @param [String] word The name of the subtool
158
- #
159
- def tool(word, &block)
160
- word = word.to_s
161
- subtool_words = @words + [word]
162
- next_remaining = Loader.next_remaining_words(@remaining_words, word)
163
- ConfigDSL.evaluate(subtool_words, next_remaining, @priority, @loader, @path, block)
164
- self
165
- end
166
- alias name tool
167
-
168
- ##
169
- # Create an alias in the current namespace.
170
- #
171
- # @param [String] word The name of the alias
172
- # @param [String] target The target of the alias
173
- #
174
- def alias_tool(word, target)
175
- @loader.make_alias(@words + [word.to_s], @words + [target.to_s], @priority)
176
- self
177
- end
178
-
179
- ##
180
- # Create an alias of the current tool.
181
- #
182
- # @param [String] word The name of the alias
183
- #
184
- def alias_as(word)
185
- if @words.empty?
186
- raise ToolDefinitionError, "Cannot make an alias of the root."
187
- end
188
- @loader.make_alias(@words[0..-2] + [word.to_s], @words, @priority)
189
- self
190
- end
191
-
192
- ##
193
- # Include another config file or directory at the current location.
194
- #
195
- # @param [String] path The file or directory to include.
196
- #
197
- def include(path)
198
- @loader.include_path(path, @words, @remaining_words, @priority)
199
- self
200
- end
201
-
202
- ##
203
- # Expand the given template in the current location.
204
- #
205
- # The template may be specified as a class or a well-known template name.
206
- # You may also provide arguments to pass to the template.
207
- #
208
- # @param [Class,String,Symbol] template_class The template, either as a
209
- # class or a well-known name.
210
- # @param [Object...] args Template arguments
211
- #
212
- def expand(template_class, *args)
213
- unless template_class.is_a?(::Class)
214
- name = template_class.to_s
215
- template_class = Templates.lookup(name)
216
- if template_class.nil?
217
- raise ToolDefinitionError, "Template not found: #{name.inspect}"
218
- end
219
- end
220
- template = template_class.new(*args)
221
- yield template if block_given?
222
- instance_exec(template, &template_class.expander)
223
- self
224
- end
225
-
226
- ##
227
- # Set the short description for the current tool. The short description is
228
- # displayed with the tool in a subtool list. You may also use the
229
- # equivalent method `short_desc`.
230
- #
231
- # The description is a {Toys::Utils::WrappableString}, which may be word-
232
- # wrapped when displayed in a help screen. You may pass a
233
- # {Toys::Utils::WrappableString} directly to this method, or you may pass
234
- # any input that can be used to construct a wrappable string:
235
- #
236
- # * If you pass a String, its whitespace will be compacted (i.e. tabs,
237
- # newlines, and multiple consecutive whitespace will be turned into a
238
- # single space), and it will be word-wrapped on whitespace.
239
- # * If you pass an Array of Strings, each string will be considered a
240
- # literal word that cannot be broken, and wrapping will be done across
241
- # the strings in the array. In this case, whitespace is not compacted.
242
- #
243
- # For example, if you pass in a sentence as a simple string, it may be
244
- # word wrapped when displayed:
245
- #
246
- # desc "This sentence may be wrapped."
247
- #
248
- # To specify a sentence that should never be word-wrapped, pass it as the
249
- # sole element of a string array:
250
- #
251
- # desc ["This sentence will not be wrapped."]
252
- #
253
- # @param [Toys::Utils::WrappableString,String,Array<String>] str
254
- #
255
- def desc(str)
256
- return self if _cur_tool.nil?
257
- _cur_tool.lock_definition_path(@path)
258
- _cur_tool.desc = str
259
- self
260
- end
261
- alias short_desc desc
262
-
263
- ##
264
- # Set the long description for the current tool. The long description is
265
- # displayed in the usage documentation for the tool itself.
266
- #
267
- # A long description is a series of descriptions, which are generally
268
- # displayed in a series of lines/paragraphs. Each individual description
269
- # uses the form described in the {Toys::ConfigDSL#desc} documentation, and
270
- # may be word-wrapped when displayed. To insert a blank line, include an
271
- # empty string as one of the descriptions.
272
- #
273
- # Example:
274
- #
275
- # long_desc "This is an initial paragraph that might be word wrapped.",
276
- # "This next paragraph is followed by a blank line.",
277
- # "",
278
- # ["This line will not be wrapped."]
279
- #
280
- # @param [Toys::Utils::WrappableString,String,Array<String>...] strs
281
- #
282
- def long_desc(*strs)
283
- return self if _cur_tool.nil?
284
- _cur_tool.lock_definition_path(@path)
285
- _cur_tool.long_desc = strs
286
- self
287
- end
288
-
289
- ##
290
- # Add a flag to the current tool. Each flag must specify a key which
291
- # the script may use to obtain the flag value from the context.
292
- # You may then provide the flags themselves in `OptionParser` form.
293
- #
294
- # Attributes of the flag may be passed in as arguments to this method, or
295
- # set in a block passed to this method.
296
- #
297
- # @param [Symbol] key The key to use to retrieve the value from the
298
- # execution context.
299
- # @param [String...] flags The flags in OptionParser format.
300
- # @param [Object] accept An acceptor that validates and/or converts the
301
- # value. You may provide either the name of an acceptor you have
302
- # defined, or one of the default acceptors provided by OptionParser.
303
- # Optional. If not specified, accepts any value as a string.
304
- # @param [Object] default The default value. This is the value that will
305
- # be set in the context if this flag is not provided on the command
306
- # line. Defaults to `nil`.
307
- # @param [Proc,nil] handler An optional handler for setting/updating the
308
- # value. If given, it should take two arguments, the new given value
309
- # and the previous value, and it should return the new value that
310
- # should be set. The default handler simply replaces the previous
311
- # value. i.e. the default is effectively `-> (val, _prev) { val }`.
312
- # @param [Boolean] report_collisions Raise an exception if a flag is
313
- # requested that is already in use or marked as unusable. Default is
314
- # true.
315
- # @param [String,Array<String>,Toys::Utils::WrappableString] desc Short
316
- # description for the flag. See {Toys::ConfigDSL#desc} for a description
317
- # of the allowed formats. Defaults to the empty string.
318
- # @param [Array<String,Array<String>,Toys::Utils::WrappableString>] long_desc
319
- # Long description for the flag. See {Toys::ConfigDSL#long_desc} for a
320
- # description of the allowed formats. (But note that this param takes
321
- # an Array of description lines, rather than a series of arguments.)
322
- # Defaults to the empty array.
323
- # @yieldparam flag_dsl [Toys::ConfigDSL::FlagDSL] An object that lets you
324
- # configure this flag in a block.
325
- #
326
- def flag(key, *flags,
327
- accept: nil, default: nil, handler: nil,
328
- report_collisions: true,
329
- desc: nil, long_desc: nil)
330
- return self if _cur_tool.nil?
331
- flag_dsl = FlagDSL.new(flags, accept, default, handler, report_collisions, desc, long_desc)
332
- yield flag_dsl if block_given?
333
- _cur_tool.lock_definition_path(@path)
334
- flag_dsl._add_to(_cur_tool, key)
335
- self
336
- end
337
-
338
- ##
339
- # Add a required positional argument to the current tool. You must specify
340
- # a key which the script may use to obtain the argument value from the
341
- # context.
342
- #
343
- # @param [Symbol] key The key to use to retrieve the value from the
344
- # execution context.
345
- # @param [Object] accept An acceptor that validates and/or converts the
346
- # value. You may provide either the name of an acceptor you have
347
- # defined, or one of the default acceptors provided by OptionParser.
348
- # Optional. If not specified, accepts any value as a string.
349
- # @param [String] display_name A name to use for display (in help text and
350
- # error reports). Defaults to the key in upper case.
351
- # @param [String,Array<String>,Toys::Utils::WrappableString] desc Short
352
- # description for the flag. See {Toys::ConfigDSL#desc} for a description
353
- # of the allowed formats. Defaults to the empty string.
354
- # @param [Array<String,Array<String>,Toys::Utils::WrappableString>] long_desc
355
- # Long description for the flag. See {Toys::ConfigDSL#long_desc} for a
356
- # description of the allowed formats. (But note that this param takes
357
- # an Array of description lines, rather than a series of arguments.)
358
- # Defaults to the empty array.
359
- # @yieldparam arg_dsl [Toys::ConfigDSL::ArgDSL] An object that lets you
360
- # configure this argument in a block.
361
- #
362
- def required_arg(key, accept: nil, display_name: nil, desc: nil, long_desc: nil)
363
- return self if _cur_tool.nil?
364
- arg_dsl = ArgDSL.new(accept, nil, display_name, desc, long_desc)
365
- yield arg_dsl if block_given?
366
- _cur_tool.lock_definition_path(@path)
367
- arg_dsl._add_required_to(_cur_tool, key)
368
- self
369
- end
370
- alias required required_arg
371
-
372
- ##
373
- # Add an optional positional argument to the current tool. You must specify
374
- # a key which the script may use to obtain the argument value from the
375
- # context. If an optional argument is not given on the command line, the
376
- # value is set to the given default.
377
- #
378
- # @param [Symbol] key The key to use to retrieve the value from the
379
- # execution context.
380
- # @param [Object] default The default value. This is the value that will
381
- # be set in the context if this argument is not provided on the command
382
- # line. Defaults to `nil`.
383
- # @param [Object] accept An acceptor that validates and/or converts the
384
- # value. You may provide either the name of an acceptor you have
385
- # defined, or one of the default acceptors provided by OptionParser.
386
- # Optional. If not specified, accepts any value as a string.
387
- # @param [String] display_name A name to use for display (in help text and
388
- # error reports). Defaults to the key in upper case.
389
- # @param [String,Array<String>,Toys::Utils::WrappableString] desc Short
390
- # description for the flag. See {Toys::ConfigDSL#desc} for a description
391
- # of the allowed formats. Defaults to the empty string.
392
- # @param [Array<String,Array<String>,Toys::Utils::WrappableString>] long_desc
393
- # Long description for the flag. See {Toys::ConfigDSL#long_desc} for a
394
- # description of the allowed formats. (But note that this param takes
395
- # an Array of description lines, rather than a series of arguments.)
396
- # Defaults to the empty array.
397
- # @yieldparam arg_dsl [Toys::ConfigDSL::ArgDSL] An object that lets you
398
- # configure this argument in a block.
399
- #
400
- def optional_arg(key, default: nil, accept: nil, display_name: nil,
401
- desc: nil, long_desc: nil)
402
- return self if _cur_tool.nil?
403
- arg_dsl = ArgDSL.new(accept, default, display_name, desc, long_desc)
404
- yield arg_dsl if block_given?
405
- _cur_tool.lock_definition_path(@path)
406
- arg_dsl._add_optional_to(_cur_tool, key)
407
- self
408
- end
409
- alias optional optional_arg
410
-
411
- ##
412
- # Specify what should be done with unmatched positional arguments. You must
413
- # specify a key which the script may use to obtain the remaining args from
414
- # the context.
415
- #
416
- # @param [Symbol] key The key to use to retrieve the value from the
417
- # execution context.
418
- # @param [Object] default The default value. This is the value that will
419
- # be set in the context if no unmatched arguments are provided on the
420
- # command line. Defaults to the empty array `[]`.
421
- # @param [Object] accept An acceptor that validates and/or converts the
422
- # value. You may provide either the name of an acceptor you have
423
- # defined, or one of the default acceptors provided by OptionParser.
424
- # Optional. If not specified, accepts any value as a string.
425
- # @param [String] display_name A name to use for display (in help text and
426
- # error reports). Defaults to the key in upper case.
427
- # @param [String,Array<String>,Toys::Utils::WrappableString] desc Short
428
- # description for the flag. See {Toys::ConfigDSL#desc} for a description
429
- # of the allowed formats. Defaults to the empty string.
430
- # @param [Array<String,Array<String>,Toys::Utils::WrappableString>] long_desc
431
- # Long description for the flag. See {Toys::ConfigDSL#long_desc} for a
432
- # description of the allowed formats. (But note that this param takes
433
- # an Array of description lines, rather than a series of arguments.)
434
- # Defaults to the empty array.
435
- # @yieldparam arg_dsl [Toys::ConfigDSL::ArgDSL] An object that lets you
436
- # configure this argument in a block.
437
- #
438
- def remaining_args(key, default: [], accept: nil, display_name: nil,
439
- desc: nil, long_desc: nil)
440
- return self if _cur_tool.nil?
441
- arg_dsl = ArgDSL.new(accept, default, display_name, desc, long_desc)
442
- yield arg_dsl if block_given?
443
- _cur_tool.lock_definition_path(@path)
444
- arg_dsl._set_remaining_on(_cur_tool, key)
445
- self
446
- end
447
- alias remaining remaining_args
448
-
449
- ##
450
- # Specify the script for this tool. This is a block that will be called,
451
- # with `self` set to a {Toys::Context}.
452
- #
453
- def script(&block)
454
- return self if _cur_tool.nil?
455
- _cur_tool.lock_definition_path(@path)
456
- _cur_tool.script = block
457
- self
458
- end
459
-
460
- ##
461
- # Define a helper method that may be called from this tool's script.
462
- # You must provide a name for the method, and a block for the method
463
- # definition.
464
- #
465
- # @param [String,Symbol] name Name of the method. May not begin with an
466
- # underscore.
467
- #
468
- def helper(name, &block)
469
- return self if _cur_tool.nil?
470
- _cur_tool.lock_definition_path(@path)
471
- _cur_tool.add_helper(name, &block)
472
- self
473
- end
474
-
475
- ##
476
- # Specify that the given module should be mixed in to this tool's script.
477
- # Effectively, the module is added to the {Toys::Context} object.
478
- # You may either provide a module directly, or specify the name of a
479
- # well-known module.
480
- #
481
- # @param [Module,Symbol] mod Module or name of well-known module.
482
- #
483
- def use(mod)
484
- return self if _cur_tool.nil?
485
- _cur_tool.lock_definition_path(@path)
486
- _cur_tool.use_module(mod)
487
- self
488
- end
489
-
490
- ##
491
- # DSL for a flag definition block. Lets you set flag attributes in a block
492
- # instead of a long series of keyword arguments.
493
- #
494
- class FlagDSL
495
- ## @private
496
- def initialize(flags, accept, default, handler, report_collisions, desc, long_desc)
497
- @flags = flags
498
- @accept = accept
499
- @default = default
500
- @handler = handler
501
- @report_collisions = report_collisions
502
- @desc = desc
503
- @long_desc = long_desc
504
- end
505
-
506
- ##
507
- # Add flags in OptionParser format. This may be called multiple times,
508
- # and the results are cumulative.
509
- # @param [String...] flags
510
- #
511
- def flags(*flags)
512
- @flags += flags
513
- self
514
- end
515
-
516
- ##
517
- # Set the OptionParser acceptor.
518
- # @param [Object] accept
519
- #
520
- def accept(accept)
521
- @accept = accept
522
- self
523
- end
524
-
525
- ##
526
- # Set the default value.
527
- # @param [Object] default
528
- #
529
- def default(default)
530
- @default = default
531
- self
532
- end
533
-
534
- ##
535
- # Set the optional handler for setting/updating the value when a flag is
536
- # parsed. It should be a Proc taking two arguments, the new given value
537
- # and the previous value, and it should return the new value that should
538
- # be set.
539
- # @param [Proc] handler
540
- #
541
- def handler(handler)
542
- @handler = handler
543
- self
544
- end
545
-
546
- ##
547
- # Set whether to raise an exception if a flag is requested that is
548
- # already in use or marked as disabled.
549
- # @param [Boolean] setting
550
- #
551
- def report_collisions(setting)
552
- @report_collisions = setting
553
- self
554
- end
555
-
556
- ##
557
- # Set the short description. See {Toys::ConfigDSL#desc} for the allowed
558
- # formats.
559
- # @param [String,Array<String>,Toys::Utils::WrappableString] desc
560
- #
561
- def desc(desc)
562
- @desc = desc
563
- self
564
- end
565
-
566
- ##
567
- # Adds to the long description. This may be called multiple times, and
568
- # the results are cumulative. See {Toys::ConfigDSL#long_desc} for the
569
- # allowed formats.
570
- # @param [String,Array<String>,Toys::Utils::WrappableString...] long_desc
571
- #
572
- def long_desc(*long_desc)
573
- @long_desc += long_desc
574
- self
575
- end
576
-
577
- ## @private
578
- def _add_to(tool, key)
579
- tool.add_flag(key, @flags,
580
- accept: @accept, default: @default, handler: @handler,
581
- report_collisions: @report_collisions,
582
- desc: @desc, long_desc: @long_desc)
583
- end
584
- end
585
-
586
- ##
587
- # DSL for an arg definition block. Lets you set arg attributes in a block
588
- # instead of a long series of keyword arguments.
589
- #
590
- class ArgDSL
591
- ## @private
592
- def initialize(accept, default, display_name, desc, long_desc)
593
- @accept = accept
594
- @default = default
595
- @display_name = display_name
596
- @desc = desc
597
- @long_desc = long_desc
598
- end
599
-
600
- ##
601
- # Set the OptionParser acceptor.
602
- # @param [Object] accept
603
- #
604
- def accept(accept)
605
- @accept = accept
606
- self
607
- end
608
-
609
- ##
610
- # Set the default value.
611
- # @param [Object] default
612
- #
613
- def default(default)
614
- @default = default
615
- self
616
- end
617
-
618
- ##
619
- # Set the name of this arg as it appears in help screens.
620
- # @param [String] display_name
621
- #
622
- def display_name(display_name)
623
- @handler = display_name
624
- self
625
- end
626
-
627
- ##
628
- # Set the short description. See {Toys::ConfigDSL#desc} for the allowed
629
- # formats.
630
- # @param [String,Array<String>,Toys::Utils::WrappableString] desc
631
- #
632
- def desc(desc)
633
- @desc = desc
634
- self
635
- end
636
-
637
- ##
638
- # Adds to the long description. This may be called multiple times, and
639
- # the results are cumulative. See {Toys::ConfigDSL#long_desc} for the
640
- # allowed formats.
641
- # @param [String,Array<String>,Toys::Utils::WrappableString...] long_desc
642
- #
643
- def long_desc(*long_desc)
644
- @long_desc += long_desc
645
- self
646
- end
647
-
648
- ## @private
649
- def _add_required_to(tool, key)
650
- tool.add_required_arg(key,
651
- accept: @accept, display_name: @display_name,
652
- desc: @desc, long_desc: @long_desc)
653
- end
654
-
655
- ## @private
656
- def _add_optional_to(tool, key)
657
- tool.add_optional_arg(key,
658
- accept: @accept, default: @default, display_name: @display_name,
659
- desc: @desc, long_desc: @long_desc)
660
- end
661
-
662
- ## @private
663
- def _set_remaining_on(tool, key)
664
- tool.set_remaining_args(key,
665
- accept: @accept, default: @default, display_name: @display_name,
666
- desc: @desc, long_desc: @long_desc)
667
- end
668
- end
669
-
670
- ## @private
671
- def _binding
672
- binding
673
- end
674
-
675
- ## @private
676
- def _cur_tool
677
- unless defined? @_cur_tool
678
- @_cur_tool = @loader.get_or_create_tool(@words, priority: @priority)
679
- end
680
- @_cur_tool
681
- end
682
-
683
- ## @private
684
- def self.evaluate(words, remaining_words, priority, loader, path, source)
685
- dsl = new(words, remaining_words, priority, loader, path)
686
- case source
687
- when String
688
- ContextualError.capture_path("Error while loading Toys config!", path) do
689
- # rubocop:disable Security/Eval
690
- eval(source, dsl._binding, path, 1)
691
- # rubocop:enable Security/Eval
692
- end
693
- when ::Proc
694
- dsl.instance_eval(&source)
695
- end
696
- nil
697
- end
698
- end
699
- end