diff profilemanager/command.py @ 1:979315ed0816

mucho cleanup on optionparser stuff
author Jeff Hammel <jhammel@mozilla.com>
date Mon, 05 Apr 2010 08:55:44 -0700
parents 7301d534bc6c
children 4d1cd60dd2a1
line wrap: on
line diff
--- a/profilemanager/command.py	Sun Apr 04 18:49:55 2010 -0400
+++ b/profilemanager/command.py	Mon Apr 05 08:55:44 2010 -0700
@@ -41,10 +41,6 @@
         retval.append('[options]')
     return ' '.join(retval)
 
-def list_commands():
-    for command in sorted(commands.keys()):
-        print '%s %s' % (command, commandargs2str(command))
-        print '\n%s\n' % commands[command]['doc']
 
 def doc2arghelp(docstring, decoration='-', delimeter=':'):
     """
@@ -96,3 +92,73 @@
                                   
     return parser
 
+class CommandParser(OptionParser):
+    def __init__(self, commands, description=None, setup=None):
+        usage = '%prog [options] command [command-options]'
+        OptionParser.__init__(self, description=description)
+        for _command in commands:
+            command(_command)
+        self.disable_interspersed_args()
+        self.setup = setup
+
+    def print_help(self):
+        OptionParser.print_help(self)
+        # short descriptions for commands
+        command_descriptions = [dict(name=i,
+                                     description=commands[i]['doc'].strip().split('\n',1)[0])
+                                for i in sorted(commands.keys())]
+        max_len = max([len(i['name']) for i in command_descriptions])
+        description = "Commands: \n%s" % ('\n'.join(['  %s%s  %s' % (description['name'], ' ' * (max_len - len(description['name'])), description['description'])
+                                                     for description in command_descriptions]))
+
+        print
+        print description
+
+    def parse(self, args=sys.argv[1:]):
+        """global parse step"""
+        
+        self.options, args = self.parse_args(args)
+
+        # help/sanity check -- should probably be separated
+        if not len(args):
+            self.print_help()
+            sys.exit(0)
+        if args[0] == 'help':
+            if len(args) == 2:
+                if args[1] in commands:
+                    name = args[1]
+                    commandparser = command2parser(name)
+                    commandparser.print_help()
+                else:
+                    self.error("No command '%s'" % args[1])
+            else:
+                self.print_help()
+            sys.exit(0)
+        command = args[0]
+        if command not in commands:
+            self.error("No command '%s'" % command)
+        return command, args[1:]
+
+    def invoke(self, args=sys.argv[1:]):
+        """
+        invoke
+        """
+
+        # parse
+        name, args = self.parse(args)
+
+        # setup
+        _object = self.setup(self, self.options)
+
+        # command specific args
+        command = commands[name]
+        commandparser = command2parser(name)
+        command_options, command_args = commandparser.parse_args(args)
+        if len(command_args) < len(command['args']):
+            commandparser.error("Not enough arguments given")
+        if len(command_args) != len(command['args']) and not command['varargs']:
+            commandparser.error("Too many arguments given")
+
+        # invoke the command
+        getattr(_object, name)(*command_args, **command_options.__dict__)
+