tab completion for console

--HG--
branch : pmacs2
This commit is contained in:
moculus 2008-03-16 22:12:29 +00:00
parent d0a22e4909
commit 6cb96eb661
1 changed files with 70 additions and 49 deletions

View File

@ -1,10 +1,12 @@
import code, string, StringIO, sys, traceback
import color, completer, method, mode
import code, re, string, StringIO, sys, traceback
import color, completer, lex, method, mode
from lex import Grammar, PatternRule
from mode.python import PythonGrammar
from point import Point
class ConsoleMini(mode.Fundamental):
modename = 'ConsoleMini'
grammar = PythonGrammar
def __init__(self, w):
mode.Fundamental.__init__(self, w)
self.bindings = {}
@ -46,7 +48,7 @@ class ConsoleMini(mode.Fundamental):
self.add_action_and_bindings(ConsoleCancel(), ('C-]',))
self.add_action_and_bindings(ConsoleHistoryPrev(), ('C-p',))
self.add_action_and_bindings(ConsoleHistoryNext(), ('C-n',))
#self.add_action_and_bindings(ConsoleTab(), ('TAB',))
self.add_action_and_bindings(ConsoleTab(), ('TAB',))
for c in string.letters + string.digits + string.punctuation:
self.add_binding('insert-string-%s' % c, c)
@ -134,50 +136,69 @@ class ConsoleHistoryNext(method.Method):
w.mode.hindex += 1
w.buffer.set_data(w.mode.history[w.mode.hindex])
#class ConsoleTab(method.Method):
# def execute(self, w, **vargs):
# a = w.application
# s = w.buffer.make_string()
#
# if '"' in s or "'" in s or "(" in s or ")" in s or "[" in s or "]" in s:
# return
#
# parts = s.split(".")
# if len(parts) == 0:
# return
#
# v = a.globals()
# v.update(a.locals())
# obj = None
# for part in parts[:-1]:
# if obj is None:
# if part in v:
# obj = v[part]
# else:
# return
# else:
# if hasattr(obj, part):
# obj = getattr(obj, part)
# else:
# return
#
# if obj is None:
# pool = v.keys()
# else:
# pool = dir(obj)
# candidates = [x for x in pool if x.startswith(parts[-1])]
#
# if len(candidates) == 0:
# return
#
# common = completer.find_common_string(candidates)
# s2 = '.'.join(parts[:-1]) + '.' + common
#
# w.buffer.set_data(s2)
#
# if len(candidates) > 1:
# if not a.has_buffer_name('*Console*'):
# a.add_buffer(buffer.ConsoleBuffer())
# b = a.bufferlist.get_buffer_by_name('*Console*')
# b.insert_string(b.get_buffer_end(), repr(candidates) + '\n', force=True)
class ConsoleTab(method.Method):
def execute(self, w, **vargs):
a = w.application
s = w.buffer.make_string()
l = lex.Lexer(w.mode, PythonGrammar)
tokens = list(l.lex([s]))
x = w.logical_cursor().x
#raise Exception, repr(x)
curr_t = None
curr_i = None
for i in range(0, len(tokens)):
t = tokens[i]
if t.x < x and t.end_x() >= x:
curr_i = i
curr_t = t
if curr_t is None:
#raise Exception, 'not found: %r %r' % (x, tokens)
return
first_t = curr_t
j = curr_i
names = [curr_t.string]
name_re = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
while j >= 1:
j -= 1
t = tokens[j]
if name_re.match(t.string):
names.insert(0, t.string)
elif t.string == '.':
pass
else:
break
obj = None
g = globals()
i = 0
name = None
while i < len(names):
name = names[i]
if obj is None:
if name in w.mode.locals:
obj = w.mode.locals[name]
elif name in w.mode.globals:
obj = w.mode.globals[name]
else:
break
else:
if hasattr(obj, name):
obj = getattr(obj, name)
else:
break
i += 1
if obj is not None and i == len(names) - 1:
newnames = dir(obj)
candidates = [x for x in newnames if x.startswith(name)]
if len(candidates) > 1:
s = completer.find_common_string(candidates)[len(name):]
w.insert_string_at_cursor(s)
elif len(candidates) == 1:
s = candidates[0][len(name):]
w.insert_string_at_cursor(s)
install = ConsoleMini.install