How to autocomplete only one argument in Cmd2 with argparse

544 Views Asked by At

How to autocomplete one argument in argument parser with cmd2.

from cmd2 import Cmd, Cmd2ArgumentParser
import cmd2

numbers = ['0', '1', '2', '3', '4']
alphabet = ['a', 'b', 'c', 'd']

class Complete(Cmd):
    parser = Cmd2ArgumentParser()
    parser.add_argument("type", choices=['numbers', 'alphabet'])
    parser.add_argument("value")
    @cmd2.with_argparser(parser)
    def do_list(self, args):
        self.poutput(args.value)


if __name__ == "__main__":
    app = Complete()
    app.cmdloop()

With this code i can autocomplete the 'type' argument (with choices in add_argument). I want to autocomplete the 'value' argument depending on the 'type' argument. If value is 'numbers', I complete it with the numbers list. if value is 'alphabet', I complete it with the alphabet list.

Is there any way to properly implement this behaviour? or should I implement my own complete_list method?

Thanks,

1

There are 1 best solutions below

0
On BEST ANSWER

I found a solution using the keyword completer_method in the Cmd2ArgumentParser. It's not yet documented https://github.com/python-cmd2/cmd2/issues/748.

The complete solution

from cmd2 import Cmd, Cmd2ArgumentParser
import cmd2

numbers = ['0', '1', '2', '3', '4']
alphabet = ['a', 'b', 'c', 'd']



class Complete(Cmd):
    def _complete_list_value(self, text, line, begidx, endidx):
        type_ = line.split()[1]
        if type_ == 'numbers':
            x  = [e for e in numbers if e.startswith(text)]
            return [e for e in numbers if e.startswith(text)]
        elif type_ == 'alphabet':
            return [e for e in alphabet if e.startswith(text)]
        else:
            return []

    parser = Cmd2ArgumentParser()
    parser.add_argument("type", choices=['numbers', 'alphabet'])
    parser.add_argument("value", completer_method=_complete_list_value)
    @cmd2.with_argparser(parser)
    def do_list(self, args):
        self.poutput(args.value)


if __name__ == "__main__":
    app = Complete()
    app.cmdloop()