~ubuntu-branches/ubuntu/wily/ruby-cri/wily-proposed

« back to all changes in this revision

Viewing changes to lib/cri/option_parser.rb

  • Committer: Package Import Robot
  • Author(s): Cédric Boutillier
  • Date: 2014-04-14 15:15:48 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20140414151548-xni482c106hiik3q
Tags: 2.6.0-1
* Imported Upstream version 2.6.0
* Add asciidoctor to Build-Depends, now that the README file has a .adoc
  extension
* Add privacy-breach.patch to remove remote badges from the README file

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
  # A sample array of definition hashes could look like this:
17
17
  #
18
18
  #     [
19
 
  #       { :short => 'a', :long => 'all',  :argument => :forbidden },
20
 
  #       { :short => 'p', :long => 'port', :argument => :required  },
 
19
  #       { :short => 'a', :long => 'all',  :argument => :forbidden, :multiple => true },
 
20
  #       { :short => 'p', :long => 'port', :argument => :required, :multiple => false },
21
21
  #     ]
22
22
  #
23
23
  # For example, the following commandline options (which should not be
84
84
    # @return [Hash] The already parsed options.
85
85
    attr_reader :options
86
86
 
87
 
    # The arguments that have already been parsed.
88
 
    #
89
 
    # If the parser was stopped before it finished, this will not contain all
90
 
    # options and `unprocessed_arguments_and_options` will contain what is
91
 
    # left to be processed.
92
 
    #
93
 
    # @return [Array] The already parsed arguments.
94
 
    attr_reader :arguments
 
87
    # @return [Array] The arguments that have already been parsed, including
 
88
    #   the -- separator.
 
89
    attr_reader :raw_arguments
95
90
 
96
91
    # The options and arguments that have not yet been processed. If the
97
92
    # parser wasn’t stopped (using {#stop}), this list will be empty.
122
117
      @unprocessed_arguments_and_options = arguments_and_options.dup
123
118
      @definitions = definitions
124
119
 
125
 
      @options   = {}
126
 
      @arguments = []
 
120
      @options       = {}
 
121
      @raw_arguments = []
127
122
 
128
123
      @running = false
129
124
      @no_more_options = false
130
125
    end
131
126
 
 
127
    # Returns the arguments that have already been parsed.
 
128
    #
 
129
    # If the parser was stopped before it finished, this will not contain all
 
130
    # options and `unprocessed_arguments_and_options` will contain what is
 
131
    # left to be processed.
 
132
    #
 
133
    # @return [Array] The already parsed arguments.
 
134
    def arguments
 
135
      ArgumentArray.new(@raw_arguments).freeze
 
136
    end
 
137
 
132
138
    # @return [Boolean] true if the parser is running, false otherwise.
133
139
    def running?
134
140
      @running
161
167
        e = @unprocessed_arguments_and_options.shift
162
168
        break if e.nil?
163
169
 
164
 
        # Handle end-of-options marker
165
170
        if e == '--'
166
 
          @no_more_options = true
167
 
        # Handle incomplete options
 
171
          handle_dashdash(e)
168
172
        elsif e =~ /^--./ and !@no_more_options
169
 
          # Get option key, and option value if included
170
 
          if e =~ /^--([^=]+)=(.+)$/
171
 
            option_key   = $1
172
 
            option_value = $2
173
 
          else
174
 
            option_key    = e[2..-1]
175
 
            option_value  = nil
176
 
          end
177
 
 
178
 
          # Find definition
179
 
          definition = @definitions.find { |d| d[:long] == option_key }
180
 
          raise IllegalOptionError.new(option_key) if definition.nil?
181
 
 
182
 
          if [ :required, :optional ].include?(definition[:argument])
183
 
            # Get option value if necessary
184
 
            if option_value.nil?
185
 
              option_value = @unprocessed_arguments_and_options.shift
186
 
              if option_value.nil? || option_value =~ /^-/
187
 
                if definition[:argument] == :required
188
 
                  raise OptionRequiresAnArgumentError.new(option_key)
189
 
                else
190
 
                  @unprocessed_arguments_and_options.unshift(option_value)
191
 
                  option_value = true
192
 
                end
193
 
              end
194
 
            end
195
 
 
196
 
            # Store option
197
 
            add_option(definition, option_value)
198
 
          else
199
 
            # Store option
200
 
            add_option(definition, true)
201
 
          end
202
 
        # Handle -xyz options
 
173
          handle_dashdash_option(e)
203
174
        elsif e =~ /^-./ and !@no_more_options
204
 
          # Get option keys
205
 
          option_keys = e[1..-1].scan(/./)
206
 
 
207
 
          # For each key
208
 
          option_keys.each do |option_key|
209
 
            # Find definition
210
 
            definition = @definitions.find { |d| d[:short] == option_key }
211
 
            raise IllegalOptionError.new(option_key) if definition.nil?
212
 
 
213
 
            if option_keys.length > 1 and definition[:argument] == :required
214
 
              # This is a combined option and it requires an argument, so complain
215
 
              raise OptionRequiresAnArgumentError.new(option_key)
216
 
            elsif [ :required, :optional ].include?(definition[:argument])
217
 
              # Get option value
218
 
              option_value = @unprocessed_arguments_and_options.shift
219
 
              if option_value.nil? || option_value =~ /^-/
220
 
                if definition[:argument] == :required
221
 
                  raise OptionRequiresAnArgumentError.new(option_key)
222
 
                else
223
 
                  @unprocessed_arguments_and_options.unshift(option_value)
224
 
                  option_value = true
225
 
                end
226
 
              end
227
 
 
228
 
              # Store option
229
 
              add_option(definition, option_value)
230
 
            else
231
 
              # Store option
232
 
              add_option(definition, true)
233
 
            end
234
 
          end
235
 
        # Handle normal arguments
 
175
          handle_dash_option(e)
236
176
        else
237
177
          add_argument(e)
238
178
        end
244
184
 
245
185
  private
246
186
 
 
187
    def handle_dashdash(e)
 
188
      add_argument(e)
 
189
      @no_more_options = true
 
190
    end
 
191
 
 
192
    def handle_dashdash_option(e)
 
193
      # Get option key, and option value if included
 
194
      if e =~ /^--([^=]+)=(.+)$/
 
195
        option_key   = $1
 
196
        option_value = $2
 
197
      else
 
198
        option_key    = e[2..-1]
 
199
        option_value  = nil
 
200
      end
 
201
 
 
202
      # Find definition
 
203
      definition = @definitions.find { |d| d[:long] == option_key }
 
204
      raise IllegalOptionError.new(option_key) if definition.nil?
 
205
 
 
206
      if [ :required, :optional ].include?(definition[:argument])
 
207
        # Get option value if necessary
 
208
        if option_value.nil?
 
209
          option_value = find_option_value(definition, option_key)
 
210
        end
 
211
 
 
212
        # Store option
 
213
        add_option(definition, option_value)
 
214
      else
 
215
        # Store option
 
216
        add_option(definition, true)
 
217
      end
 
218
    end
 
219
 
 
220
    def handle_dash_option(e)
 
221
      # Get option keys
 
222
      option_keys = e[1..-1].scan(/./)
 
223
 
 
224
      # For each key
 
225
      option_keys.each do |option_key|
 
226
        # Find definition
 
227
        definition = @definitions.find { |d| d[:short] == option_key }
 
228
        raise IllegalOptionError.new(option_key) if definition.nil?
 
229
 
 
230
        if option_keys.length > 1 and definition[:argument] == :required
 
231
          # This is a combined option and it requires an argument, so complain
 
232
          raise OptionRequiresAnArgumentError.new(option_key)
 
233
        elsif [ :required, :optional ].include?(definition[:argument])
 
234
          # Get option value
 
235
          option_value = find_option_value(definition, option_key)
 
236
 
 
237
          # Store option
 
238
          add_option(definition, option_value)
 
239
        else
 
240
          # Store option
 
241
          add_option(definition, true)
 
242
        end
 
243
      end
 
244
    end
 
245
 
 
246
    def find_option_value(definition, option_key)
 
247
      option_value = @unprocessed_arguments_and_options.shift
 
248
      if option_value.nil? || option_value =~ /^-/
 
249
        if definition[:argument] == :required
 
250
          raise OptionRequiresAnArgumentError.new(option_key)
 
251
        else
 
252
          @unprocessed_arguments_and_options.unshift(option_value)
 
253
          option_value = true
 
254
        end
 
255
      end
 
256
      option_value
 
257
    end
 
258
 
247
259
    def add_option(definition, value)
248
260
      key = (definition[:long] || definition[:short]).to_sym
249
 
      options[key] = value
 
261
      if definition[:multiple]
 
262
        options[key] ||= []
 
263
        options[key] << value
 
264
      else
 
265
        options[key] = value
 
266
      end
 
267
 
250
268
      delegate.option_added(key, value, self) unless delegate.nil?
251
269
    end
252
270
 
253
271
    def add_argument(value)
254
 
      arguments << value
255
 
      delegate.argument_added(value, self) unless delegate.nil?
 
272
      @raw_arguments << value
 
273
 
 
274
      unless '--' == value
 
275
        delegate.argument_added(value, self) unless delegate.nil?
 
276
      end
256
277
    end
257
278
 
258
279
  end