perl/python context improvements

--HG--
branch : pmacs2
This commit is contained in:
moculus 2008-05-12 15:34:06 +00:00
parent dc625d6eb5
commit 25cd253693
3 changed files with 50 additions and 192 deletions

View File

@ -20,35 +20,32 @@ class Context(object):
for i in reversed(range(p.y + 1, len(self.mode.window.buffer.lines))): for i in reversed(range(p.y + 1, len(self.mode.window.buffer.lines))):
self.namelines[i] = self.namelines[i - delta] self.namelines[i] = self.namelines[i - delta]
for i in range(p.y, p.y + delta): for i in range(p.y, p.y + delta):
self.namelines[i] = None self.namelines[i] = (None, None)
else: else:
for i in range(p.y + 1, len(self.mode.window.buffer.lines)): for i in range(p.y + 1, len(self.mode.window.buffer.lines)):
self.namelines[i + delta] = self.namelines[i] self.namelines[i + delta] = self.namelines[i]
def _init_name_map(self): def _init_name_map(self):
self.names = {} self.names = {}
self.namelines = [None] * len(self.mode.window.buffer.lines) self.namelines = [(None, None)] * len(self.mode.window.buffer.lines)
def build_name_map(self): def build_name_map(self):
self._init_name_map() self._init_name_map()
self._build_name_map(0, len(self.mode.window.buffer.lines), None, None, []) self._build_name_map(0, len(self.mode.window.buffer.lines), None, None, [])
def _del_name(self, y, name):
if name and name in self.names:
del self.names[name]
self.namelines[y] = (None, None)
def rebuild_name_map(self, y1, y2): def rebuild_name_map(self, y1, y2):
for y in range(y1, y2): for y in range(y1, y2):
name = self.namelines[y] (name, info) = self.namelines[y]
if name: self._del_name(y, name)
if name in self.names:
del self.names[name]
if name in self.classes:
del self.classes[name]
if name in self.functions:
del self.functions[name]
self.namelines[y] = None
if y1 == 0: if y1 == 0:
self._build_name_map(y1, y2, None, None, []) self._build_name_map(y1, y2, None, None, [])
else: else:
last, curr, stack = None, self.namelines[y1 - 1], [] last, curr, stack = None, self.namelines[y1 - 1][0], []
count = 0 count = 0
if curr: if curr:
for part in curr.split('.'): for part in curr.split('.'):
@ -63,7 +60,7 @@ class Context(object):
if self.namelines is None: if self.namelines is None:
self.build_name_map() self.build_name_map()
if y < len(self.namelines): if y < len(self.namelines):
return self.namelines[y] return self.namelines[y][0]
else: else:
return None return None
def get_names(self): def get_names(self):

View File

@ -286,7 +286,7 @@ class PerlGotoFunction(Method):
args = [Argument("name", type(""), "perlfunction", "Goto Function: ")] args = [Argument("name", type(""), "perlfunction", "Goto Function: ")]
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
name = vargs['name'] name = vargs['name']
functions = w.mode.get_functions() functions = w.mode.context.get_names()
if name in functions: if name in functions:
w.goto(Point(0, functions[name])) w.goto(Point(0, functions[name]))
else: else:
@ -295,7 +295,7 @@ class PerlGotoFunction(Method):
class PerlListFunctions(Method): class PerlListFunctions(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.context.get_name_list()
output = "\n".join(names) + "\n" output = "\n".join(names) + "\n"
w.application.data_buffer("*Perl-List-Functions*", output, switch_to=True) w.application.data_buffer("*Perl-List-Functions*", output, switch_to=True)
@ -303,11 +303,11 @@ class PerlWhichFunction(Method):
'''Show the user what function they are in''' '''Show the user what function they are in'''
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
cursor = w.logical_cursor() cursor = w.logical_cursor()
name = w.mode.get_line_function(cursor.y) name = w.mode.context.get_line_name(cursor.y)
if name is None: if name is None:
w.application.set_error("None"); w.application.set_error("None");
else: else:
functions = w.mode.get_functions() functions = w.mode.context.get_names()
i = functions[name] + 1 i = functions[name] + 1
w.application.set_error("line %d: %s" % (i, name)) w.application.set_error("line %d: %s" % (i, name))
@ -389,91 +389,6 @@ class PerlHashCleanup(Method):
w.kill(start_p, end_p) w.kill(start_p, end_p)
w.insert_string(start_p, data) w.insert_string(start_p, data)
class PerlHashCleanup2(Method):
#_hash_parts = (
# (TokenMatch('null', None),),
# (TokenMatch('hash_key', None), TokenMatch('string.start', None)),
# (TokenMatch('null', None),),
# (TokenMatch('delimiter', '=>'),),
# (TokenMatch('null', None),),
#)
def _hash_matchXXX(self, group, line):
i = 0
j = 0
stages = []
while tok_i < len(group):
token = group[i]
name = token.fqname()
data = token.string
k = len(stages)
if k < len(self._hash_parts):
for (name2, data2) in self._hash_parts[k]:
if (name2 is None or name == name2 and
data2 is None or data == data2):
stages.append(line[j:token.x])
j = token.x
else:
stages.append(line[j:])
return stages
i += 1
return None
def _assign_match(self, group):
return None
def _execute(self, w, **vargs):
cursor = w.logical_cursor()
tokens = w.buffer.highlights[w.mode.name()].tokens
if self._hash_match(tokens[cursor.y]):
token_groups = self._parse_hash(w, **vargs)
elif self._assign_match(tokens[cursor.y]):
token_groups = self._parse_assign(w, **vargs)
else:
w.set_error("Not a hash line")
return
ys = token_groups.keys()
ys.sort()
segment_groups = []
for y in ys:
line = w.buffer.lines[y]
segments = []
i = 0
for token in token_groups[y]:
segments.append(line[i:token.x])
i = token.x
segments.append(line[i:])
segment_groups.append(segments)
output = "Lines %d through %d\n%r" % (ys[0] + 1, ys[-1] + 1, segment_groups)
w.application.data_buffer("hash-dump", output, switch_to=True)
def _parse_hash(self, w, **vargs):
cursor = w.logical_cursor()
tokens = w.buffer.highlights[w.mode.name()].tokens
lines = {cursor.y: self._hash_match(tokens[cursor.y])}
y1 = cursor.y
while y1 > 0:
match = self._hash_match(tokens[y1 - 1])
if not match:
break
lines[y1 - 1] = match
y1 -= 1
y2 = cursor.y
while y2 < len(tokens) - 1:
match = self._hash_match(tokens[y2 + 1])
if not match:
break
lines[y2 + 1] = match
y2 += 1
return lines
def _parse_assign(self, w, **vargs):
pass
class PerlWrapParagraph(method.WrapParagraph): class PerlWrapParagraph(method.WrapParagraph):
'''Wrap Comments and POD''' '''Wrap Comments and POD'''
# enumerations for line types # enumerations for line types
@ -575,7 +490,7 @@ class PerlWrapParagraph(method.WrapParagraph):
class PerlFunctionCompleter(completer.Completer): class PerlFunctionCompleter(completer.Completer):
def get_candidates(self, s, w=None): def get_candidates(self, s, w=None):
old_window = w.buffer.method.old_window old_window = w.buffer.method.old_window
functions = old_window.mode.get_functions() functions = old_window.mode.context.get_names()
return [n for n in functions if n.startswith(s)] return [n for n in functions if n.startswith(s)]
class PerlContext(context.Context): class PerlContext(context.Context):
@ -585,56 +500,26 @@ class PerlContext(context.Context):
i = y1 i = y1
while i < y2: while i < y2:
g = highlights.tokens[i] g = highlights.tokens[i]
if (len(g) == 1 and g[0].name == 'eol' or if (not stack and len(g) > 2 and g[0].name == 'perl_keyword' and
len(g) == 2 and g[0].name == 'null' and g[1].name == 'eol'): g[0].string == 'sub' and g[2].name == 'sub'):
if last is None: curr = g[2].string
last = i
i += 1
if i == y2 and y2 < blen:
y2 += 1
continue
if g[0].name == 'null':
j, lvl = 1, len(g[0].string)
else:
j, lvl = 0, 0
while stack and lvl <= stack[-1][0]:
stack.pop(-1)
if last is not None:
curr = '.'.join([x[1] for x in stack])
if curr:
for k in range(last, i):
self.namelines[k] = curr
last = None
if len(g[j:]) > 3:
d, found = None, False
if g[j].name == 'python_keyword' and g[j].string == 'class':
d, found = self.classes, True
elif g[j].name == 'python_keyword' and g[j].string == 'def':
d, found = self.functions, True
if found:
stack.append([lvl, g[j+2].string])
curr = '.'.join([x[1] for x in stack])
d[curr] = i
self.names[curr] = i self.names[curr] = i
else:
curr = '.'.join([x[1] for x in stack])
if i == y2 - 1 and curr != self.namelines[i] and y2 < blen: if i == y2 - 1 and curr != self.namelines[i][0] and y2 < blen:
y2 += 1 y2 += 1
if curr: if curr:
self.namelines[i] = curr self.namelines[i] = (curr, tuple(stack))
i += 1 i += 1
if last is not None and y2 < len(self.namelines): m = self.mode
if self.namelines[y2]: for t in g:
n = len(self.namelines[y2].split('.')) if t.name in m.opentokens and t.string in m.opentags:
curr = '.'.join([x[1] for x in stack[:n]]) stack.append(t.string)
if curr: elif t.name in m.closetokens and t.string in m.closetags:
for k in range(last, y2): assert stack[-1] == m.closetags[t.string]
self.namelines[k] = curr stack.pop(-1)
if not stack:
curr = None
class Perl(mode.Fundamental): class Perl(mode.Fundamental):
modename = 'Perl' modename = 'Perl'
@ -775,47 +660,15 @@ 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', ('}'))
self.context = PerlContext(self)
self.functions = None self.functions = None
self.funclines = None self.funclines = None
def build_function_map(self):
self.functions = {}
self.funclines = []
highlights = self.window.get_highlighter()
curr, stack = None, []
for group in highlights.tokens:
self.funclines.append(curr)
for t in group:
if not curr and t.name == 'sub':
curr = t.string
stack = []
self.functions[curr] = t.y
elif t.name == 'delimiter':
if t.string == '{':
stack.append(None)
elif t.string == '}':
stack.pop()
if not stack:
curr = None
if curr:
self.funclines[-1] = curr
def get_functions(self): def get_functions(self):
if self.functions is None: return self.context.get_names()
self.build_function_map()
return self.functions
def get_function_names(self): def get_function_names(self):
functions = self.get_functions() return self.context.get_name_list()
pairs = [[functions[key], key] for key in functions]
pairs.sort()
names = [x[1] for x in pairs]
return names
def get_line_function(self, y): def get_line_function(self, y):
if self.funclines is None: return self.context.get_line_name(y)
self.build_function_map()
if y < len(self.funclines):
return self.funclines[y]
else:
return None
install = Perl.install install = Perl.install

View File

@ -358,8 +358,16 @@ class PythonContext(context.Context):
self.names = {} self.names = {}
self.classes = {} self.classes = {}
self.functions = {} self.functions = {}
self.namelines = [None] * len(self.mode.window.buffer.lines) self.namelines = [(None, None)] * len(self.mode.window.buffer.lines)
def _del_name(self, y, name):
if name:
if name in self.names:
del self.names[name]
if name in self.classes:
del self.classes[name]
if name in self.functions:
del self.functions[name]
self.namelines[y] = (None, None)
def _build_name_map(self, y1, y2, last, curr, stack): def _build_name_map(self, y1, y2, last, curr, stack):
blen = len(self.mode.window.buffer.lines) blen = len(self.mode.window.buffer.lines)
highlights = self.mode.window.get_highlighter() highlights = self.mode.window.get_highlighter()
@ -386,7 +394,7 @@ class PythonContext(context.Context):
curr = '.'.join([x[1] for x in stack]) curr = '.'.join([x[1] for x in stack])
if curr: if curr:
for k in range(last, i): for k in range(last, i):
self.namelines[k] = curr self.namelines[k] = (curr, None)
last = None last = None
if len(g[j:]) > 3: if len(g[j:]) > 3:
@ -403,19 +411,19 @@ class PythonContext(context.Context):
else: else:
curr = '.'.join([x[1] for x in stack]) curr = '.'.join([x[1] for x in stack])
if i == y2 - 1 and curr != self.namelines[i] and y2 < blen: if i == y2 - 1 and curr != self.namelines[i][0] and y2 < blen:
y2 += 1 y2 += 1
if curr: if curr:
self.namelines[i] = curr self.namelines[i] = (curr, None)
i += 1 i += 1
if last is not None and y2 < len(self.namelines): if last is not None and y2 < len(self.namelines):
if self.namelines[y2]: if self.namelines[y2][0]:
n = len(self.namelines[y2].split('.')) n = len(self.namelines[y2][0].split('.'))
curr = '.'.join([x[1] for x in stack[:n]]) curr = '.'.join([x[1] for x in stack[:n]])
if curr: if curr:
for k in range(last, y2): for k in range(last, y2):
self.namelines[k] = curr self.namelines[k] = (curr, None)
class Python(mode.Fundamental): class Python(mode.Fundamental):
modename = 'Python' modename = 'Python'