tag-matching and code-complete fixed

--HG--
branch : pmacs2
This commit is contained in:
moculus 2007-06-17 13:49:52 +00:00
parent 214ee106aa
commit 6847df5dff
2 changed files with 91 additions and 86 deletions

157
method.py
View File

@ -1,4 +1,4 @@
import os, commands, popen2, re import os, commands, popen2, re, sets
import buffer2, default, regex, util, window2 import buffer2, default, regex, util, window2
from point2 import Point from point2 import Point
@ -810,43 +810,47 @@ class CodeComplete(Method):
if len(w.buffer.lines[cursor.y]) == 0: if len(w.buffer.lines[cursor.y]) == 0:
return return
elif cursor.x == 0:
p1 = w.find_left_word(cursor.offset(1, 0))
p2 = w.find_right_word()
else:
p1 = w.find_left_word()
p2 = w.find_right_word(cursor.offset(-1, 0))
word = w.buffer.get_substring(p1, p2)
seen = {} bounds = w.get_word_bounds()
sofar = None if bounds is None:
tokens = w.mode.highlighter.get_tokens() return
for token in tokens:
s = token.string (p1, p2) = bounds
if s == word: buffer = w.buffer
continue word = buffer.get_substring(p1, p2)
elif s.startswith(word): app = w.application
seen[s] = True highlighter = buffer.highlights[w.mode.name()]
if sofar is None: tokens = highlighter.tokens
sofar = s seen = {}
else: sofar = None
l = min(len(s), len(sofar))
i = len(word) for group in tokens:
while i < l: for token in group:
if s[i] == sofar[i]: s = token.string
i += 1 if s == word:
else: continue
break elif s.startswith(word):
sofar = s[:i] seen[s] = True
if sofar is None:
sofar = s
else:
l = min(len(s), len(sofar))
i = len(word)
while i < l:
if s[i] == sofar[i]:
i += 1
else:
break
sofar = s[:i]
seen_keys = seen.keys() seen_keys = seen.keys()
num_seen = len(seen_keys) num_seen = len(seen_keys)
if word == sofar: if word == sofar:
#w.application.set_error('No completion possible: %r' % word) #w.application.set_error('No completion possible: %r' % word)
pass pass
elif sofar: elif sofar:
w.buffer.delete_string(p1, p2) w.buffer.delete(p1, p2)
w.buffer.insert_string_at_cursor(p1, sofar) w.buffer.insert_string(p1, sofar)
if num_seen == 1: if num_seen == 1:
w.application.set_error('Unique!') w.application.set_error('Unique!')
else: else:
@ -1289,10 +1293,9 @@ class SomethingCrazy(Method):
pass pass
class CloseTag(Method): class CloseTag(Method):
tags = {'(': ')', opentags = {'(': ')', '{': '}', '[': ']'}
'{': '}', closetags = {')': '(', '}': '{', ']': '['}
'[': ']'} mytag = ')'
mytag = ')'
def _execute(self, w, **vargs): def _execute(self, w, **vargs):
# if w.mode doesn't do tag matching, just insert the character return # if w.mode doesn't do tag matching, just insert the character return
if not w.mode.tag_matching: if not w.mode.tag_matching:
@ -1303,70 +1306,52 @@ class CloseTag(Method):
# NOTE: we derence the cursor *before* inserting the character, so it is # NOTE: we derence the cursor *before* inserting the character, so it is
# expecected that the cursor variable should be the point the new # expecected that the cursor variable should be the point the new
# character is on. # character is on.
buffer = w.buffer (x, y) = w.logical_cursor().xy()
#cursor = w.physical_cursor()
tag_stack = []
w.insert_string_at_cursor(self.mytag) w.insert_string_at_cursor(self.mytag)
cursor = w.physical_cursor() app = w.application
assert cursor.x > 0, "my assumptions made an ass out of u and me" buffer = w.buffer
highlighter = buffer.highlights[w.mode.name()]
tokens = highlighter.tokens
# find the token for the current region, to see if it is a parenthesis
# token or not. if not (i.e. part of a comment or string) then return.
regions = w.mode.get_regions()
assert len(regions[cursor.y]) > 0, "no regions found; strange"
i = 0 i = 0
found = False while i < len(tokens[y]):
while i < len(regions[cursor.y]): token = tokens[y][i]
r = regions[cursor.y][i] if token.x == x and token.string == self.mytag:
if r[0] == cursor.x - 1 and r[1] == cursor.x and r[3] == self.mytag:
found = True
break break
elif r[0] <= cursor.x - 1and r[1] >= cursor.x: elif token.x <= x and token.end_x() > x:
# in this case, we weren't adding a closing tag, but something app.set_error('found non-match: %r %d,%d' % (token.string, i, y))
# else (a parenthesis in a comment or string, for instance)
return return
i += 1 i += 1
assert found, "fascinizing: %d %s" % \ if i >= len(tokens[y]):
(cursor.x, repr(regions[cursor.y][-3:])) app.set_error('none found: %d' % (i))
return
# note that the first region we parse should be the region we just added tag_stack = []
# (and which we already verified existed), namely the region at index i. while y >= 0:
j = cursor.y while i >= 0 and i < len(tokens[y]):
while j >= 0: token = tokens[y][i]
if j == cursor.y: s = token.string
index = i if token.string in self.closetags:
else:
index = len(regions[j]) - 1
while index >= 0:
region = regions[j][index]
s = region[3]
if s in self.tags:
if tag_stack[-1] == self.tags[s]:
tag_stack.pop(-1)
else:
msg = "tag mismatch: %r vs. %r" % (s, tag_stack[-1])
raise Exception, msg
elif s == ')' or s == ']' or s == '}':
tag_stack.append(s) tag_stack.append(s)
elif token.string in self.opentags:
if tag_stack[-1] == self.opentags[s]:
del tag_stack[-1]
else:
app.set_error("tag mismatch; got %r expected %r" %
s, self.close_tags[tag_stack[-1]])
return
if len(tag_stack) == 0: if len(tag_stack) == 0:
break p = Point(token.x, y)
else: w.set_active_point(p, msg='match found at (%(y)d, %(x)d)')
index -= 1 return
if len(tag_stack) == 0: i -= 1
break y -= 1
else: i = len(tokens[y]) - 1
j -= 1 app.set_error('tag mismatch: no tag found')
assert len(tag_stack) == 0, "no match for %r found" % (tag_stack[0])
p = w.logical_point(Point(region[0], j))
w.set_active_point(p, msg='match found on line %(y)d, at character %(x)d')
class CloseParen(CloseTag): class CloseParen(CloseTag):
mytag = ')' mytag = ')'
class CloseBrace(CloseTag): class CloseBrace(CloseTag):
mytag = '}' mytag = '}'
class CloseBracket(CloseTag): class CloseBracket(CloseTag):
mytag = ']' mytag = ']'

View File

@ -294,6 +294,26 @@ class Window(object):
p = self.find_right_word() p = self.find_right_word()
if p is not None: if p is not None:
self.goto(p) self.goto(p)
def get_word_bounds_at_point(self, p):
if len(self.buffer.lines[p.y]) == 0:
return
elif p.x == 0:
p1 = self.find_left_word(Point(p.x + 1, p.y))
p2 = self.find_right_word()
else:
p1 = self.find_left_word()
p2 = self.find_right_word(Point(p.x - 1, p.y))
return (p1, p2)
def get_word_at_point(self, p):
bounds = self.get_word_bounds_at_point(p)
if bounds is None:
return None
else:
return self.buffer.get_substring(bounds[0], bounds[1])
def get_word_bounds(self):
return self.get_word_bounds_at_point(self.logical_cursor())
def get_word(self):
return self.get_word_at_point(self.logical_cursor())
# page up/down # page up/down
def _pshift_up(self, p, num): def _pshift_up(self, p, num):