121
|
1 # fancyopts.py - better command line parsing
|
|
2 #
|
|
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
|
|
4 #
|
|
5 # This software may be used and distributed according to the terms of the
|
|
6 # GNU General Public License version 2, incorporated herein by reference.
|
|
7
|
|
8 import getopt
|
|
9
|
|
10 def gnugetopt(args, options, longoptions):
|
|
11 """Parse options mostly like getopt.gnu_getopt.
|
|
12
|
|
13 This is different from getopt.gnu_getopt in that an argument of - will
|
|
14 become an argument of - instead of vanishing completely.
|
|
15 """
|
|
16 extraargs = []
|
|
17 if '--' in args:
|
|
18 stopindex = args.index('--')
|
|
19 extraargs = args[stopindex+1:]
|
|
20 args = args[:stopindex]
|
|
21 opts, parseargs = getopt.getopt(args, options, longoptions)
|
|
22 args = []
|
|
23 while parseargs:
|
|
24 arg = parseargs.pop(0)
|
|
25 if arg and arg[0] == '-' and len(arg) > 1:
|
|
26 parseargs.insert(0, arg)
|
|
27 topts, newparseargs = getopt.getopt(parseargs, options, longoptions)
|
|
28 opts = opts + topts
|
|
29 parseargs = newparseargs
|
|
30 else:
|
|
31 args.append(arg)
|
|
32 args.extend(extraargs)
|
|
33 return opts, args
|
|
34
|
|
35
|
|
36 def fancyopts(args, options, state, gnu=False):
|
|
37 """
|
|
38 read args, parse options, and store options in state
|
|
39
|
|
40 each option is a tuple of:
|
|
41
|
|
42 short option or ''
|
|
43 long option
|
|
44 default value
|
|
45 description
|
|
46
|
|
47 option types include:
|
|
48
|
|
49 boolean or none - option sets variable in state to true
|
|
50 string - parameter string is stored in state
|
|
51 list - parameter string is added to a list
|
|
52 integer - parameter strings is stored as int
|
|
53 function - call function with parameter
|
|
54
|
|
55 non-option args are returned
|
|
56 """
|
|
57 namelist = []
|
|
58 shortlist = ''
|
|
59 argmap = {}
|
|
60 defmap = {}
|
|
61
|
|
62 for short, name, default, comment in options:
|
|
63 # convert opts to getopt format
|
|
64 oname = name
|
|
65 name = name.replace('-', '_')
|
|
66
|
|
67 argmap['-' + short] = argmap['--' + oname] = name
|
|
68 defmap[name] = default
|
|
69
|
|
70 # copy defaults to state
|
|
71 if isinstance(default, list):
|
|
72 state[name] = default[:]
|
|
73 elif hasattr(default, '__call__'):
|
|
74 state[name] = None
|
|
75 else:
|
|
76 state[name] = default
|
|
77
|
|
78 # does it take a parameter?
|
|
79 if not (default is None or default is True or default is False):
|
|
80 if short: short += ':'
|
|
81 if oname: oname += '='
|
|
82 if short:
|
|
83 shortlist += short
|
|
84 if name:
|
|
85 namelist.append(oname)
|
|
86
|
|
87 # parse arguments
|
|
88 if gnu:
|
|
89 parse = gnugetopt
|
|
90 else:
|
|
91 parse = getopt.getopt
|
|
92 opts, args = parse(args, shortlist, namelist)
|
|
93
|
|
94 # transfer result to state
|
|
95 for opt, val in opts:
|
|
96 name = argmap[opt]
|
|
97 t = type(defmap[name])
|
|
98 if t is type(fancyopts):
|
|
99 state[name] = defmap[name](val)
|
|
100 elif t is type(1):
|
|
101 state[name] = int(val)
|
|
102 elif t is type(''):
|
|
103 state[name] = val
|
|
104 elif t is type([]):
|
|
105 state[name].append(val)
|
|
106 elif t is type(None) or t is type(False):
|
|
107 state[name] = True
|
|
108
|
|
109 # return unparsed args
|
|
110 return args
|