class Trollop::Parser

The commandline parser. In typical usage, the methods in this class will be handled internally by Trollop#options, in which case only the methods opt, banner and version, depends, and conflicts will typically be called.

Constants

FLAG_TYPES

The set of values that indicate a flag type of option when one of the values is given to the :type parameter to opt.

MULTI_ARG_TYPES

The set of values that indicate an option that takes multiple parameters when one of the values is given to the :type parameter to opt.

SINGLE_ARG_TYPES

The set of values that indicate an option that takes a single parameter when one of the values is given to the :type parameter to opt.

TYPES

The set of values specifiable as the :type parameter to opt.

Attributes

leftovers[R]

The values from the commandline that were not interpreted by parse.

specs[R]

The complete configuration hashes for each option. (Mainly useful for testing.)

Public Class Methods

new(*a, &b) click to toggle source

Initializes the parser, and instance-evaluates any block given.

# File lib/trollop.rb, line 61
def initialize *a, &b
  @version = nil
  @leftovers = []
  @specs = {}
  @long = {}
  @short = {}
  @order = []
  @constraints = []
  @stop_words = []
  @stop_on_unknown = false

  #instance_eval(&b) if b # can't take arguments
  cloaker(&b).bind(self).call(*a) if b
end

Public Instance Methods

banner(s;) click to toggle source

Adds text to the help display.

Also aliased as: text
conflicts(*syms) click to toggle source

Marks two (or more!) options as conflicting.

# File lib/trollop.rb, line 226
def conflicts *syms
  syms.each { |sym| raise ArgumentError, "unknown option '#{sym}'" unless @specs[sym] }
  @constraints << [:conflicts, syms]
end
depends(*syms) click to toggle source

Marks two (or more!) options as requiring each other. Only handles undirected (i.e., mutual) dependencies. Directed dependencies are better modeled with Trollop::die.

# File lib/trollop.rb, line 220
def depends *syms
  syms.each { |sym| raise ArgumentError, "unknown option '#{sym}'" unless @specs[sym] }
  @constraints << [:depends, syms]
end
educate(stream=$stdout) click to toggle source

Print the help message to 'stream'.

# File lib/trollop.rb, line 464
def educate stream=$stdout
  width # just calculate it now; otherwise we have to be careful not to
        # call this unless the cursor's at the beginning of a line.

  left = {}
  @specs.each do |name, spec| 
    left[name] = "--#{spec[:long]}" +
      (spec[:short] ? ", -#{spec[:short]}" : "") +
      case spec[:type]
      when :flag; ""
      when :int; " <i>"
      when :ints; " <i+>"
      when :string; " <s>"
      when :strings; " <s+>"
      when :float; " <f>"
      when :floats; " <f+>"
      end
  end

  leftcol_width = left.values.map { |s| s.length }.max || 0
  rightcol_start = leftcol_width + 6 # spaces

  unless @order.size > 0 && @order.first.first == :text
    stream.puts "#@version\n" if @version
    stream.puts "Options:"
  end

  @order.each do |what, opt|
    if what == :text
      stream.puts wrap(opt)
      next
    end

    spec = @specs[opt]
    stream.printf "  %#{leftcol_width}s:   ", left[opt]
    desc = spec[:desc] + 
      if spec[:default]
        if spec[:desc] =~ /\.$/
          " (Default: #{spec[:default]})"
        else
          " (default: #{spec[:default]})"
        end
      else
        ""
      end
    stream.puts wrap(desc, :width => width - rightcol_start - 1, :prefix => rightcol_start)
  end
end
opt(name, desc="", opts={}) click to toggle source

Add an option. 'name' is the argument name, a unique identifier for the option that you will use internally. 'desc' a string description which will be displayed in help messages. Takes the following optional arguments:

  • :long: Specify the long form of the argument, i.e. the form with two dashes. If unspecified, will be automatically derived based on the argument name.

  • :short: Specify the short form of the argument, i.e. the form with one dash. If unspecified, will be automatically derived based on the argument name.

  • :type: Require that the argument take a parameter or parameters of type 'type'. For a single parameter, the value can be a member of the SINGLE_ARG_TYPES constant or a corresponding class (e.g. Integer for :int). For multiple parameters, the value can be a member of the MULTI_ARG_TYPES constant. If unset, the default argument type is :flag, meaning that the argument does not take a parameter. The specification of :type is not necessary if :default is given.

  • :default: Set the default value for an argument. Without a default value, the hash returned by parse (and thus Trollop#options) will not contain the argument unless it is given on the commandline. The argument type is derived automatically from the class of the default value given, if any. Specifying a :flag argument on the commandline whose default value is true will change its value to false.

  • :required: If set to true, the argument must be provided on the commandline.

  • :multi: If set to true, allows multiple instances of the option. Otherwise, only a single instance of the option is allowed.

# File lib/trollop.rb, line 107
def opt name, desc="", opts={}
  raise ArgumentError, "you already have an argument named '#{name}'" if @specs.member? name

  ## fill in :type
  opts[:type] = 
    case opts[:type]
    when :flag, :boolean, :bool; :flag
    when :int, :integer; :int
    when :ints, :integers; :ints
    when :string; :string
    when :strings; :strings
    when :double, :float; :float
    when :doubles, :floats; :floats
    when Class
      case opts[:type].to_s # sigh... there must be a better way to do this
      when 'TrueClass', 'FalseClass'; :flag
      when 'String'; :string
      when 'Integer'; :int
      when 'Float'; :float
      else
        raise ArgumentError, "unsupported argument type '#{opts[:type].class.name}'"
      end
    when nil; nil
    else
      raise ArgumentError, "unsupported argument type '#{opts[:type]}'" unless TYPES.include?(opts[:type])
    end

  type_from_default =
    case opts[:default]
    when Integer; :int
    when Numeric; :float
    when TrueClass, FalseClass; :flag
    when String; :string
    when Array
      if opts[:default].empty?
        raise ArgumentError, "multiple argument type cannot be deduced from an empty array for '#{opts[:default][0].class.name}'"
      end
      case opts[:default][0]    # the first element determines the types
      when Integer; :ints
      when Numeric; :floats
      when String; :strings
      else
        raise ArgumentError, "unsupported multiple argument type '#{opts[:default][0].class.name}'"
      end
    when nil; nil
    else
      raise ArgumentError, "unsupported argument type '#{opts[:default].class.name}'"
    end

  raise ArgumentError, ":type specification and default type don't match" if opts[:type] && type_from_default && opts[:type] != type_from_default

  opts[:type] = (opts[:type] || type_from_default || :flag)

  ## fill in :long
  opts[:long] = opts[:long] ? opts[:long].to_s : name.to_s.gsub("_", "-")
  opts[:long] =
    case opts[:long]
    when /^--([^-].*)$/
      $1
    when /^[^-]/
      opts[:long]
    else
      raise ArgumentError, "invalid long option name #{opts[:long].inspect}"
    end
  raise ArgumentError, "long option name #{opts[:long].inspect} is already taken; please specify a (different) :long" if @long[opts[:long]]

  ## fill in :short
  opts[:short] = opts[:short].to_s if opts[:short] unless opts[:short] == :none
  opts[:short] =
    case opts[:short]
    when nil
      c = opts[:long].split(//).find { |c| c !~ INVALID_SHORT_ARG_REGEX && !@short.member?(c) }
      raise ArgumentError, "can't generate a short option name for #{opts[:long].inspect}: out of unique characters" unless c
      c
    when /^-(.)$/
      $1
    when /^.$/
      opts[:short]
    when :none
      nil
    else
      raise ArgumentError, "invalid short option name '#{opts[:short].inspect}'"
    end
  if opts[:short]
    raise ArgumentError, "short option name #{opts[:short].inspect} is already taken; please specify a (different) :short" if @short[opts[:short]]
    raise ArgumentError, "a short option name can't be a number or a dash" if opts[:short] =~ INVALID_SHORT_ARG_REGEX
  end

  ## fill in :default for flags
  opts[:default] = false if opts[:type] == :flag && opts[:default].nil?

  ## fill in :multi
  opts[:multi] ||= false

  opts[:desc] ||= desc
  @long[opts[:long]] = name
  @short[opts[:short]] = name if opts[:short]
  @specs[name] = opts
  @order << [:opt, name]
end
stop_on(*words) click to toggle source

Defines a set of words which cause parsing to terminate when encountered, such that any options to the left of the word are parsed as usual, and options to the right of the word are left intact.

A typical use case would be for subcommand support, where these would be set to the list of subcommands. A subsequent Trollop invocation would then be used to parse subcommand options.

# File lib/trollop.rb, line 238
def stop_on *words
  @stop_words = [*words].flatten
end
stop_on_unknown() click to toggle source

Similar to stop_on, but stops on any unknown word when encountered (unless it is a parameter for an argument).

# File lib/trollop.rb, line 244
def stop_on_unknown
  @stop_on_unknown = true
end
text(s;)
Alias for: banner
version(s=nil;) click to toggle source

Sets the version string. If set, the user can request the version on the commandline. Should be of the form “<program name> <version number>”.

# File lib/trollop.rb, line 211
def version s=nil; @version = s if s; @version end