# Almost all code is based on themole completion. http://themole.nasel.com.ar import readline, re import sys class CompletionManager: def __init__(self, cmd_manager, loader): self.manager = cmd_manager self.loader = loader readline.parse_and_bind("tab: complete") readline.set_completer(self.completer) readline.set_completer_delims(' \t\n`~!@#$%^&*()=+[{]}\\|;:\'",<>/?') self.parse_regex = re.compile('("[^"]*"|\'[^\']+\')') def completer(self, text, state): if readline.get_begidx() == 0: return self.generate_commands(text, state) else: return self.generate_parameters(text, state) def get_completion(self, text, state): if self.current == len(self.available): return None else: tmp = self.available[self.current] self.current += 1 return tmp + ' ' def generate_commands(self, text, state): if state == 0: self.available = [] self.current = 0 for c in self.manager.commands(): if c[0:len(text)] == text: self.available.append(c) self.available.sort() if len(self.available) == 1 and self.available[0] == text: self.available = [] self.current = 0 return text + ' ' return self.get_completion(text, state) def generate_parameters(self, text, state): if state == 0: self.available = [] self.current = 0 try: line = readline.get_line_buffer()[:readline.get_endidx()].split(' ') cmd = self.manager.find(line[0]) except: return 0 current_params = list(filter(lambda x: len(x.strip()) > 0, line[1:-1] if len(line) > 2 else [])) if ',' in text: text = text.split(',')[-1] for i in cmd.parameters(self.loader, current_params): if i[:len(text)] == text: self.available.append(i) self.available.sort() if len(self.available) == 1: self.available = [] self.current = 0 return text + cmd.parameter_separator(current_params) return self.get_completion(text, state)