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.
@@ -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"