class Clio::Usage::Parser

Parser

Parse commandline arguments according to given Usage.

Attributes

argv[R]
signatures[R]
usage[R]

Public Class Methods

new(usage, argv) click to toggle source
# File lib/clio/usage/parser.rb, line 20
def initialize(usage, argv) #, index=0)
  # convert to array if argv string
  if ::String===argv
    argv = Shellwords.shellwords(argv)
  else
    argv = argv.dup
  end

  @usage  = usage
  @argv   = argv

  @parsed     = false
  @signatures = []
  @errors     = []
end

Public Instance Methods

errors() click to toggle source
# File lib/clio/usage/parser.rb, line 175
def errors
  @errors
end
Also aliased as: parse_errors
inspect() click to toggle source
# File lib/clio/usage/parser.rb, line 41
def inspect
  s = "<" + signatures.inspect + ">"
  s
  #s  = "#<#{self.class}"
  #s << " @options=#{@options.inspect}" unless @options.empty?
  #s << " @arguments=#{@arguments.inspect}" unless @arguments.empty?
  #s << " @subcommand=#{@subcommand}>" if @subcommand
  #s << ">"
  #s
end
key() click to toggle source
# File lib/clio/usage/parser.rb, line 38
def key  ; usage.key  ; end
name() click to toggle source
# File lib/clio/usage/parser.rb, line 37
def name ; usage.name ; end
parse() click to toggle source
# File lib/clio/usage/parser.rb, line 53
def parse
  @parsed     = false
  @signatures = []
  @errors     = []

  parse_command(usage, argv.dup)

  @parsed     = true

  return Interface.new(@signatures, @errors)
end
parse_errors()
Alias for: errors
parsed?() click to toggle source

Has the commandline been parsed?

# File lib/clio/usage/parser.rb, line 66
def parsed? ; @parsed ; end

Private Instance Methods

parse_command(usage, argv) click to toggle source

TODO: clean-up parsing

# File lib/clio/usage/parser.rb, line 71
      def parse_command(usage, argv)
        options    = {}
        arguments  = []
        command    = nil

        #greedy = parse_greedy(usage, argv)

        #options.update(greedy)

        until argv.empty?
          use, val = parse_option(usage, argv)
          if use
#p "use: #{use.key}, #{val}"
            if val == "\t"
              parse_errors << [val, use]
            elsif use.multiple?
              options[use.key] ||= []
              options[use.key] << val
            else
              options[use.key] = val
            end
          elsif !usage.arguments.empty?
            usage.arguments.each do |a|
              if a.splat
                while argv.first && argv.first !~ /^[-]/
                  arguments << argv.shift
                end
                break if argv.empty?
              else
                arguments << argv.shift
              end
            end
          else
            break if argv.empty?
            arg = argv.shift
            use = usage.commands.find{|c| c === arg}
            if use
              parse_command(use, argv)
              break
            else
              parse_errors << [arg, usage]
              #raise ParseError, "unknown command or argument #{a} for #{usage.key} command"
              break
            end
          end
        end
        @signatures.unshift(Signature.new(usage.name, arguments, options))
      end
parse_option(usage, argv) click to toggle source
# Parse greedy options. This function loops thru ARGV and
# removes any matching greedy options.
def parse_greedy(usage, argv)
  options = {}
  d, i = [], 0
  while i < argv.size
    case a = argv[i]
    when /^[-].+/
      #res = parse_option(a, i)
      name, val = *a.split('=')
      use = usage.greedy_option?(name)
      if use && use.greedy?
        d << i
        if use.flag?
          val = val || true
        else
          val = argv[i+1] unless val
          i += 1
          d << i
        end
        options[use.key] = val
      end
      res = val
    end
    i += 1
  end
  d.each{ |i| argv[i] = nil }
  argv.compact!
  return options
end

#

# File lib/clio/usage/parser.rb, line 154
def parse_option(usage, argv)
  return if argv.first =~ /^[-]+$/
  return if argv.first !~ /(^-.+|=)/
  arg = argv.shift
  name, val = *arg.split('=')
  if use = usage.option?(name)
    if use.flag?
      val = true unless val
    else
      val = argv.shift unless val
    end
    #options[use.name] = val
  else
    parse_errors << [arg, usage.key]
  end
  return use, val
end