lots of rendering fixes, more general completion support

--HG--
branch : pmacs2
This commit is contained in:
moculus 2008-04-25 14:20:40 +00:00
parent c8d7bebc05
commit f1308a4d34
6 changed files with 143 additions and 73 deletions

View File

@ -190,19 +190,20 @@ class Application(object):
method.DATATYPES['method'] = completer.MethodCompleter()
method.DATATYPES['register'] = completer.RegisterCompleter()
method.DATATYPES['mode'] = completer.ModeCompleter()
method.DATATYPES['perlfunction'] = completer.PerlFunctionCompleter()
method.DATATYPES['pythonfunction'] = completer.PythonFunctionCompleter()
#method.DATATYPES['perlfunction'] = completer.PerlFunctionCompleter()
# set up curses
self.win = curses.newwin(self.y, self.x, 0, 0)
self.win.leaveok(0)
curses.meta(1)
curses.cbreak()
#curses.halfdelay(5)
curses.noecho()
curses.nonl()
curses.def_prog_mode()
def set_completer(self, datatype, completer):
method.DATATYPES[datatype] = completer
# this sets up a mode, as well as optionally adding information on when to
# auto-load the mode
def setmode(self, name, cls, paths=[], basenames=[], extensions=[], detection=[]):
@ -582,8 +583,8 @@ class Application(object):
x = 0
y += 1
#XYZ
while w.ishidden(y) and y < len(w.buffer.lines):
y += 1
#while w.ishidden(y) and y < len(w.buffer.lines):
# y += 1
else:
x += swidth
count += 1
@ -628,8 +629,8 @@ class Application(object):
x = 0
y += 1
#XYZ
while w.ishidden(y) and y < len(w.buffer.lines):
y += 1
#while w.ishidden(y) and y < len(w.buffer.lines):
# y += 1
else:
x += slot.width
count += 1
@ -665,8 +666,8 @@ class Application(object):
x = 0
y += 1
#XYZ
while w.ishidden(y) and y < len(w.buffer.lines):
y += 1
#while w.ishidden(y) and y < len(w.buffer.lines):
# y += 1
else:
x += slot.width - 1
count += 1
@ -684,9 +685,10 @@ class Application(object):
w = slot.window
redattr = color.build_attr(color.pairs('red', 'default'))
x, y = w.first.xy()
lm, rm = w.mode.lmargin, w.mode.rmargin
lines = w.buffer.lines
count = 0
lm, rm = w.mode.lmargin, w.mode.rmargin
k = x // (slot.width - lm - rm)
modename = w.mode.name()
lit = w.mode.name() in w.buffer.highlights
ended = False
@ -695,7 +697,7 @@ class Application(object):
rlines = w.render_line_lit(y, slot.width - lm - rm)
else:
rlines = w.render_line_raw(y, slot.width - lm - rm)
for j in range(0, len(rlines)):
for j in range(k, len(rlines)):
if lm:
lcont = j > 0
for rstr in slot.window.mode.get_lmargin(w, y, x, ended, lcont):
@ -707,6 +709,9 @@ class Application(object):
for rstr in slot.window.mode.get_rmargin(w, y, x, ended, rcont):
rstr.draw(self.win, slot.y_offset + count, slot.width - rm)
count += 1
if count >= slot.height:
break
k = 0
y += 1
ended = ended or y >= len(w.buffer.lines)

View File

@ -105,15 +105,3 @@ class RegisterCompleter(Completer):
class ModeCompleter(Completer):
def get_candidates(self, s, w=None):
return [n for n in w.application.modes if n.startswith(s)]
class PerlFunctionCompleter(Completer):
def get_candidates(self, s, w=None):
old_window = w.buffer.method.old_window
functions = old_window.mode.get_functions()
return [n for n in functions if n.startswith(s)]
class PythonFunctionCompleter(Completer):
def get_candidates(self, s, w=None):
old_window = w.buffer.method.old_window
functions = old_window.mode.get_functions()
return [n for n in functions if n.startswith(s)]

View File

@ -89,6 +89,7 @@ class Fundamental(Handler):
colors = {}
config = {}
actions = []
completers = {}
# margin/line numbering
show_line_numbers = False
@ -113,6 +114,8 @@ class Fundamental(Handler):
return
else:
app.methods[m.name] = m
for (datatype, completer) in cls.completers.iteritems():
app.set_completer(datatype, completer)
install = classmethod(install)
def __init__(self, w):

View File

@ -1,5 +1,5 @@
import re, sets, string, sys
import color, commands, default, method, mode, regex, tab
import color, commands, completer, default, method, mode, regex, tab
from point import Point
from lex import Grammar, PatternRule, ContextPatternRule, RegionRule, OverridePatternRule, PatternGroupRule
from method import Argument, Method, WrapParagraph
@ -577,6 +577,12 @@ class PerlWrapParagraph(method.WrapParagraph):
else:
w.set_error("did not detect comment or pod lines")
class PerlFunctionCompleter(completer.Completer):
def get_candidates(self, s, w=None):
old_window = w.buffer.method.old_window
functions = old_window.mode.get_functions()
return [n for n in functions if n.startswith(s)]
class Perl(mode.Fundamental):
modename = 'Perl'
extensions = ['.pl', '.pm']
@ -602,32 +608,31 @@ class Perl(mode.Fundamental):
'pod.end': ('red', 'default'),
# basic stuff
'escaped': ('magenta', 'default'),
'null': ('default', 'default'),
#'delimiter': ('default', 'default'),
'sub': ('cyan', 'default'),
'prototype': ('magenta', 'default'),
'number': ('default', 'default'),
'operator': ('default', 'default'),
'noperator': ('magenta', 'default'),
'endblock': ('red', 'default'),
'perl_keyword': ('magenta', 'default'),
'cast': ('yellow', 'default'),
'scalar': ('yellow', 'default'),
'array': ('yellow', 'default'),
'deref': ('yellow', 'default'),
'perl_hash': ('yellow', 'default'),
'hash_key': ('green', 'default'),
'perl_function': ('cyan', 'default'),
'perl_builtin': ('magenta', 'default'),
#'method': ('cyan', 'default'),
#'bareword': ('default', 'default'),
'perl_label': ('cyan', 'default'),
'package': ('cyan', 'default'),
'perl_class': ('cyan', 'default'),
'use': ('cyan', 'default'),
'require': ('cyan', 'default'),
#'method': ('cyan', 'default'),
'escaped': ('magenta', 'default'),
'null': ('default', 'default'),
'sub': ('cyan', 'default'),
'prototype': ('magenta', 'default'),
'number': ('default', 'default'),
'operator': ('default', 'default'),
'noperator': ('magenta', 'default'),
'endblock': ('red', 'default'),
'perl_keyword': ('magenta', 'default'),
'cast': ('yellow', 'default'),
'scalar': ('yellow', 'default'),
'array': ('yellow', 'default'),
'deref': ('yellow', 'default'),
'perl_hash': ('yellow', 'default'),
'hash_key': ('green', 'default'),
'perl_function': ('cyan', 'default'),
'perl_builtin': ('magenta', 'default'),
#'method': ('cyan', 'default'),
#'bareword': ('default', 'default'),
'perl_label': ('cyan', 'default'),
'package': ('cyan', 'default'),
'perl_class': ('cyan', 'default'),
'use': ('cyan', 'default'),
'require': ('cyan', 'default'),
#'method': ('cyan', 'default'),
# heredoc/evaldoc
'heredoc.start': ('green', 'default'),
@ -689,9 +694,11 @@ class Perl(mode.Fundamental):
PerlViewModulePerldoc, PerlViewWordPerldoc, PerlWrapParagraph,
PerlInitFunctions, PerlGotoFunction, PerlWhichFunction,
PerlListFunctions]
completers = {
'perlfunction': PerlFunctionCompleter(),
}
def __init__(self, w):
mode.Fundamental.__init__(self, w)
self.add_bindings('perl-set-lib', ('C-c l',))
self.add_bindings('perl-check-syntax', ('C-c s',))
self.add_bindings('perl-hash-cleanup', ('C-c h',))
@ -705,8 +712,6 @@ class Perl(mode.Fundamental):
self.add_bindings('close-paren', (')'))
self.add_bindings('close-bracket', (']'))
self.add_bindings('close-brace', ('}'))
# perl-specific
self.functions = None
def build_function_map(self):

View File

@ -173,12 +173,24 @@ class PythonTabber(tab.StackTabber):
self._append(token.string, currlvl + w)
return currlvl
class PythonInitFunctions(method.Method):
class PythonInitNames(method.Method):
'''Jump to a function defined in this module'''
def _execute(self, w, **vargs):
w.mode.build_function_map()
w.application.set_error("Initialized function map")
w.mode.build_name_map()
w.application.set_error("Initialized name maps")
class PythonGotoName(method.Method):
'''Jump to a class or function defined in this module'''
args = [method.Argument("name", type(""), "pythonname", "Goto Name: ")]
def _execute(self, w, **vargs):
name = vargs['name']
d = {}
d.update(w.mode.get_classes())
d.update(w.mode.get_functions())
if name in d:
w.goto(Point(0, d[name]))
else:
w.application.set_error("Function %r was not found" % name)
class PythonGotoFunction(method.Method):
'''Jump to a function defined in this module'''
args = [method.Argument("name", type(""), "pythonfunction", "Goto Function: ")]
@ -189,13 +201,24 @@ class PythonGotoFunction(method.Method):
w.goto(Point(0, functions[name]))
else:
w.application.set_error("Function %r was not found" % name)
class PythonGotoClass(method.Method):
'''Jump to a class defined in this module'''
args = [method.Argument("name", type(""), "pythonclass", "Goto Class: ")]
def _execute(self, w, **vargs):
name = vargs['name']
classes = w.mode.get_classes()
if name in classes:
w.goto(Point(0, classes[name]))
else:
w.application.set_error("Class %r was not found" % name)
class PythonListFunctions(method.Method):
class PythonListNames(method.Method):
'''Show the user all functions defined in this module'''
def _execute(self, w, **vargs):
names = w.mode.get_function_names()
output = "\n".join(names) + "\n"
w.application.data_buffer("*Python-List-Functions*", output, switch_to=True)
names.extend(w.mode.get_class_names())
output = '\n'.join(sorted(names)) + "\n"
w.application.data_buffer("*Python-List-Names*", output, switch_to=True)
class PythonCheckSyntax(method.Method):
'''Check the syntax of the current python file'''
@ -307,6 +330,24 @@ class PythonInsertTripleDquotes(method.Method):
for i in range(0, 3):
w.backward()
class PythonFunctionCompleter(completer.Completer):
def get_candidates(self, s, w=None):
old_window = w.buffer.method.old_window
functions = old_window.mode.get_functions()
return [n for n in functions if n.startswith(s)]
class PythonClassCompleter(completer.Completer):
def get_candidates(self, s, w=None):
old_window = w.buffer.method.old_window
classes = old_window.mode.get_classes()
return [n for n in classes if n.startswith(s)]
class PythonNameCompleter(completer.Completer):
def get_candidates(self, s, w=None):
old_window = w.buffer.method.old_window
names = []
names.extend(old_window.mode.get_classes())
names.extend(old_window.mode.get_functions())
return [n for n in names if n.startswith(s)]
class Python(mode.Fundamental):
modename = 'Python'
extensions = ['.py']
@ -332,26 +373,34 @@ class Python(mode.Fundamental):
config = {
'python.lib': '.',
}
actions = [PythonInitFunctions, PythonListFunctions, PythonGotoFunction,
PythonCheckSyntax, PythonDictCleanup, PythonInsertTripleSquotes,
PythonInsertTripleDquotes]
actions = [PythonInitNames, PythonListNames, PythonGotoName,
PythonGotoFunction, PythonGotoClass, PythonCheckSyntax,
PythonDictCleanup,
PythonInsertTripleSquotes, PythonInsertTripleDquotes]
completers = {
"pythonname": PythonNameCompleter(),
"pythonfunction": PythonFunctionCompleter(),
"pythonclass": PythonClassCompleter(),
}
def __init__(self, w):
mode.Fundamental.__init__(self, w)
# tag matching
self.add_bindings('close-paren', (')',))
self.add_bindings('close-brace', ('}',))
self.add_bindings('close-bracket', (']',))
# add python-specific methods
self.add_bindings('python-goto-function', ('C-c M-g',))
self.add_bindings('python-goto-name', ('C-c M-g',))
self.add_bindings('python-goto-function', ('C-c M-f',))
self.add_bindings('python-goto-class', ('C-c M-c',))
self.add_bindings('python-check-syntax', ('C-c s',))
self.add_bindings('python-dict-cleanup', ('C-c h',))
self.add_bindings('python-insert-triple-squotes', ('C-c M-\'',))
self.add_bindings('python-insert-triple-dquotes', ('C-c M-"',))
# other python
self.classes = None
self.functions = None
def build_function_map(self):
b = self.window.buffer
scope_stack = []
def build_name_map(self):
b = self.window.buffer
scope_stack = []
self.classes = {}
self.functions = {}
for i in range(0, len(b.lines)):
if regex.whitespace.match(b.lines[i]):
@ -368,15 +417,20 @@ class Python(mode.Fundamental):
if m:
(ws, typ, name) = m.groups()
lvl = len(ws)
if typ == 'class':
#raise Exception, repr(m.groups())
d = self.classes
else:
d = self.functions
if scope_stack:
prefix = '.'.join([x[1] for x in scope_stack])
self.functions['%s.%s' % (prefix, name)] = i
d['%s.%s' % (prefix, name)] = i
else:
self.functions[name] = i
d[name] = i
scope_stack.append((len(ws), name))
def get_functions(self):
if self.functions is None:
self.build_function_map()
self.build_name_map()
return self.functions
def get_function_names(self):
functions = self.get_functions()
@ -384,5 +438,15 @@ class Python(mode.Fundamental):
pairs.sort()
names = [x[1] for x in pairs]
return names
def get_classes(self):
if self.classes is None:
self.build_name_map()
return self.classes
def get_class_names(self):
classes = self.get_classes()
pairs = [[classes[key], key] for key in classes]
pairs.sort()
names = [x[1] for x in pairs]
return names
install = Python.install

View File

@ -9,4 +9,9 @@ class RenderString(object):
self.x = x
self.attrs = attrs
def draw(self, cwin, y, x):
cwin.addstr(y, self.x + x, self.string, self.attrs)
try:
cwin.addstr(y, self.x + x, self.string, self.attrs)
except:
#return
raise Exception, "cwin.addstr(%d, %d + %d, %r, %r) failed" % \
(y, self.x, x, self.string, self.attrs)