class Rake::ToolkitProgram::CommandOptionParser
Constants
- IDENTITY
- RUBY_GTE_2_4
Attributes
Public Class Methods
# File lib/rake/toolkit_program/command_option_parser.rb, line 30 def initialize(arg_dest) super() @argument_destination = arg_dest @positional_mapper = IDENTITY end
Public Instance Methods
Explicitly define capture of positional (non-option) arguments
When parsing into a Hash, the default is to store the Array of remaining positional arguments in the nil
key. This method overrides that behavior by either specifying a specific key to use or by specifying a block to call with the positional arguments, which is much more useful when accumulating arguments to a non-Hash object. Passing key
or a block are mutually exclusive.
precapture_dest_array
can be set to true
to cause the capture to take place before the positional arguments are accumulated. In this case, the Array object yielded to the block (if this method is called with a block) must be stored, as it will be the recipient of all positional arguments. In any case, when this option is passed to this method, capture behavior for the (empty) Array into which the positional arguments will be stored is carried out before option parsing, and values are (after any transformation dictated by map_positional_args
) stored in the positional arguments Array; there is no option to store positionals for consumption by the command task code in anything other than an Array. Note that the Array into which arguments are captured is not the same array either passed to or returned from the parse!
(or parse, for that matter) method.
If multiple calls to this method are made, the last one is the one that defines the behavior.
key
-
Key under which positionals shall be accumulated in a Hash
precapture_dest_array
-
Capture before argument accumulation
# File lib/rake/toolkit_program/command_option_parser.rb, line 165 def capture_positionals(key=nil, precapture_dest_array: false, &blk) if blk && !key.nil? raise ArgumentError, "either specify key or block" end @positionals_key = key @positionals_capture = blk @precapture_positionals_array = precapture_dest_array end
Constrain the number of positional arguments
This is a declarative way of expressing how many positional (i.e. non-option) arguments should be accepted by the command. The === (i.e. “case match”) method of cardinality_test
is used to test the length of the positional argument Array, raising Rake::ToolkitProgram::WrongArgumentCount
if === returns false.
A special case exists when cardinality_test
is a Symbol: because a Symbol could never match an Integer, Symbol#to_proc is called to create a useful test.
NOTE It is worth attention that Proc#=== is an alias for Proc#call, so the operator argument is passed to the Proc. This enables arbitrary computation for the validity of the positional argument count, syntactically aided by the “stabby-lambda” notation.
While this gem will do its best to explain the argument cardinality, explanation
provides an opportunity to explicitly provide a sentence to be included in the help about the allowed cardinality (i.e. count) of positional arguments.
# File lib/rake/toolkit_program/command_option_parser.rb, line 197 def expect_positional_cardinality(cardinality_test, explanation=nil) @positional_cardinality_explanation = explanation if cardinality_test.kind_of?(Symbol) cardinality_test.to_s.tap do |test_name| if explanation.nil? && test_name.end_with?('?') @positional_cardinality_explanation = ( "Positional argument count must be #{test_name[0..-2].gsub('_', ' ')}." ) end end cardinality_test = cardinality_test.to_proc end @positional_cardinality_test = cardinality_test end
Convenience method for raising Rake::ToolkitProgram::InvalidCommandLine
The error raised is the standard error for an invalid command line when using Rake::ToolkitProgram
.
# File lib/rake/toolkit_program/command_option_parser.rb, line 228 def invalid_args!(message) raise InvalidCommandLine, message end
Define a mapping function for positional arguments during accumulation
The block given to this method will be called with each positional argument in turn; the return value of the block will be acculumated as the positional argument. The block's computation may be purely functional or it may refer to outside factors in its binding such as accumulated values for options or preceding positional arguments.
# File lib/rake/toolkit_program/command_option_parser.rb, line 241 def map_positional_args(&blk) raise ArgumentError, "block required" if blk.nil? @positional_mapper = blk end
Disallow positional arguments
The command will raise Rake::ToolkitProgram::WrongArgumentCount
if any positional arguments are given.
# File lib/rake/toolkit_program/command_option_parser.rb, line 218 def no_positional_args! expect_positional_cardinality(0) end
# File lib/rake/toolkit_program/command_option_parser.rb, line 40 def order!(argv = default_argv, into: nil, &nonopt) super(argv, into: into) do |arg| nonopt.call(@positional_mapper.call(arg)) end end
Method override, see OptionParser#parse! – though we don't do POSIXLY_COMPLIANT
# File lib/rake/toolkit_program/command_option_parser.rb, line 55 def parse!(argv = default_argv, into: nil) positionals = [] do_positional_capture(positionals) if @precapture_positionals_array order!(argv, into: into, &positionals.method(:<<)).tap do argv[0, 0] = positionals do_positional_capture(argv) if !@precapture_positionals_array unless positional_cardinality_ok?(positionals.length) raise WrongArgumentCount.new( @positional_cardinality_test, positionals.length ) end end return argv end
True unless positional arguments have been prohibited
Technically, this test can only check that the established cardinality test is for 0, given as an Integer. If the test established by expect_positional_cardinality
is a Proc that only returns true for 0 or the Range 0..0
, this method will report incorrect results.
# File lib/rake/toolkit_program/command_option_parser.rb, line 93 def positional_arguments_allowed? @positional_cardinality_test != 0 end
Return the established test for positional cardinality (or nil)
If a test has been established by expect_positional_cardinality
, this method returns that test. Otherwise, it returns nil.
# File lib/rake/toolkit_program/command_option_parser.rb, line 103 def positional_cardinality @positional_cardinality_test end
String explanation of the positional cardinality, for help
# File lib/rake/toolkit_program/command_option_parser.rb, line 110 def positional_cardinality_explanation @positional_cardinality_explanation.tap do |explicit| return explicit if explicit end obscure_answer = "A rule exists about the number of positional arguments." case (pc_test = @positional_cardinality_test) when nil, 0 then nil when 1 then "Requires 1 positional argument." when Integer then "Requires #{pc_test} positional arguments." when Range then "Requires #{pc_test.to_inclusive} (inclusive) positional arguments." when Proc then begin [pc_test.call(:explain)].map do |exp| case exp when String then exp else obscure_answer end end[0] rescue StandardError obscure_answer end else obscure_answer end end
Query whether a given number of positional arguments is acceptable
The result is based on the test established by expect_positional_cardinality
, and returns true if no such test has been established.
# File lib/rake/toolkit_program/command_option_parser.rb, line 79 def positional_cardinality_ok?(n) pc_test = @positional_cardinality_test !pc_test || pc_test === n end
Private Instance Methods
# File lib/rake/toolkit_program/command_option_parser.rb, line 247 def do_positional_capture(positionals) if @positionals_capture @positionals_capture.call(positionals) elsif argument_destination.kind_of?(Hash) argument_destination[@positionals_key] = positionals end end