def parse(args, flags={})
      @args = args
      # start with symbolized defaults
      hash = Hash[@defaults.map {|k,v| [k.to_sym, v] }]

      @leading_non_opts = []
      unless flags[:opts_before_args]
        @leading_non_opts << shift until current_is_option? || @args.empty? ||
          STOP_STRINGS.include?(peek)
      end

      while current_is_option?
        case @original_current_option = shift
        when SHORT_SQ_RE
          unshift $1.split('').map { |f| "-#{f}" }
          next
        when EQ_RE, SHORT_NUM
          unshift $2
          option = $1
        when LONG_RE, SHORT_RE
          option = $1
        end

        dashed_option = normalize_option(option)
        @current_option = undasherize(dashed_option)
        type = option_type(dashed_option)
        validate_option_value(type)
        value = create_option_value(type)
        # set on different line since current_option may change
        hash[@current_option.to_sym] = value
      end

      @trailing_non_opts = @args
      check_required! hash
      delete_invalid_opts if flags[:delete_invalid_opts]
      indifferent_hash.tap {|h| h.update hash }
    end
def parse(args, flags={})
      @args = args
      # start with symbolized defaults
      hash = Hash[@defaults.map {|k,v| [k.to_sym, v] }]

      @leading_non_opts = []
      unless flags[:opts_before_args]
        @leading_non_opts << shift until current_is_option? || @args.empty? ||
          STOP_STRINGS.include?(peek)
      end

      while current_is_option?
        case @original_current_option = shift
        when SHORT_SQ_RE
          unshift $1.split('').map { |f| "-#{f}" }
          next
        when EQ_RE, SHORT_NUM
          unshift $2
          option = $1
        when LONG_RE, SHORT_RE
          option = $1
        end

        dashed_option = normalize_option(option)
        @current_option = undasherize(dashed_option)
        type = option_type(dashed_option)
        validate_option_value(type)
        value = create_option_value(type)
        # set on different line since current_option may change
        hash[@current_option.to_sym] = value
      end

      @trailing_non_opts = @args
      check_required! hash
      delete_invalid_opts if flags[:delete_invalid_opts]
      indifferent_hash.tap {|h| h.update hash }
    end
Takes a hash of options. Each option, a key-value pair, must provide the
 option's name and type. Names longer than one character are accessed with
 '--' while one character names are accessed with '-'. Names can be
 symbols, strings or even dasherized strings:

    Boson::OptionParser.new :debug=>:boolean, 'level'=>:numeric,
      '--fields'=>:array

 Options can have default values and implicit types simply by changing the
 option type for the default value:

    Boson::OptionParser.new :debug=>true, 'level'=>3.1, :fields=>%w{f1 f2}

 By default every option name longer than one character is given an alias,
 the first character from its name. For example, the --fields option has -f
 as its alias. You can override the default alias by providing your own
 option aliases as an array in the option's key.

    Boson::OptionParser.new [:debug, :damnit, :D]=>true

 Note that aliases are accessed the same way as option names. For the
 above, --debug, --damnit and -D all refer to the same option.

 Options can have additional attributes by passing a hash to the option
 value instead of a type or default:

    Boson::OptionParser.new :fields=>{:type=>:array, :values=>%w{f1 f2 f3},
     :enum=>false}

 These attributes are available when an option is parsed via
 current_attributes().  Here are the available option attributes for the
 default option types:

 [*:type*] This or :default is required. Available types are :string,
           :boolean, :array, :numeric, :hash.
 [*:default*] This or :type is required. This is the default value an
              option has when not passed.
 [*:bool_default*] This is the value an option has when passed as a
                   boolean. However, by enabling this an option can only
                   have explicit values with '=' i.e. '--index=alias' and
                   no '--index alias'. If this value is a string, it is
                   parsed as any option value would be. Otherwise, the
                   value is passed directly without parsing.
 [*:required*] Boolean indicating if option is required. Option parses
               raises error if value not given. Default is false.
 [*:alias*] Alternative way to define option aliases with an option name
            or an array of them. Useful in yaml files. Setting to false
            will prevent creating an automatic alias.
 [*:values*] An array of values an option can have. Available for :array
             and :string options. Values here can be aliased by typing a
             unique string it starts with or underscore aliasing (see
             Util.underscore_search). For example, for values foo, odd and
             obnoxiously_long, f refers to foo, od to odd and o_l to
             obnoxiously_long.
 [*:enum*] Boolean indicating if an option enforces values in :values or
           :keys. Default is true. For :array, :hash and :string options.
 [*:split*] For :array and :hash options. A string or regular expression
            on which an array value splits to produce an array of values.
            Default is ','.
 [*:keys*] :hash option only. An array of values a hash option's keys can
            have. Keys can be aliased just like :values.
 [*:default_keys*] For :hash option only. Default keys to assume when only
                   a value is given. Multiple keys can be joined by the
                   :split character. Defaults to first key of :keys if
                   :keys given.
 [*:regexp*] For :array option with a :values attribute. Boolean indicating
             that each option value does a regular expression search of
             :values. If there are values that match, they replace the
             original option value. If none, then the original option
             value is used.
 Parses an array of arguments for defined options to return an indifferent
 access hash. Once the parser recognizes a valid option, it continues to
 parse until an non option argument is detected.
 @param [Hash] flags
 @option flags [Boolean] :opts_before_args When true options must come
   before arguments. Default is false.
 @option flags [Boolean] :delete_invalid_opts When true deletes any
   invalid options left after parsing. Will stop deleting if it comes
   across - or --. Default is false.