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
from point2 import Point
@ -810,43 +810,47 @@ class CodeComplete(Method):
if len(w.buffer.lines[cursor.y]) == 0:
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 = {}
sofar = None
tokens = w.mode.highlighter.get_tokens()
for token in tokens:
s = token.string
if s == word:
continue
elif s.startswith(word):
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]
bounds = w.get_word_bounds()
if bounds is None:
return
(p1, p2) = bounds
buffer = w.buffer
word = buffer.get_substring(p1, p2)
app = w.application
highlighter = buffer.highlights[w.mode.name()]
tokens = highlighter.tokens
seen = {}
sofar = None
for group in tokens:
for token in group:
s = token.string
if s == word:
continue
elif s.startswith(word):
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()
num_seen = len(seen_keys)
num_seen = len(seen_keys)
if word == sofar:
#w.application.set_error('No completion possible: %r' % word)
pass
elif sofar:
w.buffer.delete_string(p1, p2)
w.buffer.insert_string_at_cursor(p1, sofar)
w.buffer.delete(p1, p2)
w.buffer.insert_string(p1, sofar)
if num_seen == 1:
w.application.set_error('Unique!')
else:
@ -1289,10 +1293,9 @@ class SomethingCrazy(Method):
pass
class CloseTag(Method):
tags = {'(': ')',
'{': '}',
'[': ']'}
mytag = ')'
opentags = {'(': ')', '{': '}', '[': ']'}
closetags = {')': '(', '}': '{', ']': '['}
mytag = ')'
def _execute(self, w, **vargs):
# if w.mode doesn't do tag matching, just insert the character return
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
# expecected that the cursor variable should be the point the new
# character is on.
buffer = w.buffer
#cursor = w.physical_cursor()
tag_stack = []
(x, y) = w.logical_cursor().xy()
w.insert_string_at_cursor(self.mytag)
cursor = w.physical_cursor()
assert cursor.x > 0, "my assumptions made an ass out of u and me"
app = w.application
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
found = False
while i < len(regions[cursor.y]):
r = regions[cursor.y][i]
if r[0] == cursor.x - 1 and r[1] == cursor.x and r[3] == self.mytag:
found = True
while i < len(tokens[y]):
token = tokens[y][i]
if token.x == x and token.string == self.mytag:
break
elif r[0] <= cursor.x - 1and r[1] >= cursor.x:
# in this case, we weren't adding a closing tag, but something
# else (a parenthesis in a comment or string, for instance)
elif token.x <= x and token.end_x() > x:
app.set_error('found non-match: %r %d,%d' % (token.string, i, y))
return
i += 1
assert found, "fascinizing: %d %s" % \
(cursor.x, repr(regions[cursor.y][-3:]))
if i >= len(tokens[y]):
app.set_error('none found: %d' % (i))
return
# note that the first region we parse should be the region we just added
# (and which we already verified existed), namely the region at index i.
j = cursor.y
while j >= 0:
if j == cursor.y:
index = i
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 = []
while y >= 0:
while i >= 0 and i < len(tokens[y]):
token = tokens[y][i]
s = token.string
if token.string in self.closetags:
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:
break
else:
index -= 1
if len(tag_stack) == 0:
break
else:
j -= 1
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')
p = Point(token.x, y)
w.set_active_point(p, msg='match found at (%(y)d, %(x)d)')
return
i -= 1
y -= 1
i = len(tokens[y]) - 1
app.set_error('tag mismatch: no tag found')
class CloseParen(CloseTag):
mytag = ')'
class CloseBrace(CloseTag):
mytag = '}'
class CloseBracket(CloseTag):
mytag = ']'

View File

@ -294,6 +294,26 @@ class Window(object):
p = self.find_right_word()
if p is not None:
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
def _pshift_up(self, p, num):