~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

- more refactoring of and tests for option parsing

Show diffs side-by-side

added added

removed removed

Lines of Context:
182
182
 
183
183
        Maps from long option name to option object."""
184
184
        r = dict()
 
185
        r['help'] = Option.OPTIONS['help']
185
186
        for o in self.takes_options:
186
187
            if not isinstance(o, Option):
187
188
                o = Option.OPTIONS[o]
190
191
 
191
192
    def run_argv(self, argv):
192
193
        """Parse command line and run."""
193
 
        args, opts = parse_args(argv)
194
 
 
 
194
        args, opts = parse_args(self, argv)
195
195
        if 'help' in opts:  # e.g. bzr add --help
196
196
            from bzrlib.help import help_on_command
197
197
            help_on_command(self.name())
198
198
            return 0
199
 
 
 
199
        # XXX: This should be handled by the parser
200
200
        allowed_names = self.options().keys()
201
201
        for oname in opts:
202
202
            if oname not in allowed_names:
203
203
                raise BzrCommandError("option '--%s' is not allowed for command %r"
204
204
                                      % (oname, self.name()))
205
 
 
206
205
        # mix arguments and options into one dictionary
207
206
        cmdargs = _match_argform(self.name(), self.takes_args, args)
208
207
        cmdopts = {}
269
268
        parsed = [spec, None]
270
269
    return parsed
271
270
 
272
 
def parse_args(argv):
 
271
def parse_args(command, argv):
273
272
    """Parse command line.
274
273
    
275
274
    Arguments and options are parsed at this level before being passed
276
275
    down to specific command handlers.  This routine knows, from a
277
276
    lookup table, something about the available options, what optargs
278
277
    they take, and which commands will accept them.
279
 
 
280
 
    >>> parse_args('--help'.split())
281
 
    ([], {'help': True})
282
 
    >>> parse_args('help -- --invalidcmd'.split())
283
 
    (['help', '--invalidcmd'], {})
284
 
    >>> parse_args('--version'.split())
285
 
    ([], {'version': True})
286
 
    >>> parse_args('status --all'.split())
287
 
    (['status'], {'all': True})
288
 
    >>> parse_args('commit --message=biter'.split())
289
 
    (['commit'], {'message': u'biter'})
290
 
    >>> parse_args('log -r 500'.split())
291
 
    (['log'], {'revision': [<RevisionSpec_int 500>]})
292
 
    >>> parse_args('log -r500..600'.split())
293
 
    (['log'], {'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
294
 
    >>> parse_args('log -vr500..600'.split())
295
 
    (['log'], {'verbose': True, 'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
296
 
    >>> parse_args('log -rrevno:500..600'.split()) #the r takes an argument
297
 
    (['log'], {'revision': [<RevisionSpec_revno revno:500>, <RevisionSpec_int 600>]})
298
278
    """
299
279
    # TODO: chop up this beast
300
280
    args = []
301
281
    opts = {}
302
282
 
 
283
    cmd_options = command.options()
303
284
    argsover = False
304
285
    while argv:
305
286
        a = argv.pop(0)
317
298
                    optname, optarg = a[2:].split('=', 1)
318
299
                else:
319
300
                    optname = a[2:]
320
 
                if optname not in Option.OPTIONS:
321
 
                    raise BzrError('unknown long option %r' % a)
 
301
                if optname not in cmd_options:
 
302
                    raise BzrCommandError('unknown long option %r for command %s' 
 
303
                            % (a, command.name))
322
304
            else:
323
305
                shortopt = a[1:]
324
306
                if shortopt in Option.SHORT_OPTIONS:
355
337
                # XXX: Do we ever want to support this, e.g. for -r?
356
338
                raise BzrError('repeated option %r' % a)
357
339
                
358
 
            optargfn = Option.OPTIONS[optname].type
 
340
            option_obj = cmd_options[optname]
 
341
            optargfn = option_obj.type
359
342
            if optargfn:
360
343
                if optarg == None:
361
344
                    if not argv:
369
352
                opts[optname] = True
370
353
        else:
371
354
            args.append(a)
372
 
 
373
355
    return args, opts
374
356
 
375
357
 
376
 
 
377
 
 
378
358
def _match_argform(cmd, takes_args, args):
379
359
    argdict = {}
380
360