class Argvector

Argvector

Argvector provides a very simple means of parsing command line arguments.

Unlike other more complex libs this provides only the most basic and standard parsing functionality. In many cases that's all one really needs.

Usage is straight foward. Simply instantiate the class and query it for the particular “views” of the command line you want.

cargs = Argvector.new("-a foo -b=2")

cargs.parameters    #=> [['foo'],{'a'=>true,'b'=>'2'}]
cargs.flags         #=> ['a']
cargs.preoptions    #=> {'a'=>true}
cargs.preflags      #=> ['a']
cargs.subcommand    #=> ['foo',{'b'=>'2'}]

Attributes

argv[R]
arity[R]
line[R]

Public Class Methods

new(line=nil, arity=nil) click to toggle source

Takes the command line string (or array) and options. Options have flags and end with a hash of option arity.

# File lib/more/facets/argvector.rb, line 81
def initialize(line=nil, arity=nil)
  @line, @argv  = parse_line(line)
  @arity = parse_arity(arity||{})
  parse
end
parameters(*args) click to toggle source
# File lib/more/facets/argvector.rb, line 67
def self.parameters(*args)
  new.parameters(*args)
end

Public Instance Methods

arguments()

deprecate alias ?

Alias for: operands
flags() click to toggle source

Return flags, which are true options.

# File lib/more/facets/argvector.rb, line 113
def flags
  f = []
  @options.each do |k, v|
    if TrueClass===v or FalseClass===v  # not that it's ever false
      f << k
    end
  end
  return f
end
operands() click to toggle source

Returns operand array.

# File lib/more/facets/argvector.rb, line 91
def operands
  @operands
end
Also aliased as: arguments
options() click to toggle source

Returns options hash.

# File lib/more/facets/argvector.rb, line 100
def options
  @options
end
parameters() click to toggle source

Returns [operands, options], which is good for plugging directly into a method.

# File lib/more/facets/argvector.rb, line 107
def parameters
  return @operands, @options
end
parameters_without_duplicates() click to toggle source

Like parameters but without allowing for duplicate options.

# File lib/more/facets/argvector.rb, line 188
def parameters_without_duplicates
  opts = {}
  @options.each do |k,v|
    if Array===v
      opts[k] = v[0]
    else
      opts[k] =  v
    end
  end
  return @operands, opts
end
preflags() click to toggle source

Same as flags but only returns flags in the preoptions.

# File lib/more/facets/argvector.rb, line 175
def preflags
  preopts, remainder = *parse_preoptions(argv)
  f = []
  preopts.each do |k, v|
    if TrueClass===v or FalseClass===v  # not that it's ever false
      f << k
    end
  end
  return f
end
preoptions() click to toggle source

Returns a hash of options that occur before the first operand. This works well with subcommand to get the main command's options.

line = "--trace stamp --file VERSION"
cargs = Argvector.new(line)
opts = cargs.preoptions
opts #=> {"trace"=>true}
# File lib/more/facets/argvector.rb, line 167
def preoptions
  preopts, remainder = *parse_preoptions(argv)
  return preopts
end
subcommand()
subcommand_with_arguments() click to toggle source

Assumes the first operand is a “subcommand” and returns it and the argments following it as another Arguments object.

TODO: This probably should be called 'subcommand'.

# File lib/more/facets/argvector.rb, line 151
def subcommand_with_arguments
  opts, args = *parse_preoptions(argv)
  cmd = args.shift
  subargs = self.class.new(args, @arity)
  return cmd, subargs
end
subcommand_with_parameters() click to toggle source

Assumes the first operand is a “subcommand” and returns it and the argments following it as parameters.

# File lib/more/facets/argvector.rb, line 127
def subcommand_with_parameters
  opts, args = *parse_preoptions(argv)
  cmd = args.shift
  subargs = self.class.new(args, @arity)
  return [cmd, *subargs.parameters]
end
Also aliased as: subcommand
subcommand_with_preoptions() click to toggle source
# File lib/more/facets/argvector.rb, line 137
def subcommand_with_preoptions
  pre, args = *parse_preoptions(argv)
  cmd = args.shift
  subargs = self.class.new(args, @arity)
  args, opts = *subargs.parameters
  return [cmd, args, pre.merge(opts)]
end

Private Instance Methods

assoc_options(args) click to toggle source

Parse flags takes the command line and transforms it such that flags (eg. -x and –x) are elemental associative arrays.

line = "--foo hello --try=this"

parse_flags(line) #=> [ [foo,true], hello, ["try","this"] ]
# File lib/more/facets/argvector.rb, line 294
def assoc_options(args)
  #args = args.dup
  args = multi_flag(args) #unless opts.include?(:simple)

  i = 0
  while i < args.size
    arg = args[i]
    case arg
    when /^-/
      arg = arg.sub(/^-{1,2}/,'')
      if arg.index('=')
        key, val = arg.split('=')
        args[i] = [key, val||true]
      elsif arity.key?(arg)
        cnt = arity[arg]
        key = arg
        val = args[i+1,cnt]
        args[i,cnt+1] = [[key, *val]]
        i += (cnt - 1)
      else
        key = arg
        args[i] = [key,true]
      end
    end
    i += 1
  end
  return args
end
format_options(assoc_options) click to toggle source

Format flag options. This converts the associative array of options/flags into a hash. Repeat options will be placed in arrays.

# File lib/more/facets/argvector.rb, line 340
def format_options(assoc_options)
  opts = {}
  assoc_options.each do |k,v|
    if opts.key?(k)
      opts[k] = [opts[k]].flatten << v
    else
      opts[k] = v
    end
  end
  return opts
end
multi_flag(args=nil) click to toggle source

Split single letter option groupings into separate options. ie. -xyz => -x -y -z

# File lib/more/facets/argvector.rb, line 326
def multi_flag(args=nil)
  args ||= argv
  args.collect { |arg|
    if md = /^-(\w{2,})/.match( arg )
      md[1].split(//).collect { |c| "-#{c}" }
    else
      arg.dup
    end
  }.flatten
end
parse() click to toggle source

Basic parser partitions the command line into options and operands. Options are converted to a hash and the two parts are returned.

line = "--trace stamp --file=VERSION"

args, keys = *parse_command(line)

args #=> ["stamp"]
keys #=> {"trace"=>true, "file"=>"VERSION"}
# File lib/more/facets/argvector.rb, line 213
def parse
  args = assoc_options(argv) #, *opts_arity)

  opts, opds = args.partition{ |a| Array === a }

  @operands = opds
  @options  = format_options(opts)

  return @operands, @options
end
parse_arity(arity) click to toggle source

Ensure arity is uniform.

# File lib/more/facets/argvector.rb, line 253
def parse_arity(arity)
  arity2 = {}
  arity.each{ |k,v| arity2[k.to_s] = v.to_i }
  return arity2
end
parse_line(line=nil) click to toggle source

First pass parser to split the command line into an array using Shellwords, if not already so divided.

# File lib/more/facets/argvector.rb, line 227
def parse_line(line=nil)
  if line
    case line
    when String
      argv = Shellwords.shellwords(line)
    else
      argv = line.to_ary.dup
      line = argv.join(' ')
    end
  else
    argv = ARGV.dup
    line = argv.join(' ')
  end
  return line, argv
end
parse_preoptions(args) click to toggle source

Parse preoptions. A “preoption” is one that occurs before the first operans (if any).

# File lib/more/facets/argvector.rb, line 262
def parse_preoptions(args)
  #args = args.dup
  args = multi_flag(args) #unless opts.include?(:simple)

  flags = []
  while args.first =~ /^-/
    key = args.shift
    key.sub!(/^-{1,2}/,'')
    if key.index('=')
      key, val = key.split('=')
    elsif a = arity[key]
      val = args.slice!(0,a)
      val = val.first if a == 1
    else
      val = true
    end
    flags << [key, val]
  end

  flags = format_options(flags)

  return flags, args
end