dynamic cmd.Cmd tab-completion
Solution 1:
Your script does not work with Python 3.8.10
probably because of this line
setattr(C, 'do_' + k, k)
k
is not a method. By the way, the mistake is in this line:
for k, v in self.commands.items():
self.k = k # <--
You are continuously reassigning self.k
until the last key of the commands
dictionary, that is bb
. Later, the complete_
method is always evaluated as self.commands['bb']
. Here is a possible working version:
import cmd
class C(cmd.Cmd):
commands = {
'aa': ['aa1', 'aa2'],
'bb': ['bb1', 'bb2']
}
def monad_print(self, *args):
print(args)
def preloop(self):
for k, v in self.commands.items():
setattr(C, 'do_' + k, lambda self, arg, k=k: self.monad_print(k, arg))
setattr(C, 'complete_' + k, self.complete_)
def complete_(self, text, line, start_index, end_index):
command = line.split(' ', maxsplit=1)[0]
if text:
return [
command for command in self.commands[command]
if command.startswith(text)
]
else:
return self.commands[command]
if __name__ == '__main__':
C().cmdloop()
The only difference is that the command is now taken from the entire read-line, in particular the first token of str.split()
.