python-3.xautocompletesubcommand

Using cmd module: how to have sub-commands documented in `help` and integrated with autocomplete?


I'm using the cmd module and have a command called server (method do_server()) which has autocomplete out of the box (I'm on macOS). That's all fine and works like expected. But if i want to additionally also use a sub-command on the server command, things don't work out like i need it.

I would need the following:
- sub-commands should also be integrated with the help command (shouldn't be shown when entering help since they are not first level commands but should be shown when entering help server)
- sub-commands should also integrate with auto-complete

Currently i don't see a way to define sub-commands out-of-the-box. I need to implement them as arguments for a command which isn't ideal.

My question would be, how can i achieve automatic documentation of the sub-commands with help and have autocomplete so that it integrates as good as possible with cmd?

For this example, i'd like to better integrate connect as a sub-command:

from cmd import Cmd


class Tansanit(Cmd):

    def do_server(self, args):
        """ Show server info """
        print("Some server details")

        if args and args == "connect":
            print("Connect to the server")

    def do_quit(self, args):
        """ Quit CLI """
        raise SystemExit


if __name__ == '__main__':
    t = Tansanit()
    t.prompt = "> "
    t.cmdloop()

I would prefer to have something like this:

from cmd import Cmd


class Tansanit(Cmd):

    def do_server(self, args):
        """ Show server info """
        print("Some server details")

    def do_server_connect(self, args):
        """ Connect to server """
        print("Connect to the server")

    def do_quit(self, args):
        """ Quit CLI """
        raise SystemExit


if __name__ == '__main__':
    t = Tansanit()
    t.prompt = "> "
    t.cmdloop()

Unfortunately that's not possible.


Solution

  • Relavant infos can be found here

    Autocomplete for sub-commands

    The interpreter is able to process completion for commands names, but for commands arguments you will have to help it. For the command xxx, this is done by defining a complete_xxx method. For example, if you have defined a color command, the completion method for this command could be:

    _AVAILABLE_COLORS = ('blue', 'green', 'yellow', 'red', 'black')
    def complete_color(self, text, line, begidx, endidx):
        return [i for i in _AVAILABLE_COLORS if i.startswith(text)]
    

    The complete_xxx method takes four arguments:

    text is the string we are matching against, all returned matches must begin with it line is is the current input line begidx is the beginning index in the line of the text being matched endidx is the end index in the line of the text being matched It should return a list (possibly empty) of strings representing the possible completions. The arguments begidx and endidx are useful when completion depends on the position of the argument.

    help for sub-commands

    You can also define help for topics that are not related to commands:

    def help_introduction(self):
        print 'introduction'
        print 'a good place for a tutorial'
    

    This isn't perfect since the help will be categorized as undocumented commands but it's for an argument. But maybe still better then nothing.