1 """Command-line options parser.
2 With the help of an options spec string, easily parse command-line options.
13 def __setitem__(self, k, v):
16 def __getitem__(self, k):
19 def __getattr__(self, k):
23 def _default_onabort(msg):
39 When constructed, two strings are mandatory. The first one is the command
40 name showed before error messages. The second one is a string called an
41 optspec that specifies the synopsis and option flags and their description.
42 For more information about optspecs, consult the bup-options(1) man page.
44 Two optional arguments specify an alternative parsing function and an
45 alternative behaviour on abort (after having output the usage string).
47 By default, the parser function is getopt.gnu_getopt, and the abort
48 behaviour is to exit the program.
50 def __init__(self, exe, optspec, optfunc=getopt.gnu_getopt,
51 onabort=_default_onabort):
53 self.optspec = optspec
54 self._onabort = onabort
55 self.optfunc = optfunc
57 self._shortopts = 'h?'
58 self._longopts = ['help']
61 self._usagestr = self._gen_usage()
65 lines = self.optspec.strip().split('\n')
71 out.append('%s: %s\n' % (first_syn and 'usage' or ' or', l))
77 out.append('\n%s\n' % l.lstrip())
79 (flags, extra) = l.split(' ', 1)
81 if flags.endswith('='):
86 g = re.search(r'\[([^\]]*)\]', extra)
91 flagl = flags.split(',')
94 self._aliases[f] = flagl[0]
95 self._hasparms[f] = has_parm
96 self._defaults[f] = _intify(defval)
98 self._shortopts += f + (has_parm and ':' or '')
99 flagl_nice.append('-' + f)
101 f_nice = re.sub(r'\W', '_', f)
102 self._aliases[f_nice] = flagl[0]
103 assert(not f.startswith('no-')) # supported implicitly
104 self._longopts.append(f + (has_parm and '=' or ''))
105 self._longopts.append('no-' + f)
106 flagl_nice.append('--' + f)
107 flags_nice = ', '.join(flagl_nice)
110 prefix = ' %-20s ' % flags_nice
111 argtext = '\n'.join(textwrap.wrap(extra, width=70,
112 initial_indent=prefix,
113 subsequent_indent=' '*28))
114 out.append(argtext + '\n')
117 return ''.join(out).rstrip() + '\n'
119 def usage(self, msg=""):
120 """Print usage string to stderr and abort."""
121 sys.stderr.write(self._usagestr)
122 e = self._onabort and self._onabort(msg) or None
127 """Print an error message to stderr and abort with usage string."""
128 msg = 'error: %s\n' % s
129 sys.stderr.write(msg)
130 return self.usage(msg)
132 def parse(self, args):
133 """Parse a list of arguments and return (options, flags, extra).
135 In the returned tuple, "options" is an OptDict with known options,
136 "flags" is a list of option flags that were used on the command-line,
137 and "extra" is a list of positional arguments.
140 (flags,extra) = self.optfunc(args, self._shortopts, self._longopts)
141 except getopt.GetoptError, e:
146 for k,v in self._defaults.iteritems():
152 if k in ('h', '?', 'help'):
154 if k.startswith('no-'):
155 k = self._aliases[k[3:]]
159 if not self._hasparms[k]:
161 v = (opt._opts.get(k) or 0) + 1
165 for (f1,f2) in self._aliases.iteritems():
166 opt[f1] = opt._opts.get(f2)
167 return (opt,flags,extra)