toys-core 0.3.3 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -1
- data/lib/toys-core.rb +2 -0
- data/lib/toys/cli.rb +108 -15
- data/lib/toys/config_dsl.rb +101 -55
- data/lib/toys/context.rb +3 -3
- data/lib/toys/core_version.rb +1 -1
- data/lib/toys/errors.rb +76 -0
- data/lib/toys/helpers/highline.rb +0 -2
- data/lib/toys/helpers/spinner.rb +17 -11
- data/lib/toys/loader.rb +43 -18
- data/lib/toys/middleware.rb +14 -14
- data/lib/toys/middleware/add_verbosity_flags.rb +113 -0
- data/lib/toys/middleware/base.rb +1 -1
- data/lib/toys/middleware/handle_usage_errors.rb +15 -9
- data/lib/toys/middleware/set_default_descriptions.rb +114 -37
- data/lib/toys/middleware/show_help.rb +245 -0
- data/lib/toys/middleware/show_version.rb +20 -16
- data/lib/toys/templates/clean.rb +4 -1
- data/lib/toys/templates/gem_build.rb +3 -1
- data/lib/toys/templates/minitest.rb +5 -6
- data/lib/toys/tool.rb +418 -213
- data/lib/toys/utils/help_text.rb +487 -0
- data/lib/toys/utils/line_output.rb +105 -0
- data/lib/toys/utils/wrappable_string.rb +67 -19
- metadata +6 -5
- data/lib/toys/middleware/add_verbosity_switches.rb +0 -99
- data/lib/toys/middleware/show_usage.rb +0 -174
- data/lib/toys/utils/usage.rb +0 -250
@@ -28,20 +28,21 @@
|
|
28
28
|
;
|
29
29
|
|
30
30
|
require "toys/middleware/base"
|
31
|
+
require "toys/utils/line_output"
|
31
32
|
|
32
33
|
module Toys
|
33
34
|
module Middleware
|
34
35
|
##
|
35
36
|
# A middleware that displays a version string for certain tools if the
|
36
|
-
# `--version`
|
37
|
-
# this
|
37
|
+
# `--version` flag is given. You can specify which tools respond to
|
38
|
+
# this flag, and the string that will be displayed.
|
38
39
|
#
|
39
40
|
class ShowVersion < Base
|
40
41
|
##
|
41
|
-
# Default version
|
42
|
+
# Default version flags
|
42
43
|
# @return [Array<String>]
|
43
44
|
#
|
44
|
-
|
45
|
+
DEFAULT_VERSION_FLAGS = ["--version"].freeze
|
45
46
|
|
46
47
|
##
|
47
48
|
# Return a simple version displayer that returns the given string for
|
@@ -58,28 +59,31 @@ module Toys
|
|
58
59
|
#
|
59
60
|
# @param [Proc] version_displayer A proc that takes a tool and returns
|
60
61
|
# either the version string that should be displayed, or a falsy
|
61
|
-
# value to indicate the tool should not have a `--version`
|
62
|
+
# value to indicate the tool should not have a `--version` flag.
|
62
63
|
# Defaults to a "null" displayer that returns false for all tools.
|
63
|
-
# @param [Array<String>]
|
64
|
+
# @param [Array<String>] version_flags A list of flags that should
|
64
65
|
# trigger displaying the version. Default is
|
65
|
-
# {
|
66
|
+
# {DEFAULT_VERSION_FLAGS}.
|
67
|
+
# @param [IO] stream Output stream to write to. Default is stdout.
|
66
68
|
#
|
67
69
|
def initialize(version_displayer: nil,
|
68
|
-
|
70
|
+
version_flags: DEFAULT_VERSION_FLAGS,
|
71
|
+
stream: $stdout)
|
69
72
|
@version_displayer = version_displayer || proc { |_| false }
|
70
|
-
@
|
73
|
+
@version_flags = version_flags
|
74
|
+
@output = Utils::LineOutput.new(stream)
|
71
75
|
end
|
72
76
|
|
73
77
|
##
|
74
|
-
# Adds the version
|
78
|
+
# Adds the version flag if requested.
|
75
79
|
#
|
76
|
-
def config(tool)
|
80
|
+
def config(tool, _loader)
|
77
81
|
version = @version_displayer.call(tool)
|
78
82
|
if version
|
79
|
-
tool.
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
+
tool.add_flag(:_show_version, *@version_flags,
|
84
|
+
desc: "Display the version",
|
85
|
+
handler: ->(_val, _prev) { version },
|
86
|
+
only_unique: true)
|
83
87
|
end
|
84
88
|
yield
|
85
89
|
end
|
@@ -89,7 +93,7 @@ module Toys
|
|
89
93
|
#
|
90
94
|
def execute(context)
|
91
95
|
if context[:_show_version]
|
92
|
-
puts context[:_show_version]
|
96
|
+
@output.puts context[:_show_version]
|
93
97
|
else
|
94
98
|
yield
|
95
99
|
end
|
data/lib/toys/templates/clean.rb
CHANGED
@@ -88,6 +88,8 @@ module Toys
|
|
88
88
|
tool(template.name) do
|
89
89
|
desc "#{task_type} the gem: #{template.gem_name}"
|
90
90
|
|
91
|
+
flag :yes, "-y", "--yes", desc: "Do not ask for interactive confirmation"
|
92
|
+
|
91
93
|
use :exec
|
92
94
|
use :fileutils
|
93
95
|
use :highline
|
@@ -105,7 +107,7 @@ module Toys
|
|
105
107
|
logger.error "Cannot push the gem when there are uncommited changes"
|
106
108
|
exit(1)
|
107
109
|
end
|
108
|
-
exit(1) unless agree("Release #{gemfile}? (y/n) ")
|
110
|
+
exit(1) unless options[:yes] || agree("Release #{gemfile}? (y/n) ")
|
109
111
|
sh "gem push pkg/#{gemfile}"
|
110
112
|
if template.tag
|
111
113
|
sh "git tag v#{version}"
|
@@ -86,12 +86,11 @@ module Toys
|
|
86
86
|
|
87
87
|
use :exec
|
88
88
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
)
|
94
|
-
remaining_args(:tests, docs: "Paths to the tests to run (defaults to all tests)")
|
89
|
+
flag :warnings, "-w", "--[no-]warnings",
|
90
|
+
default: template.warnings,
|
91
|
+
desc: "Turn on Ruby warnings (defaults to #{template.warnings})"
|
92
|
+
|
93
|
+
remaining_args :tests, desc: "Paths to the tests to run (defaults to all tests)"
|
95
94
|
|
96
95
|
execute do
|
97
96
|
ruby_args = []
|
data/lib/toys/tool.rb
CHANGED
@@ -35,7 +35,7 @@ module Toys
|
|
35
35
|
##
|
36
36
|
# A Tool is a single command that can be invoked using Toys.
|
37
37
|
# It has a name, a series of one or more words that you use to identify
|
38
|
-
# the tool on the command line. It also has a set of formal
|
38
|
+
# the tool on the command line. It also has a set of formal flags and
|
39
39
|
# command line arguments supported, and a block that gets run when the
|
40
40
|
# tool is executed.
|
41
41
|
#
|
@@ -52,11 +52,11 @@ module Toys
|
|
52
52
|
@definition_path = nil
|
53
53
|
@definition_finished = false
|
54
54
|
|
55
|
-
@desc =
|
55
|
+
@desc = Toys::Utils::WrappableString.new("")
|
56
56
|
@long_desc = []
|
57
57
|
|
58
58
|
@default_data = {}
|
59
|
-
@
|
59
|
+
@flag_definitions = []
|
60
60
|
@required_arg_definitions = []
|
61
61
|
@optional_arg_definitions = []
|
62
62
|
@remaining_args_definition = nil
|
@@ -74,10 +74,22 @@ module Toys
|
|
74
74
|
attr_reader :full_name
|
75
75
|
|
76
76
|
##
|
77
|
-
#
|
78
|
-
# @return [
|
77
|
+
# Returns the short description string.
|
78
|
+
# @return [Toys::Utils::WrappableString]
|
79
79
|
#
|
80
|
-
attr_reader :
|
80
|
+
attr_reader :desc
|
81
|
+
|
82
|
+
##
|
83
|
+
# Returns the long description strings as an array.
|
84
|
+
# @return [Array<Toys::Utils::WrappableString>]
|
85
|
+
#
|
86
|
+
attr_reader :long_desc
|
87
|
+
|
88
|
+
##
|
89
|
+
# Return a list of all defined flags.
|
90
|
+
# @return [Array<Toys::Tool::FlagDefinition>]
|
91
|
+
#
|
92
|
+
attr_reader :flag_definitions
|
81
93
|
|
82
94
|
##
|
83
95
|
# Return a list of all defined required positional arguments.
|
@@ -167,45 +179,21 @@ module Toys
|
|
167
179
|
executor.is_a?(::Proc)
|
168
180
|
end
|
169
181
|
|
170
|
-
##
|
171
|
-
# Returns the effective short description for this tool. This will be
|
172
|
-
# displayed when this tool is listed in a command list.
|
173
|
-
#
|
174
|
-
# @param [Integer,nil] wrap_width Wrap wrappable strings to the given
|
175
|
-
# width, or `nil` for no wrapping.
|
176
|
-
# @return [Array<String>]
|
177
|
-
#
|
178
|
-
def effective_desc(wrap_width: nil)
|
179
|
-
Tool.resolve_wrapping(@desc, wrap_width)
|
180
|
-
end
|
181
|
-
|
182
|
-
##
|
183
|
-
# Returns the effective long description for this tool. This will be
|
184
|
-
# displayed as part of the usage for this particular tool.
|
185
|
-
#
|
186
|
-
# @param [Integer,nil] wrap_width Wrap wrappable strings to the given
|
187
|
-
# width, or `nil` for no wrapping.
|
188
|
-
# @return [Array<String>]
|
189
|
-
#
|
190
|
-
def effective_long_desc(wrap_width: nil)
|
191
|
-
Tool.resolve_wrapping(@long_desc.empty? ? @desc : @long_desc, wrap_width)
|
192
|
-
end
|
193
|
-
|
194
182
|
##
|
195
183
|
# Returns true if there is a specific description set for this tool.
|
196
184
|
# @return [Boolean]
|
197
185
|
#
|
198
186
|
def includes_description?
|
199
|
-
|
187
|
+
!long_desc.empty? || !desc.empty?
|
200
188
|
end
|
201
189
|
|
202
190
|
##
|
203
|
-
# Returns true if at least one
|
191
|
+
# Returns true if at least one flag or positional argument is defined
|
204
192
|
# for this tool.
|
205
193
|
# @return [Boolean]
|
206
194
|
#
|
207
195
|
def includes_arguments?
|
208
|
-
!default_data.empty? || !
|
196
|
+
!default_data.empty? || !flag_definitions.empty? ||
|
209
197
|
!required_arg_definitions.empty? || !optional_arg_definitions.empty? ||
|
210
198
|
!remaining_args_definition.nil?
|
211
199
|
end
|
@@ -228,11 +216,29 @@ module Toys
|
|
228
216
|
end
|
229
217
|
|
230
218
|
##
|
231
|
-
# Returns
|
219
|
+
# Returns true if this tool's definition has been finished and is locked.
|
220
|
+
# @return [Boolean]
|
221
|
+
#
|
222
|
+
def definition_finished?
|
223
|
+
@definition_finished
|
224
|
+
end
|
225
|
+
|
226
|
+
##
|
227
|
+
# Returns all arg definitions in order: required, optional, remaining.
|
228
|
+
# @return [Array<Toys::Tool::ArgDefinition>]
|
229
|
+
#
|
230
|
+
def arg_definitions
|
231
|
+
result = required_arg_definitions + optional_arg_definitions
|
232
|
+
result << remaining_args_definition if remaining_args_definition
|
233
|
+
result
|
234
|
+
end
|
235
|
+
|
236
|
+
##
|
237
|
+
# Returns a list of flags used by this tool.
|
232
238
|
# @return [Array<String>]
|
233
239
|
#
|
234
|
-
def
|
235
|
-
|
240
|
+
def used_flags
|
241
|
+
flag_definitions.reduce([]) { |used, fdef| used + fdef.effective_flags }.uniq
|
236
242
|
end
|
237
243
|
|
238
244
|
##
|
@@ -242,33 +248,56 @@ module Toys
|
|
242
248
|
#
|
243
249
|
# @param [String] path The path to the file defining this tool
|
244
250
|
#
|
245
|
-
def
|
246
|
-
if
|
251
|
+
def lock_definition_path(path)
|
252
|
+
if definition_path && definition_path != path
|
247
253
|
raise ToolDefinitionError,
|
248
254
|
"Cannot redefine tool #{display_name.inspect} in #{path}" \
|
249
|
-
" (already defined in #{
|
255
|
+
" (already defined in #{definition_path})"
|
250
256
|
end
|
251
257
|
@definition_path = path
|
252
258
|
end
|
253
259
|
|
254
260
|
##
|
255
|
-
# Set the short description.
|
261
|
+
# Set the short description string.
|
262
|
+
#
|
263
|
+
# The description may be provided as a {Toys::Utils::WrappableString}, a
|
264
|
+
# single string (which will be wrapped), or an array of strings, which will
|
265
|
+
# be interpreted as string fragments that will be concatenated and wrapped.
|
256
266
|
#
|
257
|
-
# @param [String,Array<String>]
|
267
|
+
# @param [Toys::Utils::WrappableString,String,Array<String>] desc
|
258
268
|
#
|
259
|
-
def desc=(
|
269
|
+
def desc=(desc)
|
260
270
|
check_definition_state
|
261
|
-
@desc = Tool.canonicalize_desc(
|
271
|
+
@desc = Tool.canonicalize_desc(desc)
|
262
272
|
end
|
263
273
|
|
264
274
|
##
|
265
|
-
# Set the long description.
|
275
|
+
# Set the long description strings.
|
266
276
|
#
|
267
|
-
#
|
277
|
+
# Each string may be provided as a {Toys::Utils::WrappableString}, a single
|
278
|
+
# string (which will be wrapped), or an array of strings, which will be
|
279
|
+
# interpreted as string fragments that will be concatenated and wrapped.
|
268
280
|
#
|
269
|
-
|
281
|
+
# @param [Array<Toys::Utils::WrappableString,String,Array<String>>] descs
|
282
|
+
#
|
283
|
+
def long_desc=(descs)
|
270
284
|
check_definition_state
|
271
|
-
@long_desc = Tool.
|
285
|
+
@long_desc = Tool.canonicalize_long_desc(descs)
|
286
|
+
end
|
287
|
+
|
288
|
+
##
|
289
|
+
# Set the long description strings.
|
290
|
+
#
|
291
|
+
# Each string may be provided as a {Toys::Utils::WrappableString}, a single
|
292
|
+
# string (which will be wrapped), or an array of strings, which will be
|
293
|
+
# interpreted as string fragments that will be concatenated and wrapped.
|
294
|
+
#
|
295
|
+
# @param [Toys::Utils::WrappableString,String,Array<String>...] descs
|
296
|
+
#
|
297
|
+
def populate_long_desc(*descs)
|
298
|
+
check_definition_state
|
299
|
+
@long_desc = Tool.canonicalize_long_desc(descs)
|
300
|
+
self
|
272
301
|
end
|
273
302
|
|
274
303
|
##
|
@@ -312,24 +341,27 @@ module Toys
|
|
312
341
|
end
|
313
342
|
|
314
343
|
##
|
315
|
-
# Add a
|
316
|
-
# the executor may use to obtain the
|
317
|
-
# You may then provide the
|
344
|
+
# Add a flag to the current tool. Each flag must specify a key which
|
345
|
+
# the executor may use to obtain the flag value from the context.
|
346
|
+
# You may then provide the flags themselves in `OptionParser` form.
|
318
347
|
#
|
319
348
|
# @param [Symbol] key The key to use to retrieve the value from the
|
320
349
|
# execution context.
|
321
|
-
# @param [String...]
|
350
|
+
# @param [String...] flags The flags in OptionParser format.
|
322
351
|
# @param [Object,nil] accept An OptionParser acceptor. Optional.
|
323
352
|
# @param [Object] default The default value. This is the value that will
|
324
|
-
# be set in the context if this
|
353
|
+
# be set in the context if this flag is not provided on the command
|
325
354
|
# line. Defaults to `nil`.
|
326
355
|
# @param [String,Toys::Utils::WrappableString,
|
327
|
-
# Array<String,Toys::Utils::WrappableString>]
|
328
|
-
# the
|
329
|
-
# @param [
|
330
|
-
#
|
331
|
-
#
|
332
|
-
#
|
356
|
+
# Array<String,Toys::Utils::WrappableString>] desc Short description
|
357
|
+
# for the flag. Defaults to empty array.
|
358
|
+
# @param [String,Toys::Utils::WrappableString,
|
359
|
+
# Array<String,Toys::Utils::WrappableString>] long_desc Long
|
360
|
+
# description for the flag. Defaults to empty array.
|
361
|
+
# @param [Boolean] only_unique If true, any flags that are already
|
362
|
+
# defined in this tool are removed from this flag. For example, if
|
363
|
+
# an earlier flag uses `-a`, and this flag wants to use both
|
364
|
+
# `-a` and `-b`, then only `-b` will be assigned to this flag.
|
333
365
|
# Defaults to false.
|
334
366
|
# @param [Proc,nil] handler An optional handler for setting/updating the
|
335
367
|
# value. If given, it should take two arguments, the new given value
|
@@ -337,17 +369,21 @@ module Toys
|
|
337
369
|
# should be set. The default handler simply replaces the previous
|
338
370
|
# value. i.e. the default is effectively `-> (val, _prev) { val }`.
|
339
371
|
#
|
340
|
-
def
|
341
|
-
|
372
|
+
def add_flag(key, *flags,
|
373
|
+
accept: nil, default: nil, desc: nil, long_desc: nil,
|
374
|
+
only_unique: false, handler: nil)
|
342
375
|
check_definition_state
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
376
|
+
flag_def = FlagDefinition.new(self, key)
|
377
|
+
flag_def.add_flags(flags)
|
378
|
+
flag_def.accept = accept
|
379
|
+
flag_def.handler = handler
|
380
|
+
flag_def.default = default
|
381
|
+
flag_def.desc = desc unless desc.nil?
|
382
|
+
flag_def.long_desc = long_desc unless long_desc.nil?
|
383
|
+
yield flag_def if block_given?
|
384
|
+
flag_def.create_default_flag_if_needed
|
385
|
+
flag_def.remove_flags(used_flags) if only_unique
|
386
|
+
@flag_definitions << flag_def if flag_def.active?
|
351
387
|
self
|
352
388
|
end
|
353
389
|
|
@@ -359,14 +395,25 @@ module Toys
|
|
359
395
|
# @param [Symbol] key The key to use to retrieve the value from the
|
360
396
|
# execution context.
|
361
397
|
# @param [Object,nil] accept An OptionParser acceptor. Optional.
|
398
|
+
# @param [String] display_name A name to use for display (in help text and
|
399
|
+
# error reports). Defaults to the key in upper case.
|
400
|
+
# @param [String,Toys::Utils::WrappableString,
|
401
|
+
# Array<String,Toys::Utils::WrappableString>] desc Short description
|
402
|
+
# for the arg. Defaults to empty array.
|
362
403
|
# @param [String,Toys::Utils::WrappableString,
|
363
|
-
# Array<String,Toys::Utils::WrappableString>]
|
364
|
-
# the arg. Defaults to empty array.
|
404
|
+
# Array<String,Toys::Utils::WrappableString>] long_desc Long
|
405
|
+
# description for the arg. Defaults to empty array.
|
365
406
|
#
|
366
|
-
def add_required_arg(key, accept: nil,
|
407
|
+
def add_required_arg(key, accept: nil, display_name: nil, desc: nil, long_desc: nil)
|
367
408
|
check_definition_state
|
368
|
-
|
369
|
-
|
409
|
+
arg_def = ArgDefinition.new(self, key, :required)
|
410
|
+
arg_def.accept = accept
|
411
|
+
arg_def.default = nil
|
412
|
+
arg_def.display_name = display_name unless display_name.nil?
|
413
|
+
arg_def.desc = desc unless desc.nil?
|
414
|
+
arg_def.long_desc = long_desc unless long_desc.nil?
|
415
|
+
yield arg_def if block_given?
|
416
|
+
@required_arg_definitions << arg_def
|
370
417
|
self
|
371
418
|
end
|
372
419
|
|
@@ -378,18 +425,30 @@ module Toys
|
|
378
425
|
#
|
379
426
|
# @param [Symbol] key The key to use to retrieve the value from the
|
380
427
|
# execution context.
|
381
|
-
# @param [Object,nil] accept An OptionParser acceptor. Optional.
|
382
428
|
# @param [Object] default The default value. This is the value that will
|
383
429
|
# be set in the context if this argument is not provided on the command
|
384
430
|
# line. Defaults to `nil`.
|
431
|
+
# @param [Object,nil] accept An OptionParser acceptor. Optional.
|
432
|
+
# @param [String] display_name A name to use for display (in help text and
|
433
|
+
# error reports). Defaults to the key in upper case.
|
385
434
|
# @param [String,Toys::Utils::WrappableString,
|
386
|
-
# Array<String,Toys::Utils::WrappableString>]
|
387
|
-
# the arg. Defaults to empty array.
|
435
|
+
# Array<String,Toys::Utils::WrappableString>] desc Short description
|
436
|
+
# for the arg. Defaults to empty array.
|
437
|
+
# @param [String,Toys::Utils::WrappableString,
|
438
|
+
# Array<String,Toys::Utils::WrappableString>] long_desc Long
|
439
|
+
# description for the arg. Defaults to empty array.
|
388
440
|
#
|
389
|
-
def add_optional_arg(key,
|
441
|
+
def add_optional_arg(key, default: nil, accept: nil, display_name: nil,
|
442
|
+
desc: nil, long_desc: nil)
|
390
443
|
check_definition_state
|
391
|
-
|
392
|
-
|
444
|
+
arg_def = ArgDefinition.new(self, key, :optional)
|
445
|
+
arg_def.accept = accept
|
446
|
+
arg_def.default = default
|
447
|
+
arg_def.display_name = display_name unless display_name.nil?
|
448
|
+
arg_def.desc = desc unless desc.nil?
|
449
|
+
arg_def.long_desc = long_desc unless long_desc.nil?
|
450
|
+
yield arg_def if block_given?
|
451
|
+
@optional_arg_definitions << arg_def
|
393
452
|
self
|
394
453
|
end
|
395
454
|
|
@@ -400,18 +459,30 @@ module Toys
|
|
400
459
|
#
|
401
460
|
# @param [Symbol] key The key to use to retrieve the value from the
|
402
461
|
# execution context.
|
403
|
-
# @param [Object,nil] accept An OptionParser acceptor. Optional.
|
404
462
|
# @param [Object] default The default value. This is the value that will
|
405
463
|
# be set in the context if no unmatched arguments are provided on the
|
406
464
|
# command line. Defaults to the empty array `[]`.
|
465
|
+
# @param [Object,nil] accept An OptionParser acceptor. Optional.
|
466
|
+
# @param [String] display_name A name to use for display (in help text and
|
467
|
+
# error reports). Defaults to the key in upper case.
|
468
|
+
# @param [String,Toys::Utils::WrappableString,
|
469
|
+
# Array<String,Toys::Utils::WrappableString>] desc Short description
|
470
|
+
# for the arg. Defaults to empty array.
|
407
471
|
# @param [String,Toys::Utils::WrappableString,
|
408
|
-
# Array<String,Toys::Utils::WrappableString>]
|
409
|
-
# the
|
472
|
+
# Array<String,Toys::Utils::WrappableString>] long_desc Long
|
473
|
+
# description for the arg. Defaults to empty array.
|
410
474
|
#
|
411
|
-
def set_remaining_args(key,
|
475
|
+
def set_remaining_args(key, default: [], accept: nil, display_name: nil,
|
476
|
+
desc: nil, long_desc: nil)
|
412
477
|
check_definition_state
|
413
|
-
|
414
|
-
|
478
|
+
arg_def = ArgDefinition.new(self, key, :remaining)
|
479
|
+
arg_def.accept = accept
|
480
|
+
arg_def.default = default
|
481
|
+
arg_def.display_name = display_name unless display_name.nil?
|
482
|
+
arg_def.desc = desc unless desc.nil?
|
483
|
+
arg_def.long_desc = long_desc unless long_desc.nil?
|
484
|
+
yield arg_def if block_given?
|
485
|
+
@remaining_args_definition = arg_def
|
415
486
|
self
|
416
487
|
end
|
417
488
|
|
@@ -437,33 +508,40 @@ module Toys
|
|
437
508
|
# @return [Integer] The result code.
|
438
509
|
#
|
439
510
|
def execute(cli, args, verbosity: 0)
|
440
|
-
|
441
|
-
|
511
|
+
ContextualError.capture_path(
|
512
|
+
"Error during tool execution!", definition_path,
|
513
|
+
tool_name: full_name, tool_args: args
|
514
|
+
) do
|
515
|
+
Execution.new(self).execute(cli, args, verbosity: verbosity)
|
516
|
+
end
|
442
517
|
end
|
443
518
|
|
444
519
|
##
|
445
520
|
# Complete definition and run middleware configs
|
521
|
+
# @param [Toys::Loader] loader
|
446
522
|
#
|
447
523
|
# @private
|
448
524
|
#
|
449
|
-
def finish_definition
|
525
|
+
def finish_definition(loader)
|
450
526
|
unless @definition_finished
|
451
|
-
|
452
|
-
|
453
|
-
|
527
|
+
ContextualError.capture("Error installing tool middleware!", tool_name: full_name) do
|
528
|
+
config_proc = proc {}
|
529
|
+
middleware_stack.reverse.each do |middleware|
|
530
|
+
config_proc = make_config_proc(middleware, loader, config_proc)
|
531
|
+
end
|
532
|
+
config_proc.call
|
454
533
|
end
|
455
|
-
config_proc.call
|
456
534
|
@definition_finished = true
|
457
535
|
end
|
458
536
|
self
|
459
537
|
end
|
460
538
|
|
461
539
|
##
|
462
|
-
# Representation of a single
|
540
|
+
# Representation of a single flag
|
463
541
|
#
|
464
|
-
class
|
542
|
+
class FlagSyntax
|
465
543
|
##
|
466
|
-
# Parse
|
544
|
+
# Parse flag syntax
|
467
545
|
# @param [String] str syntax.
|
468
546
|
#
|
469
547
|
def initialize(str)
|
@@ -474,58 +552,54 @@ module Toys
|
|
474
552
|
elsif str =~ /^(--\w[\?\w-]*)(([=\s])(\w+))?$/
|
475
553
|
setup(str, [$1], $1, "--", $3, $4)
|
476
554
|
else
|
477
|
-
raise ToolDefinitionError, "Illegal
|
555
|
+
raise ToolDefinitionError, "Illegal flag: #{str.inspect}"
|
478
556
|
end
|
479
557
|
end
|
480
558
|
|
481
|
-
attr_reader :
|
559
|
+
attr_reader :original_str
|
482
560
|
attr_reader :str_without_value
|
483
|
-
attr_reader :
|
484
|
-
attr_reader :
|
561
|
+
attr_reader :flags
|
562
|
+
attr_reader :flag_style
|
485
563
|
attr_reader :value_delim
|
486
564
|
attr_reader :value_label
|
487
565
|
|
488
566
|
private
|
489
567
|
|
490
|
-
def setup(
|
491
|
-
@
|
492
|
-
@
|
568
|
+
def setup(original_str, flags, str_without_value, flag_style, value_delim, value_label)
|
569
|
+
@original_str = original_str
|
570
|
+
@flags = flags
|
493
571
|
@str_without_value = str_without_value
|
494
|
-
@
|
572
|
+
@flag_style = flag_style
|
495
573
|
@value_delim = value_delim
|
496
|
-
@value_label = value_label
|
574
|
+
@value_label = value_label ? value_label.upcase : value_label
|
497
575
|
end
|
498
576
|
end
|
499
577
|
|
500
578
|
##
|
501
|
-
# Representation of a formal set of
|
579
|
+
# Representation of a formal set of flags.
|
502
580
|
#
|
503
|
-
class
|
581
|
+
class FlagDefinition
|
582
|
+
##
|
583
|
+
# The default handler replaces the previous value.
|
584
|
+
# @return [Proc]
|
585
|
+
#
|
586
|
+
DEFAULT_HANDLER = ->(val, _prev) { val }
|
587
|
+
|
504
588
|
##
|
505
|
-
# Create a
|
589
|
+
# Create a FlagDefinition
|
506
590
|
# @private
|
507
591
|
#
|
508
|
-
# @param [Symbol] key This
|
509
|
-
#
|
510
|
-
|
511
|
-
|
512
|
-
# Array<String,Toys::Utils::WrappableString>] docs Documentation
|
513
|
-
# @param [Proc,nil] handler An optional handler for setting/updating the
|
514
|
-
# value. If given, it should take two arguments, the new given value
|
515
|
-
# and the previous value, and it should return the new value that
|
516
|
-
# should be set. If `nil`, uses a default handler that just replaces
|
517
|
-
# the previous value. i.e. the default is effectively
|
518
|
-
# `-> (val, _prev) { val }`.
|
519
|
-
#
|
520
|
-
def initialize(key, switches, accept, docs, handler = nil)
|
592
|
+
# @param [Symbol] key This flag will set the given context key.
|
593
|
+
#
|
594
|
+
def initialize(tool, key)
|
595
|
+
@tool = tool
|
521
596
|
@key = key
|
522
|
-
|
523
|
-
@
|
524
|
-
@
|
525
|
-
@
|
526
|
-
@
|
597
|
+
@flag_syntax = []
|
598
|
+
@accept = nil
|
599
|
+
@handler = DEFAULT_HANDLER
|
600
|
+
@desc = ""
|
601
|
+
@long_desc = []
|
527
602
|
reset_data
|
528
|
-
@effective_switches = nil
|
529
603
|
end
|
530
604
|
|
531
605
|
##
|
@@ -535,10 +609,10 @@ module Toys
|
|
535
609
|
attr_reader :key
|
536
610
|
|
537
611
|
##
|
538
|
-
# Returns an array of
|
539
|
-
# @return [Array<
|
612
|
+
# Returns an array of FlagSyntax for the flags.
|
613
|
+
# @return [Array<FlagSyntax>]
|
540
614
|
#
|
541
|
-
attr_reader :
|
615
|
+
attr_reader :flag_syntax
|
542
616
|
|
543
617
|
##
|
544
618
|
# Returns the acceptor, which may be `nil`.
|
@@ -547,66 +621,150 @@ module Toys
|
|
547
621
|
attr_reader :accept
|
548
622
|
|
549
623
|
##
|
550
|
-
# Returns the
|
551
|
-
# @return [
|
624
|
+
# Returns the short description string.
|
625
|
+
# @return [Toys::Utils::WrappableString]
|
626
|
+
#
|
627
|
+
attr_reader :desc
|
628
|
+
|
629
|
+
##
|
630
|
+
# Returns the long description strings as an array.
|
631
|
+
# @return [Array<Toys::Utils::WrappableString>]
|
552
632
|
#
|
553
|
-
attr_reader :
|
633
|
+
attr_reader :long_desc
|
554
634
|
|
555
635
|
##
|
556
|
-
# Returns the handler.
|
636
|
+
# Returns the handler for setting/updating the value.
|
557
637
|
# @return [Proc]
|
558
638
|
#
|
559
639
|
attr_reader :handler
|
560
640
|
|
561
641
|
##
|
562
|
-
#
|
563
|
-
# @
|
642
|
+
# Adds the given flags.
|
643
|
+
# @param [Array<String>] flags Flags in OptionParser format
|
564
644
|
#
|
565
|
-
def
|
566
|
-
@
|
645
|
+
def add_flags(flags)
|
646
|
+
@flag_syntax.concat(flags.map { |s| FlagSyntax.new(s) })
|
647
|
+
reset_data
|
648
|
+
self
|
567
649
|
end
|
568
650
|
|
569
651
|
##
|
570
|
-
#
|
571
|
-
# @
|
652
|
+
# Set the acceptor.
|
653
|
+
# @param [Object] accept Acceptor. May be `nil` for the default.
|
572
654
|
#
|
573
|
-
def
|
574
|
-
@
|
655
|
+
def accept=(accept)
|
656
|
+
@accept = accept
|
657
|
+
reset_data
|
575
658
|
end
|
576
659
|
|
577
660
|
##
|
578
|
-
#
|
579
|
-
# @
|
661
|
+
# Set the default.
|
662
|
+
# @param [Object] default The default value.
|
663
|
+
#
|
664
|
+
def default=(default)
|
665
|
+
@tool.default_data[@key] = default
|
666
|
+
end
|
667
|
+
|
668
|
+
##
|
669
|
+
# Set the handler for setting/updating the value.
|
670
|
+
# @param [Proc,nil] handler The handler for setting/updating the value.
|
671
|
+
# The handler should take two arguments, the new given value and the
|
672
|
+
# previous value, and it should return the new value that should be
|
673
|
+
# set. If `nil`, uses {DEFAULT_HANDLER}.
|
674
|
+
#
|
675
|
+
def handler=(handler)
|
676
|
+
@handler = handler || DEFAULT_HANDLER
|
677
|
+
end
|
678
|
+
|
679
|
+
##
|
680
|
+
# Set the short description string.
|
681
|
+
#
|
682
|
+
# The description may be provided as a {Toys::Utils::WrappableString}, a
|
683
|
+
# single string (which will be wrapped), or an array of strings, which
|
684
|
+
# will be interpreted as string fragments that will be concatenated and
|
685
|
+
# wrapped.
|
686
|
+
#
|
687
|
+
# @param [Toys::Utils::WrappableString,String,Array<String>] desc
|
688
|
+
#
|
689
|
+
def desc=(desc)
|
690
|
+
@desc = Tool.canonicalize_desc(desc)
|
691
|
+
end
|
692
|
+
|
693
|
+
##
|
694
|
+
# Set the long description strings.
|
695
|
+
#
|
696
|
+
# Each string may be provided as a {Toys::Utils::WrappableString}, a
|
697
|
+
# single string (which will be wrapped), or an array of strings, which
|
698
|
+
# will be interpreted as string fragments that will be concatenated and
|
699
|
+
# wrapped.
|
580
700
|
#
|
581
|
-
|
582
|
-
|
701
|
+
# @param [Array<Toys::Utils::WrappableString,String,Array<String>>] descs
|
702
|
+
#
|
703
|
+
def long_desc=(descs)
|
704
|
+
@long_desc = Tool.canonicalize_long_desc(descs)
|
583
705
|
end
|
584
706
|
|
585
707
|
##
|
586
|
-
#
|
708
|
+
# Set the long description strings.
|
709
|
+
#
|
710
|
+
# Each string may be provided as a {Toys::Utils::WrappableString}, a
|
711
|
+
# single string (which will be wrapped), or an array of strings, which
|
712
|
+
# will be interpreted as string fragments that will be concatenated and
|
713
|
+
# wrapped.
|
587
714
|
#
|
588
|
-
# @param [
|
715
|
+
# @param [Toys::Utils::WrappableString,String,Array<String>...] descs
|
716
|
+
#
|
717
|
+
def populate_long_desc(*descs)
|
718
|
+
@long_desc = Tool.canonicalize_long_desc(descs)
|
719
|
+
self
|
720
|
+
end
|
721
|
+
|
722
|
+
##
|
723
|
+
# Returns an array of FlagSyntax including only single-dash flags
|
724
|
+
# @return [Array<FlagSyntax>]
|
725
|
+
#
|
726
|
+
def single_flag_syntax
|
727
|
+
@single_flag_syntax ||= flag_syntax.find_all { |ss| ss.flag_style == "-" }
|
728
|
+
end
|
729
|
+
|
730
|
+
##
|
731
|
+
# Returns an array of FlagSyntax including only double-dash flags
|
732
|
+
# @return [Array<FlagSyntax>]
|
733
|
+
#
|
734
|
+
def double_flag_syntax
|
735
|
+
@double_flag_syntax ||= flag_syntax.find_all { |ss| ss.flag_style == "--" }
|
736
|
+
end
|
737
|
+
|
738
|
+
##
|
739
|
+
# Returns the list of effective flags used.
|
589
740
|
# @return [Array<String>]
|
590
741
|
#
|
591
|
-
def
|
592
|
-
|
742
|
+
def effective_flags
|
743
|
+
@effective_flags ||= flag_syntax.map(&:flags).flatten
|
593
744
|
end
|
594
745
|
|
595
746
|
##
|
596
|
-
# All optparser
|
747
|
+
# All optparser flags and acceptor if present
|
597
748
|
# @return [Array]
|
598
749
|
#
|
599
750
|
def optparser_info
|
600
|
-
@optparser_info ||=
|
751
|
+
@optparser_info ||= begin
|
752
|
+
flags = flag_syntax.map do |fs|
|
753
|
+
f = fs.str_without_value
|
754
|
+
f = "#{f} #{value_label}" if value_label
|
755
|
+
f
|
756
|
+
end
|
757
|
+
flags + Array(accept)
|
758
|
+
end
|
601
759
|
end
|
602
760
|
|
603
761
|
##
|
604
|
-
# Returns true if this
|
605
|
-
#
|
762
|
+
# Returns true if this flag is active. That is, it has a nonempty
|
763
|
+
# flags list.
|
606
764
|
# @return [Boolean]
|
607
765
|
#
|
608
766
|
def active?
|
609
|
-
!
|
767
|
+
!effective_flags.empty?
|
610
768
|
end
|
611
769
|
|
612
770
|
##
|
@@ -627,47 +785,52 @@ module Toys
|
|
627
785
|
@value_delim
|
628
786
|
end
|
629
787
|
|
630
|
-
##
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
@switch_syntax.select! do |ss|
|
636
|
-
ss.switches.all? { |s| !switches.include?(s) }
|
788
|
+
## @private
|
789
|
+
def remove_flags(flags)
|
790
|
+
flags = flags.map { |f| FlagSyntax.new(f).flags }.flatten
|
791
|
+
@flag_syntax.select! do |ss|
|
792
|
+
ss.flags.all? { |s| !flags.include?(s) }
|
637
793
|
end
|
638
794
|
reset_data
|
639
795
|
self
|
640
796
|
end
|
641
797
|
|
798
|
+
## @private
|
799
|
+
def create_default_flag_if_needed
|
800
|
+
return unless @flag_syntax.empty?
|
801
|
+
canonical_flag = key.to_s.downcase.tr("_", "-").gsub(/[^a-z0-9-]/, "").sub(/^-+/, "")
|
802
|
+
unless canonical_flag.empty?
|
803
|
+
flag = @accept ? "--#{canonical_flag}=VALUE" : "--#{canonical_flag}"
|
804
|
+
@flag_syntax << FlagSyntax.new(flag)
|
805
|
+
end
|
806
|
+
reset_data
|
807
|
+
end
|
808
|
+
|
642
809
|
private
|
643
810
|
|
644
811
|
def reset_data
|
645
|
-
@
|
812
|
+
@effective_flags = nil
|
646
813
|
@optparser_info = nil
|
647
|
-
@
|
648
|
-
@
|
814
|
+
@single_flag_syntax = nil
|
815
|
+
@double_flag_syntax = nil
|
649
816
|
@value_label = nil
|
650
817
|
@value_delim = nil
|
651
818
|
end
|
652
819
|
|
653
820
|
def find_canonical_value_label
|
654
821
|
return if @value_delim
|
655
|
-
|
822
|
+
@value_label = @accept ? "VALUE" : nil
|
823
|
+
@value_delim = @accept ? " " : ""
|
824
|
+
single_flag_syntax.each do |ss|
|
656
825
|
next unless ss.value_label
|
657
826
|
@value_label = ss.value_label
|
658
827
|
@value_delim = ss.value_delim
|
659
|
-
break
|
660
828
|
end
|
661
|
-
|
662
|
-
single_switch_syntax.reverse_each do |ss|
|
829
|
+
double_flag_syntax.each do |ss|
|
663
830
|
next unless ss.value_label
|
664
831
|
@value_label = ss.value_label
|
665
832
|
@value_delim = ss.value_delim
|
666
|
-
break
|
667
833
|
end
|
668
|
-
return if @value_delim
|
669
|
-
@value_label = nil
|
670
|
-
@value_delim = ""
|
671
834
|
end
|
672
835
|
end
|
673
836
|
|
@@ -680,14 +843,16 @@ module Toys
|
|
680
843
|
# @private
|
681
844
|
#
|
682
845
|
# @param [Symbol] key This argument will set the given context key.
|
683
|
-
# @param [
|
684
|
-
# @param [String,Toys::Utils::WrappableString,
|
685
|
-
# Array<String,Toys::Utils::WrappableString>] docs Documentation
|
846
|
+
# @param [:required,:optional,:remaining] type Type of this argument
|
686
847
|
#
|
687
|
-
def initialize(
|
848
|
+
def initialize(tool, key, type)
|
849
|
+
@tool = tool
|
688
850
|
@key = key
|
689
|
-
@
|
690
|
-
@
|
851
|
+
@type = type
|
852
|
+
@accept = nil
|
853
|
+
@desc = ""
|
854
|
+
@long_desc = []
|
855
|
+
@display_name = key.to_s.tr("-", "_").gsub(/\W/, "").upcase
|
691
856
|
end
|
692
857
|
|
693
858
|
##
|
@@ -696,35 +861,85 @@ module Toys
|
|
696
861
|
#
|
697
862
|
attr_reader :key
|
698
863
|
|
864
|
+
##
|
865
|
+
# Type of this argument.
|
866
|
+
# @return [:required,:optional,:remaining]
|
867
|
+
#
|
868
|
+
attr_reader :type
|
869
|
+
|
699
870
|
##
|
700
871
|
# Returns the acceptor, which may be `nil`.
|
701
872
|
# @return [Object]
|
702
873
|
#
|
703
|
-
|
874
|
+
attr_accessor :accept
|
704
875
|
|
705
876
|
##
|
706
|
-
# Returns the
|
707
|
-
# @return [
|
877
|
+
# Returns the short description string.
|
878
|
+
# @return [Toys::Utils::WrappableString]
|
708
879
|
#
|
709
|
-
attr_reader :
|
880
|
+
attr_reader :desc
|
710
881
|
|
711
882
|
##
|
712
|
-
#
|
883
|
+
# Returns the long description strings as an array.
|
884
|
+
# @return [Array<Toys::Utils::WrappableString>]
|
713
885
|
#
|
886
|
+
attr_reader :long_desc
|
887
|
+
|
888
|
+
##
|
889
|
+
# Returns the displayable name.
|
714
890
|
# @return [String]
|
715
891
|
#
|
716
|
-
|
717
|
-
|
892
|
+
attr_accessor :display_name
|
893
|
+
|
894
|
+
##
|
895
|
+
# Set the default.
|
896
|
+
# @param [Object] default The default value.
|
897
|
+
#
|
898
|
+
def default=(default)
|
899
|
+
@tool.default_data[@key] = default
|
718
900
|
end
|
719
901
|
|
720
902
|
##
|
721
|
-
#
|
903
|
+
# Set the short description string.
|
722
904
|
#
|
723
|
-
#
|
724
|
-
#
|
905
|
+
# The description may be provided as a {Toys::Utils::WrappableString}, a
|
906
|
+
# single string (which will be wrapped), or an array of strings, which
|
907
|
+
# will be interpreted as string fragments that will be concatenated and
|
908
|
+
# wrapped.
|
725
909
|
#
|
726
|
-
|
727
|
-
|
910
|
+
# @param [Toys::Utils::WrappableString,String,Array<String>] desc
|
911
|
+
#
|
912
|
+
def desc=(desc)
|
913
|
+
@desc = Tool.canonicalize_desc(desc)
|
914
|
+
end
|
915
|
+
|
916
|
+
##
|
917
|
+
# Set the long description strings.
|
918
|
+
#
|
919
|
+
# Each string may be provided as a {Toys::Utils::WrappableString}, a
|
920
|
+
# single string (which will be wrapped), or an array of strings, which
|
921
|
+
# will be interpreted as string fragments that will be concatenated and
|
922
|
+
# wrapped.
|
923
|
+
#
|
924
|
+
# @param [Array<Toys::Utils::WrappableString,String,Array<String>>] descs
|
925
|
+
#
|
926
|
+
def long_desc=(descs)
|
927
|
+
@long_desc = Tool.canonicalize_long_desc(descs)
|
928
|
+
end
|
929
|
+
|
930
|
+
##
|
931
|
+
# Set the long description strings.
|
932
|
+
#
|
933
|
+
# Each string may be provided as a {Toys::Utils::WrappableString}, a
|
934
|
+
# single string (which will be wrapped), or an array of strings, which
|
935
|
+
# will be interpreted as string fragments that will be concatenated and
|
936
|
+
# wrapped.
|
937
|
+
#
|
938
|
+
# @param [Toys::Utils::WrappableString,String,Array<String>...] descs
|
939
|
+
#
|
940
|
+
def populate_long_desc(*descs)
|
941
|
+
@long_desc = Tool.canonicalize_long_desc(descs)
|
942
|
+
self
|
728
943
|
end
|
729
944
|
|
730
945
|
##
|
@@ -736,19 +951,18 @@ module Toys
|
|
736
951
|
#
|
737
952
|
def process_value(input)
|
738
953
|
return input unless accept
|
739
|
-
n = canonical_name
|
740
954
|
result = input
|
741
955
|
optparse = ::OptionParser.new
|
742
|
-
optparse.on("
|
743
|
-
optparse.parse(["
|
956
|
+
optparse.on("--abc=VALUE", accept) { |v| result = v }
|
957
|
+
optparse.parse(["--abc", input])
|
744
958
|
result
|
745
959
|
end
|
746
960
|
end
|
747
961
|
|
748
962
|
private
|
749
963
|
|
750
|
-
def make_config_proc(middleware, next_config)
|
751
|
-
proc { middleware.config(self, &next_config) }
|
964
|
+
def make_config_proc(middleware, loader, next_config)
|
965
|
+
proc { middleware.config(self, loader, &next_config) }
|
752
966
|
end
|
753
967
|
|
754
968
|
def check_definition_state
|
@@ -759,23 +973,14 @@ module Toys
|
|
759
973
|
end
|
760
974
|
|
761
975
|
class << self
|
762
|
-
## @private
|
763
|
-
def canonical_switch(name)
|
764
|
-
name.to_s.downcase.tr("_", "-").gsub(/[^a-z0-9-]/, "")
|
765
|
-
end
|
766
|
-
|
767
976
|
## @private
|
768
977
|
def canonicalize_desc(desc)
|
769
|
-
|
770
|
-
d.is_a?(Utils::WrappableString) ? d : d.split("\n")
|
771
|
-
end.flatten.freeze
|
978
|
+
desc.is_a?(Utils::WrappableString) ? desc : Utils::WrappableString.new(desc)
|
772
979
|
end
|
773
980
|
|
774
981
|
## @private
|
775
|
-
def
|
776
|
-
|
777
|
-
s.is_a?(Utils::WrappableString) && !wrap_width.nil? ? s.wrap(wrap_width) : s.to_s
|
778
|
-
end.flatten
|
982
|
+
def canonicalize_long_desc(descs)
|
983
|
+
Array(descs).map { |desc| canonicalize_desc(desc) }.freeze
|
779
984
|
end
|
780
985
|
end
|
781
986
|
|
@@ -821,14 +1026,14 @@ module Toys
|
|
821
1026
|
|
822
1027
|
def create_option_parser
|
823
1028
|
optparse = ::OptionParser.new
|
824
|
-
# The following clears out the Officious (hidden default
|
1029
|
+
# The following clears out the Officious (hidden default flags).
|
825
1030
|
optparse.remove
|
826
1031
|
optparse.remove
|
827
1032
|
optparse.new
|
828
1033
|
optparse.new
|
829
|
-
@tool.
|
830
|
-
optparse.on(*
|
831
|
-
@data[
|
1034
|
+
@tool.flag_definitions.each do |flag|
|
1035
|
+
optparse.on(*flag.optparser_info) do |val|
|
1036
|
+
@data[flag.key] = flag.handler.call(val, @data[flag.key])
|
832
1037
|
end
|
833
1038
|
end
|
834
1039
|
optparse
|
@@ -837,7 +1042,7 @@ module Toys
|
|
837
1042
|
def parse_required_args(remaining, args)
|
838
1043
|
@tool.required_arg_definitions.each do |arg_info|
|
839
1044
|
if remaining.empty?
|
840
|
-
reason = "No value given for required argument
|
1045
|
+
reason = "No value given for required argument #{arg_info.display_name}"
|
841
1046
|
raise create_parse_error(args, reason)
|
842
1047
|
end
|
843
1048
|
@data[arg_info.key] = arg_info.process_value(remaining.shift)
|
@@ -887,7 +1092,7 @@ module Toys
|
|
887
1092
|
if @tool.includes_executor?
|
888
1093
|
context.instance_eval(&@tool.executor)
|
889
1094
|
else
|
890
|
-
context.logger.fatal("No implementation for #{@tool.display_name.inspect}")
|
1095
|
+
context.logger.fatal("No implementation for tool #{@tool.display_name.inspect}")
|
891
1096
|
context.exit(-1)
|
892
1097
|
end
|
893
1098
|
end
|