toys-core 0.3.5 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/toys/cli.rb +15 -10
- data/lib/toys/config_dsl.rb +103 -17
- data/lib/toys/context.rb +60 -48
- data/lib/toys/core_version.rb +1 -1
- data/lib/toys/helpers/exec.rb +1 -1
- data/lib/toys/helpers/highline.rb +4 -9
- data/lib/toys/middleware/add_verbosity_flags.rb +6 -6
- data/lib/toys/middleware/set_default_descriptions.rb +162 -92
- data/lib/toys/middleware/show_help.rb +12 -6
- data/lib/toys/middleware/{show_version.rb → show_root_version.rb} +14 -23
- data/lib/toys/tool.rb +122 -372
- data/lib/toys/tool/acceptor.rb +190 -0
- data/lib/toys/tool/arg_definition.rb +130 -0
- data/lib/toys/tool/flag_definition.rb +322 -0
- data/lib/toys/utils/exec.rb +1 -1
- data/lib/toys/utils/help_text.rb +21 -15
- data/lib/toys/utils/line_output.rb +29 -12
- data/lib/toys/utils/wrappable_string.rb +23 -0
- metadata +6 -3
@@ -33,11 +33,10 @@ require "toys/utils/line_output"
|
|
33
33
|
module Toys
|
34
34
|
module Middleware
|
35
35
|
##
|
36
|
-
# A middleware that displays a version string for
|
37
|
-
# `--version` flag is given.
|
38
|
-
# this flag, and the string that will be displayed.
|
36
|
+
# A middleware that displays a version string for the root tool if the
|
37
|
+
# `--version` flag is given.
|
39
38
|
#
|
40
|
-
class
|
39
|
+
class ShowRootVersion < Base
|
41
40
|
##
|
42
41
|
# Default version flags
|
43
42
|
# @return [Array<String>]
|
@@ -45,32 +44,27 @@ module Toys
|
|
45
44
|
DEFAULT_VERSION_FLAGS = ["--version"].freeze
|
46
45
|
|
47
46
|
##
|
48
|
-
#
|
49
|
-
#
|
47
|
+
# Default description for the version flags
|
48
|
+
# @return [String]
|
50
49
|
#
|
51
|
-
|
52
|
-
#
|
53
|
-
def self.root_version_displayer(version)
|
54
|
-
proc { |tool| tool.root? ? version : false }
|
55
|
-
end
|
50
|
+
DEFAULT_VERSION_FLAG_DESC = "Display the version".freeze
|
56
51
|
|
57
52
|
##
|
58
53
|
# Create a ShowVersion middleware
|
59
54
|
#
|
60
|
-
# @param [
|
61
|
-
# either the version string that should be displayed, or a falsy
|
62
|
-
# value to indicate the tool should not have a `--version` flag.
|
63
|
-
# Defaults to a "null" displayer that returns false for all tools.
|
55
|
+
# @param [String] version_string The string that should be displayed.
|
64
56
|
# @param [Array<String>] version_flags A list of flags that should
|
65
57
|
# trigger displaying the version. Default is
|
66
58
|
# {DEFAULT_VERSION_FLAGS}.
|
67
59
|
# @param [IO] stream Output stream to write to. Default is stdout.
|
68
60
|
#
|
69
|
-
def initialize(
|
61
|
+
def initialize(version_string: nil,
|
70
62
|
version_flags: DEFAULT_VERSION_FLAGS,
|
63
|
+
version_flag_desc: DEFAULT_VERSION_FLAG_DESC,
|
71
64
|
stream: $stdout)
|
72
|
-
@
|
65
|
+
@version_string = version_string
|
73
66
|
@version_flags = version_flags
|
67
|
+
@version_flag_desc = version_flag_desc
|
74
68
|
@output = Utils::LineOutput.new(stream)
|
75
69
|
end
|
76
70
|
|
@@ -78,12 +72,9 @@ module Toys
|
|
78
72
|
# Adds the version flag if requested.
|
79
73
|
#
|
80
74
|
def config(tool, _loader)
|
81
|
-
|
82
|
-
if version
|
75
|
+
if @version_string && tool.root?
|
83
76
|
tool.add_flag(:_show_version, @version_flags,
|
84
|
-
|
85
|
-
handler: ->(_val, _prev) { version },
|
86
|
-
only_unique: true)
|
77
|
+
report_collisions: false, desc: @version_flag_desc)
|
87
78
|
end
|
88
79
|
yield
|
89
80
|
end
|
@@ -93,7 +84,7 @@ module Toys
|
|
93
84
|
#
|
94
85
|
def execute(context)
|
95
86
|
if context[:_show_version]
|
96
|
-
@output.puts
|
87
|
+
@output.puts(@version_string)
|
97
88
|
else
|
98
89
|
yield
|
99
90
|
end
|
data/lib/toys/tool.rb
CHANGED
@@ -40,6 +40,27 @@ module Toys
|
|
40
40
|
# tool is executed.
|
41
41
|
#
|
42
42
|
class Tool
|
43
|
+
##
|
44
|
+
# Built-in acceptors (i.e. those recognized by OptionParser).
|
45
|
+
# You can reference these acceptors directly. Otherwise, you have to add
|
46
|
+
# one explicitly to the tool using {Tool#add_acceptor}.
|
47
|
+
#
|
48
|
+
OPTPARSER_ACCEPTORS = [
|
49
|
+
::Object,
|
50
|
+
::NilClass,
|
51
|
+
::String,
|
52
|
+
::Integer,
|
53
|
+
::Float,
|
54
|
+
::Numeric,
|
55
|
+
::TrueClass,
|
56
|
+
::FalseClass,
|
57
|
+
::Array,
|
58
|
+
::Regexp,
|
59
|
+
::OptionParser::DecimalInteger,
|
60
|
+
::OptionParser::OctalInteger,
|
61
|
+
::OptionParser::DecimalNumeric
|
62
|
+
].freeze
|
63
|
+
|
43
64
|
##
|
44
65
|
# Create a new tool.
|
45
66
|
#
|
@@ -56,6 +77,10 @@ module Toys
|
|
56
77
|
@long_desc = []
|
57
78
|
|
58
79
|
@default_data = {}
|
80
|
+
@acceptors = {}
|
81
|
+
OPTPARSER_ACCEPTORS.each { |a| @acceptors[a] = a }
|
82
|
+
@used_flags = []
|
83
|
+
|
59
84
|
@flag_definitions = []
|
60
85
|
@required_arg_definitions = []
|
61
86
|
@optional_arg_definitions = []
|
@@ -110,6 +135,12 @@ module Toys
|
|
110
135
|
#
|
111
136
|
attr_reader :remaining_args_definition
|
112
137
|
|
138
|
+
##
|
139
|
+
# Return a list of flags that have been used in the flag definitions.
|
140
|
+
# @return [Array<String>]
|
141
|
+
#
|
142
|
+
attr_reader :used_flags
|
143
|
+
|
113
144
|
##
|
114
145
|
# Return the default argument data.
|
115
146
|
# @return [Hash]
|
@@ -234,11 +265,18 @@ module Toys
|
|
234
265
|
end
|
235
266
|
|
236
267
|
##
|
237
|
-
# Returns a list of
|
238
|
-
# @return [Array<
|
268
|
+
# Returns a list of all custom acceptors used by this tool.
|
269
|
+
# @return [Array<Toys::Tool::Acceptor>]
|
239
270
|
#
|
240
|
-
def
|
241
|
-
|
271
|
+
def custom_acceptors
|
272
|
+
result = []
|
273
|
+
flag_definitions.each do |f|
|
274
|
+
result << f.accept if f.accept.is_a?(Acceptor)
|
275
|
+
end
|
276
|
+
arg_definitions.each do |a|
|
277
|
+
result << a.accept if a.accept.is_a?(Acceptor)
|
278
|
+
end
|
279
|
+
result.uniq
|
242
280
|
end
|
243
281
|
|
244
282
|
##
|
@@ -268,7 +306,7 @@ module Toys
|
|
268
306
|
#
|
269
307
|
def desc=(desc)
|
270
308
|
check_definition_state
|
271
|
-
@desc =
|
309
|
+
@desc = Utils::WrappableString.make(desc)
|
272
310
|
end
|
273
311
|
|
274
312
|
##
|
@@ -282,22 +320,7 @@ module Toys
|
|
282
320
|
#
|
283
321
|
def long_desc=(descs)
|
284
322
|
check_definition_state
|
285
|
-
@long_desc =
|
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
|
323
|
+
@long_desc = Utils::WrappableString.make_array(descs)
|
301
324
|
end
|
302
325
|
|
303
326
|
##
|
@@ -340,6 +363,17 @@ module Toys
|
|
340
363
|
self
|
341
364
|
end
|
342
365
|
|
366
|
+
##
|
367
|
+
# Add an acceptor to the tool. This acceptor may be refereneced by name
|
368
|
+
# when adding a flag or an arg.
|
369
|
+
#
|
370
|
+
# @param [Toys::Tool::Acceptor] acceptor The acceptor to add.
|
371
|
+
#
|
372
|
+
def add_acceptor(acceptor)
|
373
|
+
@acceptors[acceptor.name] = acceptor
|
374
|
+
self
|
375
|
+
end
|
376
|
+
|
343
377
|
##
|
344
378
|
# Add a flag to the current tool. Each flag must specify a key which
|
345
379
|
# the script may use to obtain the flag value from the context.
|
@@ -348,38 +382,60 @@ module Toys
|
|
348
382
|
# @param [Symbol] key The key to use to retrieve the value from the
|
349
383
|
# execution context.
|
350
384
|
# @param [Array<String>] flags The flags in OptionParser format.
|
351
|
-
# @param [Object
|
385
|
+
# @param [Object] accept An acceptor that validates and/or converts the
|
386
|
+
# value. You may provide either the name of an acceptor you have
|
387
|
+
# defined, or one of the default acceptors provided by OptionParser.
|
388
|
+
# Optional. If not specified, accepts any value as a string.
|
352
389
|
# @param [Object] default The default value. This is the value that will
|
353
390
|
# be set in the context if this flag is not provided on the command
|
354
391
|
# line. Defaults to `nil`.
|
392
|
+
# @param [Proc,nil] handler An optional handler for setting/updating the
|
393
|
+
# value. If given, it should take two arguments, the new given value
|
394
|
+
# and the previous value, and it should return the new value that
|
395
|
+
# should be set. The default handler simply replaces the previous
|
396
|
+
# value. i.e. the default is effectively `-> (val, _prev) { val }`.
|
397
|
+
# @param [Boolean] report_collisions Raise an exception if a flag is
|
398
|
+
# requested that is already in use or marked as disabled. Default is
|
399
|
+
# true.
|
355
400
|
# @param [String,Array<String>,Toys::Utils::WrappableString] desc Short
|
356
401
|
# description for the flag. See {Toys::Tool#desc=} for a description of
|
357
402
|
# allowed formats. Defaults to the empty string.
|
358
403
|
# @param [Array<String,Array<String>,Toys::Utils::WrappableString>] long_desc
|
359
404
|
# Long description for the flag. See {Toys::Tool#long_desc=} for a
|
360
405
|
# description of allowed formats. Defaults to the 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.
|
365
|
-
# Defaults to false.
|
366
|
-
# @param [Proc,nil] handler An optional handler for setting/updating the
|
367
|
-
# value. If given, it should take two arguments, the new given value
|
368
|
-
# and the previous value, and it should return the new value that
|
369
|
-
# should be set. The default handler simply replaces the previous
|
370
|
-
# value. i.e. the default is effectively `-> (val, _prev) { val }`.
|
371
406
|
#
|
372
407
|
def add_flag(key, flags = [],
|
373
|
-
accept: nil, default: nil, handler: nil,
|
374
|
-
|
408
|
+
accept: nil, default: nil, handler: nil,
|
409
|
+
report_collisions: true,
|
410
|
+
desc: nil, long_desc: nil)
|
375
411
|
check_definition_state
|
376
|
-
|
377
|
-
flag_def.
|
412
|
+
accept = resolve_acceptor(accept)
|
413
|
+
flag_def = FlagDefinition.new(key, flags, @used_flags, report_collisions,
|
414
|
+
accept, handler, default)
|
415
|
+
flag_def.desc = desc if desc
|
416
|
+
flag_def.long_desc = long_desc if long_desc
|
378
417
|
@flag_definitions << flag_def if flag_def.active?
|
379
418
|
@default_data[key] = default
|
380
419
|
self
|
381
420
|
end
|
382
421
|
|
422
|
+
##
|
423
|
+
# Mark one or more flags as disabled, preventing their use by any
|
424
|
+
# subsequent flag definition. This may be used to prevent middleware from
|
425
|
+
# defining a particular flag.
|
426
|
+
#
|
427
|
+
# @param [String...] flags The flags to disable
|
428
|
+
#
|
429
|
+
def disable_flag(*flags)
|
430
|
+
flags = flags.uniq
|
431
|
+
intersection = @used_flags & flags
|
432
|
+
unless intersection.empty?
|
433
|
+
raise ToolDefinitionError, "Cannot disable flags already used: #{intersection.inspect}"
|
434
|
+
end
|
435
|
+
@used_flags.concat(flags)
|
436
|
+
self
|
437
|
+
end
|
438
|
+
|
383
439
|
##
|
384
440
|
# Add a required positional argument to the current tool. You must specify
|
385
441
|
# a key which the script may use to obtain the argument value from the
|
@@ -387,7 +443,10 @@ module Toys
|
|
387
443
|
#
|
388
444
|
# @param [Symbol] key The key to use to retrieve the value from the
|
389
445
|
# execution context.
|
390
|
-
# @param [Object
|
446
|
+
# @param [Object] accept An acceptor that validates and/or converts the
|
447
|
+
# value. You may provide either the name of an acceptor you have
|
448
|
+
# defined, or one of the default acceptors provided by OptionParser.
|
449
|
+
# Optional. If not specified, accepts any value as a string.
|
391
450
|
# @param [String] display_name A name to use for display (in help text and
|
392
451
|
# error reports). Defaults to the key in upper case.
|
393
452
|
# @param [String,Array<String>,Toys::Utils::WrappableString] desc Short
|
@@ -399,7 +458,8 @@ module Toys
|
|
399
458
|
#
|
400
459
|
def add_required_arg(key, accept: nil, display_name: nil, desc: nil, long_desc: nil)
|
401
460
|
check_definition_state
|
402
|
-
|
461
|
+
accept = resolve_acceptor(accept)
|
462
|
+
arg_def = ArgDefinition.new(key, :required, accept, nil, desc, long_desc, display_name)
|
403
463
|
@required_arg_definitions << arg_def
|
404
464
|
self
|
405
465
|
end
|
@@ -415,7 +475,10 @@ module Toys
|
|
415
475
|
# @param [Object] default The default value. This is the value that will
|
416
476
|
# be set in the context if this argument is not provided on the command
|
417
477
|
# line. Defaults to `nil`.
|
418
|
-
# @param [Object
|
478
|
+
# @param [Object] accept An acceptor that validates and/or converts the
|
479
|
+
# value. You may provide either the name of an acceptor you have
|
480
|
+
# defined, or one of the default acceptors provided by OptionParser.
|
481
|
+
# Optional. If not specified, accepts any value as a string.
|
419
482
|
# @param [String] display_name A name to use for display (in help text and
|
420
483
|
# error reports). Defaults to the key in upper case.
|
421
484
|
# @param [String,Array<String>,Toys::Utils::WrappableString] desc Short
|
@@ -428,7 +491,8 @@ module Toys
|
|
428
491
|
def add_optional_arg(key, default: nil, accept: nil, display_name: nil,
|
429
492
|
desc: nil, long_desc: nil)
|
430
493
|
check_definition_state
|
431
|
-
|
494
|
+
accept = resolve_acceptor(accept)
|
495
|
+
arg_def = ArgDefinition.new(key, :optional, accept, default, desc, long_desc, display_name)
|
432
496
|
@optional_arg_definitions << arg_def
|
433
497
|
@default_data[key] = default
|
434
498
|
self
|
@@ -444,7 +508,10 @@ module Toys
|
|
444
508
|
# @param [Object] default The default value. This is the value that will
|
445
509
|
# be set in the context if no unmatched arguments are provided on the
|
446
510
|
# command line. Defaults to the empty array `[]`.
|
447
|
-
# @param [Object
|
511
|
+
# @param [Object] accept An acceptor that validates and/or converts the
|
512
|
+
# value. You may provide either the name of an acceptor you have
|
513
|
+
# defined, or one of the default acceptors provided by OptionParser.
|
514
|
+
# Optional. If not specified, accepts any value as a string.
|
448
515
|
# @param [String] display_name A name to use for display (in help text and
|
449
516
|
# error reports). Defaults to the key in upper case.
|
450
517
|
# @param [String,Array<String>,Toys::Utils::WrappableString] desc Short
|
@@ -457,7 +524,8 @@ module Toys
|
|
457
524
|
def set_remaining_args(key, default: [], accept: nil, display_name: nil,
|
458
525
|
desc: nil, long_desc: nil)
|
459
526
|
check_definition_state
|
460
|
-
|
527
|
+
accept = resolve_acceptor(accept)
|
528
|
+
arg_def = ArgDefinition.new(key, :remaining, accept, default, desc, long_desc, display_name)
|
461
529
|
@remaining_args_definition = arg_def
|
462
530
|
@default_data[key] = default
|
463
531
|
self
|
@@ -513,327 +581,6 @@ module Toys
|
|
513
581
|
self
|
514
582
|
end
|
515
583
|
|
516
|
-
##
|
517
|
-
# Representation of a single flag
|
518
|
-
#
|
519
|
-
class FlagSyntax
|
520
|
-
##
|
521
|
-
# Parse flag syntax
|
522
|
-
# @param [String] str syntax.
|
523
|
-
#
|
524
|
-
def initialize(str)
|
525
|
-
if str =~ /^(-[\?\w])(\s?(\w+))?$/
|
526
|
-
setup(str, [$1], $1, "-", " ", $3)
|
527
|
-
elsif str =~ /^--\[no-\](\w[\?\w-]*)$/
|
528
|
-
setup(str, ["--#{$1}", "--no-#{$1}"], "--[no-]#{$1}", "--", nil, nil)
|
529
|
-
elsif str =~ /^(--\w[\?\w-]*)(([=\s])(\w+))?$/
|
530
|
-
setup(str, [$1], $1, "--", $3, $4)
|
531
|
-
else
|
532
|
-
raise ToolDefinitionError, "Illegal flag: #{str.inspect}"
|
533
|
-
end
|
534
|
-
end
|
535
|
-
|
536
|
-
attr_reader :original_str
|
537
|
-
attr_reader :str_without_value
|
538
|
-
attr_reader :flags
|
539
|
-
attr_reader :flag_style
|
540
|
-
attr_reader :value_delim
|
541
|
-
attr_reader :value_label
|
542
|
-
|
543
|
-
private
|
544
|
-
|
545
|
-
def setup(original_str, flags, str_without_value, flag_style, value_delim, value_label)
|
546
|
-
@original_str = original_str
|
547
|
-
@flags = flags
|
548
|
-
@str_without_value = str_without_value
|
549
|
-
@flag_style = flag_style
|
550
|
-
@value_delim = value_delim
|
551
|
-
@value_label = value_label ? value_label.upcase : value_label
|
552
|
-
end
|
553
|
-
end
|
554
|
-
|
555
|
-
##
|
556
|
-
# Representation of a formal set of flags.
|
557
|
-
#
|
558
|
-
class FlagDefinition
|
559
|
-
##
|
560
|
-
# The default handler replaces the previous value.
|
561
|
-
# @return [Proc]
|
562
|
-
#
|
563
|
-
DEFAULT_HANDLER = ->(val, _prev) { val }
|
564
|
-
|
565
|
-
##
|
566
|
-
# Create a FlagDefinition
|
567
|
-
# @private
|
568
|
-
#
|
569
|
-
# @param [Symbol] key This flag will set the given context key.
|
570
|
-
#
|
571
|
-
def initialize(key, flags, accept, handler, desc, long_desc, default)
|
572
|
-
@key = key
|
573
|
-
@flag_syntax = flags.map { |s| FlagSyntax.new(s) }
|
574
|
-
@accept = accept
|
575
|
-
@handler = handler || DEFAULT_HANDLER
|
576
|
-
@desc = Tool.canonicalize_desc(desc)
|
577
|
-
@long_desc = Tool.canonicalize_long_desc(long_desc)
|
578
|
-
@needs_val = !@accept.nil? ||
|
579
|
-
(!default.nil? && default != true && default != false)
|
580
|
-
create_default_flag_if_needed
|
581
|
-
reset_data
|
582
|
-
end
|
583
|
-
|
584
|
-
##
|
585
|
-
# Returns the key.
|
586
|
-
# @return [Symbol]
|
587
|
-
#
|
588
|
-
attr_reader :key
|
589
|
-
|
590
|
-
##
|
591
|
-
# Returns an array of FlagSyntax for the flags.
|
592
|
-
# @return [Array<FlagSyntax>]
|
593
|
-
#
|
594
|
-
attr_reader :flag_syntax
|
595
|
-
|
596
|
-
##
|
597
|
-
# Returns the acceptor, which may be `nil`.
|
598
|
-
# @return [Object]
|
599
|
-
#
|
600
|
-
attr_reader :accept
|
601
|
-
|
602
|
-
##
|
603
|
-
# Returns the short description string.
|
604
|
-
# @return [Toys::Utils::WrappableString]
|
605
|
-
#
|
606
|
-
attr_reader :desc
|
607
|
-
|
608
|
-
##
|
609
|
-
# Returns the long description strings as an array.
|
610
|
-
# @return [Array<Toys::Utils::WrappableString>]
|
611
|
-
#
|
612
|
-
attr_reader :long_desc
|
613
|
-
|
614
|
-
##
|
615
|
-
# Returns the handler for setting/updating the value.
|
616
|
-
# @return [Proc]
|
617
|
-
#
|
618
|
-
attr_reader :handler
|
619
|
-
|
620
|
-
##
|
621
|
-
# Returns an array of FlagSyntax including only single-dash flags
|
622
|
-
# @return [Array<FlagSyntax>]
|
623
|
-
#
|
624
|
-
def single_flag_syntax
|
625
|
-
@single_flag_syntax ||= flag_syntax.find_all { |ss| ss.flag_style == "-" }
|
626
|
-
end
|
627
|
-
|
628
|
-
##
|
629
|
-
# Returns an array of FlagSyntax including only double-dash flags
|
630
|
-
# @return [Array<FlagSyntax>]
|
631
|
-
#
|
632
|
-
def double_flag_syntax
|
633
|
-
@double_flag_syntax ||= flag_syntax.find_all { |ss| ss.flag_style == "--" }
|
634
|
-
end
|
635
|
-
|
636
|
-
##
|
637
|
-
# Returns the list of effective flags used.
|
638
|
-
# @return [Array<String>]
|
639
|
-
#
|
640
|
-
def effective_flags
|
641
|
-
@effective_flags ||= flag_syntax.map(&:flags).flatten
|
642
|
-
end
|
643
|
-
|
644
|
-
##
|
645
|
-
# All optparser flags and acceptor if present
|
646
|
-
# @return [Array]
|
647
|
-
#
|
648
|
-
def optparser_info
|
649
|
-
@optparser_info ||= begin
|
650
|
-
flags = flag_syntax.map do |fs|
|
651
|
-
f = fs.str_without_value
|
652
|
-
f = "#{f} #{value_label}" if value_label
|
653
|
-
f
|
654
|
-
end
|
655
|
-
flags + Array(accept)
|
656
|
-
end
|
657
|
-
end
|
658
|
-
|
659
|
-
##
|
660
|
-
# Returns true if this flag is active. That is, it has a nonempty
|
661
|
-
# flags list.
|
662
|
-
# @return [Boolean]
|
663
|
-
#
|
664
|
-
def active?
|
665
|
-
!effective_flags.empty?
|
666
|
-
end
|
667
|
-
|
668
|
-
##
|
669
|
-
# Return the value label if one exists
|
670
|
-
# @return [String,nil]
|
671
|
-
#
|
672
|
-
def value_label
|
673
|
-
find_canonical_value_label
|
674
|
-
@value_label
|
675
|
-
end
|
676
|
-
|
677
|
-
##
|
678
|
-
# Return the value delimiter if one exists
|
679
|
-
# @return [String,nil]
|
680
|
-
#
|
681
|
-
def value_delim
|
682
|
-
find_canonical_value_label
|
683
|
-
@value_delim
|
684
|
-
end
|
685
|
-
|
686
|
-
##
|
687
|
-
# Set description
|
688
|
-
# @param [String,Array<String>,Toys::Utils::WrappableString] desc
|
689
|
-
#
|
690
|
-
def desc=(desc)
|
691
|
-
@desc = Tool.canonicalize_desc(desc)
|
692
|
-
end
|
693
|
-
|
694
|
-
##
|
695
|
-
# Set long description
|
696
|
-
# @param [Array<String,Array<String>,Toys::Utils::WrappableString>] long_desc
|
697
|
-
#
|
698
|
-
def long_desc=(long_desc)
|
699
|
-
@long_desc = Tool.canonicalize_long_desc(long_desc)
|
700
|
-
end
|
701
|
-
|
702
|
-
## @private
|
703
|
-
def remove_flags(flags)
|
704
|
-
flags = flags.map { |f| FlagSyntax.new(f).flags }.flatten
|
705
|
-
@flag_syntax.select! do |ss|
|
706
|
-
ss.flags.all? { |s| !flags.include?(s) }
|
707
|
-
end
|
708
|
-
reset_data
|
709
|
-
end
|
710
|
-
|
711
|
-
private
|
712
|
-
|
713
|
-
def reset_data
|
714
|
-
@effective_flags = nil
|
715
|
-
@optparser_info = nil
|
716
|
-
@single_flag_syntax = nil
|
717
|
-
@double_flag_syntax = nil
|
718
|
-
@value_label = nil
|
719
|
-
@value_delim = nil
|
720
|
-
end
|
721
|
-
|
722
|
-
def create_default_flag_if_needed
|
723
|
-
return unless @flag_syntax.empty?
|
724
|
-
canonical_flag = key.to_s.downcase.tr("_", "-").gsub(/[^a-z0-9-]/, "").sub(/^-+/, "")
|
725
|
-
unless canonical_flag.empty?
|
726
|
-
flag = @needs_val ? "--#{canonical_flag}=VALUE" : "--#{canonical_flag}"
|
727
|
-
@flag_syntax << FlagSyntax.new(flag)
|
728
|
-
end
|
729
|
-
end
|
730
|
-
|
731
|
-
def find_canonical_value_label
|
732
|
-
return if @value_delim
|
733
|
-
@value_label = @needs_val ? "VALUE" : nil
|
734
|
-
@value_delim = @needs_val ? " " : ""
|
735
|
-
single_flag_syntax.each do |ss|
|
736
|
-
next unless ss.value_label
|
737
|
-
@value_label = ss.value_label
|
738
|
-
@value_delim = ss.value_delim
|
739
|
-
end
|
740
|
-
double_flag_syntax.each do |ss|
|
741
|
-
next unless ss.value_label
|
742
|
-
@value_label = ss.value_label
|
743
|
-
@value_delim = ss.value_delim
|
744
|
-
end
|
745
|
-
end
|
746
|
-
end
|
747
|
-
|
748
|
-
##
|
749
|
-
# Representation of a formal positional argument
|
750
|
-
#
|
751
|
-
class ArgDefinition
|
752
|
-
##
|
753
|
-
# Create an ArgDefinition
|
754
|
-
# @private
|
755
|
-
#
|
756
|
-
# @param [Symbol] key This argument will set the given context key.
|
757
|
-
# @param [:required,:optional,:remaining] type Type of this argument
|
758
|
-
#
|
759
|
-
def initialize(key, type, accept, desc, long_desc, display_name)
|
760
|
-
@key = key
|
761
|
-
@type = type
|
762
|
-
@accept = accept
|
763
|
-
@desc = Tool.canonicalize_desc(desc)
|
764
|
-
@long_desc = Tool.canonicalize_long_desc(long_desc)
|
765
|
-
@display_name = display_name || key.to_s.tr("-", "_").gsub(/\W/, "").upcase
|
766
|
-
end
|
767
|
-
|
768
|
-
##
|
769
|
-
# Returns the key.
|
770
|
-
# @return [Symbol]
|
771
|
-
#
|
772
|
-
attr_reader :key
|
773
|
-
|
774
|
-
##
|
775
|
-
# Type of this argument.
|
776
|
-
# @return [:required,:optional,:remaining]
|
777
|
-
#
|
778
|
-
attr_reader :type
|
779
|
-
|
780
|
-
##
|
781
|
-
# Returns the acceptor, which may be `nil`.
|
782
|
-
# @return [Object]
|
783
|
-
#
|
784
|
-
attr_accessor :accept
|
785
|
-
|
786
|
-
##
|
787
|
-
# Returns the short description string.
|
788
|
-
# @return [Toys::Utils::WrappableString]
|
789
|
-
#
|
790
|
-
attr_reader :desc
|
791
|
-
|
792
|
-
##
|
793
|
-
# Returns the long description strings as an array.
|
794
|
-
# @return [Array<Toys::Utils::WrappableString>]
|
795
|
-
#
|
796
|
-
attr_reader :long_desc
|
797
|
-
|
798
|
-
##
|
799
|
-
# Returns the displayable name.
|
800
|
-
# @return [String]
|
801
|
-
#
|
802
|
-
attr_accessor :display_name
|
803
|
-
|
804
|
-
##
|
805
|
-
# Process the given value through the acceptor.
|
806
|
-
# May raise an exception if the acceptor rejected the input.
|
807
|
-
#
|
808
|
-
# @param [String] input Input value
|
809
|
-
# @return [Object] Accepted value
|
810
|
-
#
|
811
|
-
def process_value(input)
|
812
|
-
return input unless accept
|
813
|
-
result = input
|
814
|
-
optparse = ::OptionParser.new
|
815
|
-
optparse.on("--abc=VALUE", accept) { |v| result = v }
|
816
|
-
optparse.parse(["--abc", input])
|
817
|
-
result
|
818
|
-
end
|
819
|
-
|
820
|
-
##
|
821
|
-
# Set description
|
822
|
-
# @param [String,Array<String>,Toys::Utils::WrappableString] desc
|
823
|
-
#
|
824
|
-
def desc=(desc)
|
825
|
-
@desc = Tool.canonicalize_desc(desc)
|
826
|
-
end
|
827
|
-
|
828
|
-
##
|
829
|
-
# Set long description
|
830
|
-
# @param [Array<String,Array<String>,Toys::Utils::WrappableString>] long_desc
|
831
|
-
#
|
832
|
-
def long_desc=(long_desc)
|
833
|
-
@long_desc = Tool.canonicalize_long_desc(long_desc)
|
834
|
-
end
|
835
|
-
end
|
836
|
-
|
837
584
|
private
|
838
585
|
|
839
586
|
def make_config_proc(middleware, loader, next_config)
|
@@ -847,16 +594,12 @@ module Toys
|
|
847
594
|
end
|
848
595
|
end
|
849
596
|
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
end
|
855
|
-
|
856
|
-
## @private
|
857
|
-
def canonicalize_long_desc(descs)
|
858
|
-
Array(descs).map { |desc| canonicalize_desc(desc) }.freeze
|
597
|
+
def resolve_acceptor(accept)
|
598
|
+
return accept if accept.nil? || accept.is_a?(Acceptor)
|
599
|
+
unless @acceptors.key?(accept)
|
600
|
+
raise ToolDefinitionError, "Unknown acceptor: #{accept.inspect}"
|
859
601
|
end
|
602
|
+
@acceptors[accept]
|
860
603
|
end
|
861
604
|
|
862
605
|
##
|
@@ -911,6 +654,9 @@ module Toys
|
|
911
654
|
@data[flag.key] = flag.handler.call(val, @data[flag.key])
|
912
655
|
end
|
913
656
|
end
|
657
|
+
@tool.custom_acceptors do |accept|
|
658
|
+
optparse.accept(accept)
|
659
|
+
end
|
914
660
|
optparse
|
915
661
|
end
|
916
662
|
|
@@ -986,3 +732,7 @@ module Toys
|
|
986
732
|
end
|
987
733
|
end
|
988
734
|
end
|
735
|
+
|
736
|
+
require "toys/tool/acceptor"
|
737
|
+
require "toys/tool/arg_definition"
|
738
|
+
require "toys/tool/flag_definition"
|