class Rake::ToolkitProgram::CommandOptionParser

Constants

IDENTITY
RUBY_GTE_2_4

Attributes

argument_destination[R]

Public Class Methods

new(arg_dest) click to toggle source
Calls superclass method
# 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

capture_positionals(key=nil, precapture_dest_array: false, &blk) click to toggle source

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
expect_positional_cardinality(cardinality_test, explanation=nil) click to toggle source

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
invalid_args!(message) click to toggle source

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
map_positional_args(&blk) click to toggle source

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
no_positional_args!() click to toggle source

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
order!(argv = default_argv, into: nil, &nonopt) click to toggle source
Calls superclass method
# 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
parse!(argv = default_argv, into: nil) click to toggle source

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
positional_arguments_allowed?() click to toggle source

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
positional_cardinality() click to toggle source

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
positional_cardinality_explanation() click to toggle source

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
positional_cardinality_ok?(n) click to toggle source

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

do_positional_capture(positionals) click to toggle source
# 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