import glob import os import util _completers = {} def set_completer(name, completer): global _completers _completers[name] = completer def get_completer(*args): return _completers.get(*args) def find_common_string(candidates): if len(candidates) == 0: return "" elif len(candidates) == 1: return candidates[0] else: index = 0 test = candidates[0] while True: for c in candidates: if len(c) <= index or c[index] != test[index]: return test[:index] index += 1 return test class Completer(object): def __init__(self, application): self.application = application def get_candidates(self, s, w=None): raise Exception("Not implemented") def tab_string(self, s, w=None): '''returns a tuple of three things: 1. the new string 2. whether the string "exists" 3. whether the string is "complete"''' candidates = self.get_candidates(s, w) if len(candidates) == 0: return (s, False, True) elif len(candidates) == 1: return (candidates[0], True, True) else: s2 = find_common_string(candidates) if s2 in candidates: return (s2, True, False) else: return (s2, False, False) class FileCompleter(Completer): def get_candidates(self, s, w=None): s = util.expand_tilde(s) #raise Exception(s + '*') candidates = [util.normal_path(p) for p in glob.glob(s + '*')] # ignore some suffixes by default, unless the only possible completions # ALL have ignored-suffixes, in which case just return them all. candidates2 = [] for c in candidates: ok = True for suffix in self.application.config['ignore_suffix']: if c.endswith(suffix): ok = False break if ok: candidates2.append(c) if candidates2: candidates = candidates2 #raise(s + "* :: " + repr(candidates)) return candidates class BufferCompleter(Completer): def get_candidates(self, s, w=None): bl = self.application.bufferlist candidates = [b.name() for b in bl.buffers if b.name().startswith(s)] return candidates class CommandCompleter(Completer): def __init__(self, application): Completer.__init__(self, application) self.fc = FileCompleter(application) def get_candidates(self, s, w=None): if s.startswith('~') or s.startswith('/') or s.startswith('./') or s.startswith('../'): return self.fc.get_candidates(s) path = os.getenv('PATH') path_dirs = path.split(':') candidates = set() for d in path_dirs: if (not os.path.isdir(d) or not os.access(d, os.R_OK)): continue for p in os.listdir(d): if not os.path.isfile(os.path.join(d, p)): continue elif not p.startswith(s): continue else: candidates.add(p) return sorted(candidates) class ShellCompleter(Completer): def __init__(self, application): Completer.__init__(self, application) self.fc = FileCompleter(application) self.cc = CommandCompleter(application) def get_candidates(self, s, w=None): if ' ' in s: i = s.rindex(' ') + 1 base = s[:i] last = s[i:] candidates = self.fc.get_candidates(last) return [base + x for x in candidates] else: return self.cc.get_candidates(s) class TokenCompleter(Completer): def get_candidates(self, s, w=None): w2 = w.buffer.method.old_window t = w2.get_token2() h = w2.get_highlighter() candidates = {} for line in h.tokens: for t2 in line: if t2 is t: continue elif t2.string.startswith(s): candidates[t2.string] = 1 return candidates.keys() class MethodCompleter(Completer): def get_candidates(self, s, w=None): return [n for n in w.application.methods if n.startswith(s)] class ConfigCompleter(Completer): def get_candidates(self, s, w=None): return [n for n in w.application.config if n.startswith(s)] class RegisterCompleter(Completer): def get_candidates(self, s, w=None): return [n for n in w.application.registers if n.startswith(s)] class ModeCompleter(Completer): def get_candidates(self, s, w=None): return [n for n in w.application.modes if n.startswith(s)]