]> arthur.barton.de Git - bup.git/blob - options.py
bup index --check: detect broken index entries.
[bup.git] / options.py
1 import textwrap, getopt, re
2 from helpers import *
3
4 class OptDict:
5     def __init__(self):
6         self._opts = {}
7
8     def __setitem__(self, k, v):
9         self._opts[k] = v
10         
11     def __getitem__(self, k):
12         return self._opts[k]
13
14     def __getattr__(self, k):
15         return self[k]
16
17
18 class Options:
19     def __init__(self, exe, optspec):
20         self.exe = exe
21         self.optspec = optspec
22         self._aliases = {}
23         self._shortopts = 'h?'
24         self._longopts = ['help']
25         self._hasparms = {}
26         self._usagestr = self._gen_usage()
27         
28     def _gen_usage(self):
29         out = []
30         lines = self.optspec.strip().split('\n')
31         lines.reverse()
32         first_syn = True
33         while lines:
34             l = lines.pop()
35             if l == '--': break
36             out.append('%s: %s\n' % (first_syn and 'usage' or '   or', l))
37             first_syn = False
38         out.append('\n')
39         while lines:
40             l = lines.pop()
41             if l.startswith(' '):
42                 out.append('\n%s\n' % l.lstrip())
43             elif l:
44                 (flags, extra) = l.split(' ', 1)
45                 extra = extra.strip()
46                 if flags.endswith('='):
47                     flags = flags[:-1]
48                     has_parm = 1
49                 else:
50                     has_parm = 0
51                 flagl = flags.split(',')
52                 flagl_nice = []
53                 for f in flagl:
54                     f_nice = re.sub(r'\W', '_', f)
55                     self._aliases[f] = flagl[0]
56                     self._aliases[f_nice] = flagl[0]
57                     self._hasparms[f] = has_parm
58                     if len(f) == 1:
59                         self._shortopts += f + (has_parm and ':' or '')
60                         flagl_nice.append('-' + f)
61                     else:
62                         assert(not f.startswith('no-')) # supported implicitly
63                         self._longopts.append(f + (has_parm and '=' or ''))
64                         self._longopts.append('no-' + f)
65                         flagl_nice.append('--' + f)
66                 flags_nice = ', '.join(flagl_nice)
67                 if has_parm:
68                     flags_nice += ' ...'
69                 prefix = '    %-20s  ' % flags_nice
70                 argtext = '\n'.join(textwrap.wrap(extra, width=70,
71                                                 initial_indent=prefix,
72                                                 subsequent_indent=' '*28))
73                 out.append(argtext + '\n')
74             else:
75                 out.append('\n')
76         return ''.join(out).rstrip() + '\n'
77     
78     def usage(self):
79         log(self._usagestr)
80         sys.exit(97)
81
82     def fatal(self, s):
83         log('error: %s\n' % s)
84         return self.usage()
85         
86     def parse(self, args):
87         try:
88             (flags,extra) = getopt.gnu_getopt(args,
89                                               self._shortopts, self._longopts)
90         except getopt.GetoptError, e:
91             self.fatal(e)
92
93         opt = OptDict()
94         for f in self._aliases.values():
95             opt[f] = None
96         for (k,v) in flags:
97             while k.startswith('-'):
98                 k = k[1:]
99             if k in ['h', '?', 'help']:
100                 self.usage()
101             if k.startswith('no-'):
102                 k = self._aliases[k[3:]]
103                 opt[k] = None
104             else:
105                 k = self._aliases[k]
106                 if not self._hasparms[k]:
107                     assert(v == '')
108                     opt[k] = (opt._opts.get(k) or 0) + 1
109                 else:
110                     try:
111                         vv = int(v)
112                         if str(vv) == v:
113                             v = vv
114                     except ValueError:
115                         pass
116                     opt[k] = v
117         for (f1,f2) in self._aliases.items():
118             opt[f1] = opt[f2]
119         return (opt,flags,extra)