mercurial/fancyopts.py
author Bryan O'Sullivan <bryano@fb.com>
Thu, 18 Apr 2013 12:55:58 -0700
changeset 19052 63a783d1ac85
parent 17712 c4717f44c1f1
child 20034 1e5b38a919dd
permissions -rw-r--r--
blackbox: fix a case of name capture
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
8230
ec98f35e3e16 fancyopts: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7772
diff changeset
     1
# fancyopts.py - better command line parsing
ec98f35e3e16 fancyopts: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7772
diff changeset
     2
#
ec98f35e3e16 fancyopts: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7772
diff changeset
     3
#  Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
ec98f35e3e16 fancyopts: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7772
diff changeset
     4
#
ec98f35e3e16 fancyopts: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7772
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 8366
diff changeset
     6
# GNU General Public License version 2 or any later version.
8230
ec98f35e3e16 fancyopts: add copyright and license header
Martin Geisler <mg@lazybytes.net>
parents: 7772
diff changeset
     7
17712
c4717f44c1f1 fancyopts: don't show a traceback on invalid integer values
Idan Kamara <idankk86@gmail.com>
parents: 14943
diff changeset
     8
import getopt, util
c4717f44c1f1 fancyopts: don't show a traceback on invalid integer values
Idan Kamara <idankk86@gmail.com>
parents: 14943
diff changeset
     9
from i18n import _
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    10
7772
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    11
def gnugetopt(args, options, longoptions):
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    12
    """Parse options mostly like getopt.gnu_getopt.
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    13
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    14
    This is different from getopt.gnu_getopt in that an argument of - will
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    15
    become an argument of - instead of vanishing completely.
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    16
    """
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    17
    extraargs = []
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    18
    if '--' in args:
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    19
        stopindex = args.index('--')
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
    20
        extraargs = args[stopindex + 1:]
7772
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    21
        args = args[:stopindex]
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    22
    opts, parseargs = getopt.getopt(args, options, longoptions)
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    23
    args = []
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    24
    while parseargs:
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    25
        arg = parseargs.pop(0)
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    26
        if arg and arg[0] == '-' and len(arg) > 1:
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    27
            parseargs.insert(0, arg)
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    28
            topts, newparseargs = getopt.getopt(parseargs, options, longoptions)
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    29
            opts = opts + topts
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    30
            parseargs = newparseargs
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    31
        else:
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    32
            args.append(arg)
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    33
    args.extend(extraargs)
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    34
    return opts, args
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    35
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    36
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    37
def fancyopts(args, options, state, gnu=False):
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    38
    """
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    39
    read args, parse options, and store options in state
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    40
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    41
    each option is a tuple of:
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    42
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    43
      short option or ''
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    44
      long option
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    45
      default value
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    46
      description
11321
40c06bbf58be help: show value requirement and multiple occurrence of options
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 10282
diff changeset
    47
      option value label(optional)
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    48
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    49
    option types include:
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    50
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    51
      boolean or none - option sets variable in state to true
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    52
      string - parameter string is stored in state
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    53
      list - parameter string is added to a list
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    54
      integer - parameter strings is stored as int
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    55
      function - call function with parameter
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    56
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    57
    non-option args are returned
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    58
    """
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    59
    namelist = []
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    60
    shortlist = ''
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    61
    argmap = {}
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    62
    defmap = {}
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    63
11321
40c06bbf58be help: show value requirement and multiple occurrence of options
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 10282
diff changeset
    64
    for option in options:
40c06bbf58be help: show value requirement and multiple occurrence of options
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 10282
diff changeset
    65
        if len(option) == 5:
40c06bbf58be help: show value requirement and multiple occurrence of options
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 10282
diff changeset
    66
            short, name, default, comment, dummy = option
40c06bbf58be help: show value requirement and multiple occurrence of options
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 10282
diff changeset
    67
        else:
40c06bbf58be help: show value requirement and multiple occurrence of options
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 10282
diff changeset
    68
            short, name, default, comment = option
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    69
        # convert opts to getopt format
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    70
        oname = name
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    71
        name = name.replace('-', '_')
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    72
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    73
        argmap['-' + short] = argmap['--' + oname] = name
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    74
        defmap[name] = default
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    75
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    76
        # copy defaults to state
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    77
        if isinstance(default, list):
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    78
            state[name] = default[:]
14943
d3bb825ddae3 globally: use safehasattr(x, '__call__') instead of hasattr(x, '__call__')
Augie Fackler <durin42@gmail.com>
parents: 11321
diff changeset
    79
        elif getattr(default, '__call__', False):
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    80
            state[name] = None
5093
88803a69b24a fancyopts: Copy list arguments in command table before modifying.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 3749
diff changeset
    81
        else:
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    82
            state[name] = default
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
    83
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    84
        # does it take a parameter?
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    85
        if not (default is None or default is True or default is False):
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
    86
            if short:
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
    87
                short += ':'
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
    88
            if oname:
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
    89
                oname += '='
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    90
        if short:
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    91
            shortlist += short
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    92
        if name:
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    93
            namelist.append(oname)
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    94
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
    95
    # parse arguments
7772
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    96
    if gnu:
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    97
        parse = gnugetopt
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    98
    else:
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
    99
        parse = getopt.getopt
88887054d277 fancyopts: Parse options that occur after arguments.
Augie Fackler <durin42@gmail.com>
parents: 5878
diff changeset
   100
    opts, args = parse(args, shortlist, namelist)
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   101
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
   102
    # transfer result to state
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
   103
    for opt, val in opts:
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
   104
        name = argmap[opt]
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
   105
        t = type(defmap[name])
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
   106
        if t is type(fancyopts):
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
   107
            state[name] = defmap[name](val)
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
   108
        elif t is type(1):
17712
c4717f44c1f1 fancyopts: don't show a traceback on invalid integer values
Idan Kamara <idankk86@gmail.com>
parents: 14943
diff changeset
   109
            try:
c4717f44c1f1 fancyopts: don't show a traceback on invalid integer values
Idan Kamara <idankk86@gmail.com>
parents: 14943
diff changeset
   110
                state[name] = int(val)
c4717f44c1f1 fancyopts: don't show a traceback on invalid integer values
Idan Kamara <idankk86@gmail.com>
parents: 14943
diff changeset
   111
            except ValueError:
c4717f44c1f1 fancyopts: don't show a traceback on invalid integer values
Idan Kamara <idankk86@gmail.com>
parents: 14943
diff changeset
   112
                raise util.Abort(_('invalid value %r for option %s, '
c4717f44c1f1 fancyopts: don't show a traceback on invalid integer values
Idan Kamara <idankk86@gmail.com>
parents: 14943
diff changeset
   113
                                   'expected int') % (val, opt))
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
   114
        elif t is type(''):
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
   115
            state[name] = val
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
   116
        elif t is type([]):
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
   117
            state[name].append(val)
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
   118
        elif t is type(None) or t is type(False):
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
   119
            state[name] = True
209
63af1db35611 Beginning of new command parsing interface
mpm@selenic.com
parents: 164
diff changeset
   120
5638
a9b7e425674f fancyopts: lots of cleanups
Matt Mackall <mpm@selenic.com>
parents: 5093
diff changeset
   121
    # return unparsed args
0
9117c6561b0b Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff changeset
   122
    return args