Mercurial > python-cmd2
comparison flagReader.py @ 0:febfdc79550b
moved repository to Assembla
author | catherine@DellZilla.myhome.westell.com |
---|---|
date | Wed, 05 Mar 2008 12:16:19 -0500 |
parents | |
children | f807c5cfa0de |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:febfdc79550b |
---|---|
1 """Defines and parses UNIX-style flags to modify command arguments. | |
2 | |
3 print flagReader.FlagSet.parse.__doc__ for usage examples. | |
4 """ | |
5 | |
6 import re | |
7 | |
8 class Flag(object): | |
9 def __init__(self, name, abbrev=None, nargs=0): | |
10 """Flag(name, abbrev=None, nargs=0) : Defines a flag. | |
11 | |
12 name: the full name of the flag (double-dash form) | |
13 abbrev: the single-letter abbreviated form of the flag; defaults to | |
14 nargs: number of arguments expected after the flag""" | |
15 | |
16 self.name = name | |
17 self.abbrev = abbrev or name[0] | |
18 self.fullabbrev = '-%s' % (self.abbrev) | |
19 self.fullname = '--%s' % (name) | |
20 self.nargs = nargs | |
21 | |
22 class FlagSet(object): | |
23 def __init__(self, flags): | |
24 if not issubclass(type(flags), list): | |
25 raise TypeError, 'Argument must be a list' | |
26 self.flags = flags | |
27 self.lookup = {} | |
28 for flag in self.flags: | |
29 self.lookup[flag.abbrev] = flag | |
30 self.lookup[flag.fullabbrev] = flag | |
31 self.lookup[flag.fullname] = flag | |
32 self.abbrevPattern = re.compile('^-([%s]+)$' % (''.join(f.abbrev for f in flags))) | |
33 def parse(self, arg): | |
34 """ | |
35 Finds flags; returns {flag: (values, if any)} and the remaining argument. | |
36 | |
37 >>> f = FlagSet([Flag('foo'), Flag('bar'), Flag('gimmea', nargs=1)]) | |
38 >>> f.parse('-fb') | |
39 ({'foo': [], 'bar': []}, '') | |
40 >>> f.parse('no flags') | |
41 ({}, 'no flags') | |
42 >>> f.parse('-f blah') | |
43 ({'foo': []}, 'blah') | |
44 >>> f.parse('--bar') | |
45 ({'bar': []}, '') | |
46 >>> f.parse('--bar -f') | |
47 ({'foo': [], 'bar': []}, '') | |
48 >>> f.parse('--notaflag') | |
49 ({}, '--notaflag') | |
50 >>> f.parse('') | |
51 ({}, '') | |
52 >>> f.parse('--gimmea bee -f and then some other stuff') | |
53 ({'gimmea': ['bee'], 'foo': []}, 'and then some other stuff') | |
54 >>> f.parse('hidden -bar') | |
55 ({}, 'hidden -bar') | |
56 >>> f.parse('-g myarg -b') | |
57 ({'gimmea': ['myarg'], 'bar': []}, '') | |
58 """ | |
59 result = {} | |
60 words = arg.split() | |
61 while words: | |
62 word = words[0] | |
63 flag = self.lookup.get(word) | |
64 if flag: | |
65 result[flag.name] = [] | |
66 words.pop(0) | |
67 for arg in range(flag.nargs): | |
68 try: | |
69 result[flag.name].append(words.pop(0)) | |
70 except IndexError: # there aren't as many args as we expect | |
71 raise IndexError, '%s expects %d arguments' % (word, flag.nargs) | |
72 continue # on to next word | |
73 smashedAbbrevs = self.abbrevPattern.search(word) | |
74 if smashedAbbrevs: | |
75 for abbrev in smashedAbbrevs.group(1): | |
76 result[self.lookup[abbrev].name] = [] | |
77 words.pop(0) | |
78 continue # on to next word | |
79 #if you get to here, word[0] does not denote options | |
80 break | |
81 return result, ' '.join(words) | |
82 | |
83 def _test(): | |
84 import doctest | |
85 doctest.testmod() | |
86 | |
87 if __name__ == '__main__': | |
88 _test() |