147 lines
4.7 KiB
Python
147 lines
4.7 KiB
Python
import glob, os, pwd
|
|
import method, 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:
|
|
done = False
|
|
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):
|
|
assert "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)]
|