"Framework for command line interfaces like CVS.  See class CmdFrameWork."


class CommandFrameWork:

    """Framework class for command line interfaces like CVS.

    The general command line structure is

            command [flags] subcommand [subflags] [argument] ...

    There's a class variable GlobalFlags which specifies the
    global flags options.  Subcommands are defined by defining
    methods named do_<subcommand>.  Flags for the subcommand are
    defined by defining class or instance variables named
    flags_<subcommand>.  If there's no command, method default()
    is called.  The __doc__ strings for the do_ methods are used
    for the usage message, printed after the general usage message
    which is the class variable UsageMessage.  The class variable
    PostUsageMessage is printed after all the do_ methods' __doc__
    strings.  The method's return value can be a suggested exit
    status.  [XXX Need to rewrite this to clarify it.]

    Common usage is to derive a class, instantiate it, and then call its
    run() method; by default this takes its arguments from sys.argv[1:].
    """

    UsageMessage = \
      "usage: (name)s [flags] subcommand [subflags] [argument] ..."

    PostUsageMessage = None

    GlobalFlags = ''

    def __init__(self):
        """Constructor, present for completeness."""
        pass

    def run(self, args = None):
        """Process flags, subcommand and options, then run it."""
        import getopt, sys
        if args is None: args = sys.argv[1:]
        try:
            opts, args = getopt.getopt(args, self.GlobalFlags)
        except getopt.error as msg:
            return self.usage(msg)
        self.options(opts)
        if not args:
            self.ready()
            return self.default()
        else:
            cmd = args[0]
            mname = 'do_' + cmd
            fname = 'flags_' + cmd
            try:
                method = getattr(self, mname)
            except AttributeError:
                return self.usage("command %r unknown" % (cmd,))
            try:
                flags = getattr(self, fname)
            except AttributeError:
                flags = ''
            try:
                opts, args = getopt.getopt(args[1:], flags)
            except getopt.error as msg:
                return self.usage(
                        "subcommand %s: " % cmd + str(msg))
            self.ready()
            return method(opts, args)

    def options(self, opts):
        """Process the options retrieved by getopt.
        Override this if you have any options."""
        if opts:
            print("-"*40)
            print("Options:")
            for o, a in opts:
                print('option', o, 'value', repr(a))
            print("-"*40)

    def ready(self):
        """Called just before calling the subcommand."""
        pass

    def usage(self, msg = None):
        """Print usage message.  Return suitable exit code (2)."""
        if msg: print(msg)
        print(self.UsageMessage % {'name': self.__class__.__name__})
        docstrings = {}
        c = self.__class__
        while 1:
            for name in dir(c):
                if name[:3] == 'do_':
                    if name in docstrings:
                        continue
                    try:
                        doc = getattr(c, name).__doc__
                    except:
                        doc = None
                    if doc:
                        docstrings[name] = doc
            if not c.__bases__:
                break
            c = c.__bases__[0]
        if docstrings:
            print("where subcommand can be:")
            names = list(docstrings.keys())
            names.sort()
            for name in names:
                print(docstrings[name])
        if self.PostUsageMessage:
            print(self.PostUsageMessage)
        return 2

    def default(self):
        """Default method, called when no subcommand is given.
        You should always override this."""
        print("Nobody expects the Spanish Inquisition!")


def test():
    """Test script -- called when this module is run as a script."""
    import sys
    class Hello(CommandFrameWork):
        def do_hello(self, opts, args):
            "hello -- print 'hello world', needs no arguments"
            print("Hello, world")
    x = Hello()
    tests = [
            [],
            ['hello'],
            ['spam'],
            ['-x'],
            ['hello', '-x'],
            None,
            ]
    for t in tests:
        print('-'*10, t, '-'*10)
        sts = x.run(t)
        print("Exit status:", repr(sts))


if __name__ == '__main__':
    test()
