toys-core 0.3.5 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 certain tools if the
37
- # `--version` flag is given. You can specify which tools respond to
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 ShowVersion < Base
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
- # Return a simple version displayer that returns the given string for
49
- # the root tool.
47
+ # Default description for the version flags
48
+ # @return [String]
50
49
  #
51
- # @return [Proc]
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 [Proc] version_displayer A proc that takes a tool and returns
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(version_displayer: nil,
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
- @version_displayer = version_displayer || proc { |_| false }
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
- version = @version_displayer.call(tool)
82
- if version
75
+ if @version_string && tool.root?
83
76
  tool.add_flag(:_show_version, @version_flags,
84
- desc: "Display the version",
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 context[:_show_version]
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 flags used by this tool.
238
- # @return [Array<String>]
268
+ # Returns a list of all custom acceptors used by this tool.
269
+ # @return [Array<Toys::Tool::Acceptor>]
239
270
  #
240
- def used_flags
241
- flag_definitions.reduce([]) { |used, fdef| used + fdef.effective_flags }.uniq
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 = Tool.canonicalize_desc(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 = 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
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,nil] accept An OptionParser acceptor. Optional.
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, desc: nil, long_desc: nil,
374
- only_unique: false)
408
+ accept: nil, default: nil, handler: nil,
409
+ report_collisions: true,
410
+ desc: nil, long_desc: nil)
375
411
  check_definition_state
376
- flag_def = FlagDefinition.new(key, flags, accept, handler, desc, long_desc, default)
377
- flag_def.remove_flags(used_flags) if only_unique
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,nil] accept An OptionParser acceptor. Optional.
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
- arg_def = ArgDefinition.new(key, :required, accept, desc, long_desc, display_name)
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,nil] accept An OptionParser acceptor. Optional.
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
- arg_def = ArgDefinition.new(key, :optional, accept, desc, long_desc, display_name)
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,nil] accept An OptionParser acceptor. Optional.
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
- arg_def = ArgDefinition.new(key, :remaining, accept, desc, long_desc, display_name)
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
- class << self
851
- ## @private
852
- def canonicalize_desc(desc)
853
- desc.is_a?(Utils::WrappableString) ? desc : Utils::WrappableString.new(desc)
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"