Mercurial > hg > hq
comparison hq/command.py @ 6:321721b581f1
general improvements to the command parser
author | Jeff Hammel <jhammel@mozilla.com> |
---|---|
date | Wed, 26 May 2010 18:56:34 -0700 |
parents | b5671297a0db |
children |
comparison
equal
deleted
inserted
replaced
5:448c248b3738 | 6:321721b581f1 |
---|---|
11 # TODO: add `help` command | 11 # TODO: add `help` command |
12 | 12 |
13 def __init__(self, _class, description=None): | 13 def __init__(self, _class, description=None): |
14 self._class = _class | 14 self._class = _class |
15 self.commands = {} | 15 self.commands = {} |
16 usage = '%prog [options] command [command-options]' | 16 usage = '%prog [options] <command> [command-options]' |
17 description = description or _class.__doc__ | 17 description = description or _class.__doc__.strip() |
18 description += ' Use `%prog help <command>` to display the usage of a command' | |
19 | |
18 OptionParser.__init__(self, usage=usage, description=description) | 20 OptionParser.__init__(self, usage=usage, description=description) |
19 commands = [ getattr(_class, i) for i in dir(_class) | 21 commands = [ getattr(_class, i) for i in dir(_class) |
20 if not i.startswith('_') ] | 22 if not i.startswith('_') ] |
21 commands = [ method for method in commands | 23 commands = [ method for method in commands |
22 if hasattr(method, '__call__') ] | 24 if hasattr(method, '__call__') ] |
23 for _command in commands: | 25 for command in commands: |
24 self.command(_command) | 26 self.add_command(command) |
25 self.disable_interspersed_args() | 27 self.disable_interspersed_args() |
26 | 28 |
27 def print_help(self): | 29 def print_help(self): |
28 # XXX should probably use the optparse formatters to help out here | 30 # XXX should probably use the optparse formatters to help out here |
29 | 31 |
72 | 74 |
73 # parse | 75 # parse |
74 name, args = self.parse(args) | 76 name, args = self.parse(args) |
75 | 77 |
76 # setup | 78 # setup |
77 _object = self._class(self, self.options) | 79 options = self.options.__dict__.copy() |
80 _object = self._class(**options) | |
81 # XXX should only pass values in options that self._class.__init__ | |
82 # needs/wants | |
78 | 83 |
79 # command specific args | 84 # command specific args |
80 command = self.commands[name] | 85 command = self.commands[name] |
81 commandparser = self.command2parser(name) | 86 commandparser = self.command2parser(name) |
82 command_options, command_args = commandparser.parse_args(args) | 87 command_options, command_args = commandparser.parse_args(args) |
93 pass | 98 pass |
94 else: | 99 else: |
95 pprint(retval) | 100 pprint(retval) |
96 return retval | 101 return retval |
97 | 102 |
103 def add_command(self, function): | |
104 command = self.command(function) | |
105 self.commands[command['name']] = command | |
106 | |
98 def command(self, function): | 107 def command(self, function): |
99 name = function.func_name | 108 name = function.func_name |
100 if function.__doc__: | 109 if function.__doc__: |
101 doc = inspect.cleandoc(function.__doc__) | 110 doc = inspect.cleandoc(function.__doc__) |
102 else: | 111 else: |
107 args = argspec.args[1:-len(defaults)] | 116 args = argspec.args[1:-len(defaults)] |
108 optional = dict(zip(argspec.args[-len(defaults):], defaults)) | 117 optional = dict(zip(argspec.args[-len(defaults):], defaults)) |
109 else: | 118 else: |
110 args = argspec.args[1:] | 119 args = argspec.args[1:] |
111 optional = None | 120 optional = None |
112 self.commands[name] = { 'doc': doc, | 121 return { 'name': name, |
113 'args': args, | 122 'doc': doc, |
114 'optional': optional, | 123 'args': args, |
115 'varargs': argspec.varargs | 124 'optional': optional, |
116 } | 125 'varargs': argspec.varargs |
117 return function # XXX to restructure??? | 126 } |
118 | 127 |
119 def commandargs2str(self, command): | 128 def commandargs2str(self, command): |
120 if isinstance(command, basestring): | 129 if isinstance(command, basestring): |
121 command = self.commands[command] | 130 command = self.commands[command] |
122 retval = [] | 131 retval = [] |
140 lines = [ i.strip() for i in docstring.split('\n') ] | 149 lines = [ i.strip() for i in docstring.split('\n') ] |
141 argdict = {} | 150 argdict = {} |
142 doc = [] | 151 doc = [] |
143 option = None | 152 option = None |
144 for line in lines: | 153 for line in lines: |
145 if not line and option: # blank lines terminate [?] | 154 if not line and option: # blank lines terminate [???] |
146 break | 155 break |
147 if line.startswith(decoration) and delimeter in line: | 156 if line.startswith(decoration) and delimeter in line: |
148 name, description = line.split(delimeter, 1) | 157 name, description = line.split(delimeter, 1) |
149 name = name.lstrip(decoration).strip() | 158 name = name.lstrip(decoration).strip() |
150 description = description.strip() | 159 description = description.strip() |
158 argdict = dict([(key, ' '.join(value)) | 167 argdict = dict([(key, ' '.join(value)) |
159 for key, value in argdict.items()]) | 168 for key, value in argdict.items()]) |
160 return ('\n'.join(doc), argdict) | 169 return ('\n'.join(doc), argdict) |
161 | 170 |
162 def command2parser(self, command): | 171 def command2parser(self, command): |
163 doc, argdict = self.doc2arghelp(self.commands[command]['doc']) | 172 if isinstance(command, basestring): |
164 parser = OptionParser('%%prog %s %s' % (command, self.commandargs2str(command)), | 173 command = self.commands[command] |
174 doc, argdict = self.doc2arghelp(command['doc']) | |
175 parser = OptionParser('%%prog %s %s' % (command['name'], self.commandargs2str(command['name'])), | |
165 description=doc, add_help_option=False) | 176 description=doc, add_help_option=False) |
166 if self.commands[command]['optional']: | 177 if command['optional']: |
167 for key, value in self.commands[command]['optional'].items(): | 178 for key, value in command['optional'].items(): |
168 help = argdict.get(key, '') | 179 help = argdict.get(key, '') |
169 if value is True: | 180 if value is True: |
170 parser.add_option('--no-%s' % key, dest=key, | 181 parser.add_option('--no-%s' % key, dest=key, |
171 action='store_false', default=True, | 182 action='store_false', default=True, |
172 help=help) | 183 help=help) |