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

View File

@ -105,15 +105,3 @@ class RegisterCompleter(Completer):
class ModeCompleter(Completer): class ModeCompleter(Completer):
def get_candidates(self, s, w=None): def get_candidates(self, s, w=None):
return [n for n in w.application.modes if n.startswith(s)] 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 = {} colors = {}
config = {} config = {}
actions = [] actions = []
completers = {}
# margin/line numbering # margin/line numbering
show_line_numbers = False show_line_numbers = False
@ -113,6 +114,8 @@ class Fundamental(Handler):
return return
else: else:
app.methods[m.name] = m app.methods[m.name] = m
for (datatype, completer) in cls.completers.iteritems():
app.set_completer(datatype, completer)
install = classmethod(install) install = classmethod(install)
def __init__(self, w): def __init__(self, w):

View File

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

View File

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

View File

@ -9,4 +9,9 @@ class RenderString(object):
self.x = x self.x = x
self.attrs = attrs self.attrs = attrs
def draw(self, cwin, y, x): 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)