fixed search/replace, etc

--HG--
branch : pmacs2
This commit is contained in:
moculus 2007-07-06 18:34:14 +00:00
parent 7f5734e1f2
commit e5b8bf9239
7 changed files with 143 additions and 209 deletions

View File

@ -655,10 +655,10 @@ class Application(object):
perc = "%2d%%" % (first.y*100 / len(b.lines))
# XYZ: we should actually use more of the 'state' variables
#format = "%s %-18s (%s)--L%d--C%d--%s"
#status = format % (modflag, name, w.mode.name(), cursor.y+1, cursor.x+1, perc)
format = "%s %-18s (%s)--L%d--C%d--%s %s %s %s"
status = format % (modflag, name, w.mode.name(), cursor.y+1, cursor.x+1, perc, w.first, cursor, w.last)
format = "%s %-18s (%s)--L%d--C%d--%s"
status = format % (modflag, name, w.mode.name(), cursor.y+1, cursor.x+1, perc)
#format = "%s %-18s (%s)--L%d--C%d--%s %s %s %s"
#status = format % (modflag, name, w.mode.name(), cursor.y+1, cursor.x+1, perc, w.first, cursor, w.last)
status = status[:slot.width + 1]
status += "-" * (slot.width - len(status) + 1)

View File

@ -81,7 +81,6 @@ class PythonTabber(tab2.StackTabber):
# if we were continuing, let's pop that previous continuation token
# and note that we're continuing
if self.markers and self.markers[-1].name == 'cont':
raise Exception, repr(self.markers)
self.continued = True
self._pop()
# if we haven't reached the target-line yet, we can detect how many

View File

@ -1,6 +1,6 @@
import sets, string
import color, method, minibuffer, mode2
import color, method, minibuffer, mode2, search
from point2 import Point
class Replace(mode2.Fundamental):
@ -11,51 +11,39 @@ class Replace(mode2.Fundamental):
self.actions = {}
self.bindings = {}
default_actions = (
(ReplaceAll(), ('a', '!',)),
(ReplaceOne(), ('y', 'SPACE',)),
(SkipReplace(), ('n', 'DELETE',)),
(CancelReplace(), ('q', 'RETURN', 'C-]', 'C-n', 'C-p', 'C-a', 'C-e',
'C-f', 'C-b')),
)
# add the replace actions
for pair in default_actions:
(action, sequences) = pair
assert type(sequences) == type(()), repr(pair)
self.add_action_and_bindings(action, sequences)
self.add_action_and_bindings(ReplaceAll(), ('a', '!',))
self.add_action_and_bindings(ReplaceOne(), ('y', 'SPACE',))
self.add_action_and_bindings(SkipReplace(), ('n', 'DELETE',))
self.add_action_and_bindings(CancelReplace(), ('q', 'RETURN', 'C-]', 'C-n', 'C-p', 'C-a', 'C-e', 'C-f', 'C-b'))
_find_next(w, False)
if w.buffer.method.p1 is None:
w.application.set_error('%r was not found')
m = w.buffer.method
found = _find_next(m, move=False)
if not found:
w.application.set_error('%r was not found' % m.before)
raise minibuffer.MiniBufferError
_set_prompt(w.buffer.method, w.buffer.method.old_window)
_set_prompt(m)
def name(self):
return "Replace"
class ReplaceOne(method.Method):
def execute(self, w, **vargs):
m = w.buffer.method
old_window = m.old_window
_replace(m, old_window)
_find_next(w, True)
_finish(m, w, old_window)
_replace(m)
_find_next(m, True)
_finish(m, w)
class SkipReplace(method.Method):
def execute(self, w, **vargs):
m = w.buffer.method
old_window = m.old_window
_find_next(w, True)
_finish(m, w, old_window)
_find_next(m, True)
_finish(m, w)
class ReplaceAll(method.Method):
def execute(self, w, **vargs):
m = w.buffer.method
old_window = m.old_window
while m.p1 is not None:
_replace(m, old_window)
_find_next(w, True)
_replace(m)
_find_next(m, True)
_end(w)
w.application.set_error("Replace ended")
@ -64,7 +52,19 @@ class CancelReplace(method.Method):
_end(w)
w.application.set_error("Replace cancelled")
def _set_prompt(m, w):
def _find_next(m, move=False):
s = m.before
w = m.old_window
newc = search._find_next(s, w, move)
if newc:
(m.p1, m.p2) = newc
return True
else:
(m.p1, m.p2) = (None, None)
return False
def _set_prompt(m):
w = m.old_window
if m.p1 is None:
w.application.mini_prompt = '%r was not found' % m.before
return
@ -80,54 +80,17 @@ def _set_prompt(m, w):
p = 'Replace %r with %r [ynaq] (1 occurance)?' % (m.before, m.after)
w.application.mini_prompt = p
def _replace(m, old_window):
old_window.buffer.delete(m.p1, m.p2)
def _replace(m):
m.old_window.buffer.delete(m.p1, m.p2)
if m.after:
old_window.buffer.insert_string(m.p1, m.after)
m.old_window.buffer.insert_string(m.p1, m.after)
def _find_next(w, move=False):
m = w.buffer.method
old_window = m.old_window
b = old_window.buffer
s = m.before
c = old_window.logical_cursor()
(x, y) = (c.x, c.y)
if move:
x += 1
l = b.lines[y][x:]
# for each line available
while y < len(b.lines):
if s in l:
# success
x = x + l.index(s)
x2 = x + len(s)
m.p1 = Point(x, y)
m.p2 = Point(x2, y)
old_window.goto(m.p1)
old_window.application.clear_highlighted_ranges()
old_window.application.add_highlighted_range(old_window, m.p1, m.p2)
#old_window.application.highlighted_range = [old_window, m.p1, m.p2]
_set_prompt(m, old_window)
return
elif y >= len(b.lines) - 1:
# failure
break
else:
# keep trying
y += 1
l = b.lines[y]
x = 0
m.p1 = None
m.p2 = None
def _finish(m, w, old_window):
def _finish(m, w):
if m.p1 is None:
_end(w)
w.application.set_error("Replace ended")
else:
_set_prompt(m, old_window)
_set_prompt(m)
def _end(w):
w.application.close_mini_buffer()

View File

@ -1,8 +1,11 @@
import sets, string
import color, method, minibuffer, mode2
import color, method, minibuffer, mode2, search
from point2 import Point
selected_color = 'magenta'
unselected_color = 'yellow'
class Search(mode2.Fundamental):
'''This is the default mode'''
def __init__(self, w):
@ -35,8 +38,9 @@ class SearchNext(method.Method):
if not w.buffer.make_string():
w.buffer.set_data(w.application.last_search)
else:
old_w = w.buffer.method.old_window
_find_next(old_w, w, move=True)
s = w.buffer.make_string()
w2 = w.buffer.method.old_window
search.find_next(s, w2, move=True)
class SearchPrevious(method.Method):
def execute(self, w, **vargs):
@ -44,8 +48,9 @@ class SearchPrevious(method.Method):
if not w.buffer.make_string():
return
else:
old_w = w.buffer.method.old_window
_find_previous(old_w, w, move=True)
s = w.buffer.make_string()
w2 = w.buffer.method.old_window
search.find_previous(s, w2, move=True)
class EndSearch(method.Method):
def execute(self, w, **vargs):
@ -75,10 +80,13 @@ def _post_delete(w):
old_w.goto(old_cursor)
if not w.buffer.make_string():
w.application.clear_highlighted_ranges()
elif w.buffer.method.direction == 'next':
_find_next(old_w, w, move=False)
return
s = w.buffer.make_string()
w2 = w.buffer.method.old_window
if w.buffer.method.direction == 'next':
search.find_next(s, w2, move=False)
else:
_find_previous(old_w, w, move=False)
search.find_previous(s, w2, move=False)
class InsertSearchString(method.Method):
def __init__(self, s):
@ -92,11 +100,12 @@ class InsertSearchString(method.Method):
if not s:
return
else:
old_w = w.buffer.method.old_window
s = w.buffer.make_string()
w2 = w.buffer.method.old_window
if w.buffer.method.direction == 'next':
_find_next(old_w, w, move=False)
search.find_next(s, w2, move=False)
else:
_find_previous(old_w, w, move=False)
search.find_previous(s, w2, move=False)
def _end(w):
w.application.close_mini_buffer()
@ -104,113 +113,3 @@ def _end(w):
w.application.last_search = w.buffer.make_string()
w.buffer.method.old_cursor = None
w.buffer.method.old_window = None
def _find_ranges(w, s):
(x, y) = (0, 0)
ranges = []
while y < len(w.buffer.lines):
while x < len(w.buffer.lines[y]):
try:
i = w.buffer.lines[y].index(s, x)
x = i + len(s)
ranges.append([Point(i, y), Point(x, y), 'black', 'white'])
except ValueError:
break
x = 0
y += 1
return ranges
def _find(old_w, new_w, move=False, direction='next'):
# DOESN'T WORK WELL FOR NEXT
app = old_w.application
s = new_w.buffer.make_string()
c = old_w.logical_cursor()
(x, y) = c.xy()
newc = None
ranges = _find_ranges(old_w, s)
indices = range(0, len(ranges))
if direction == 'next':
if move:
limit = Point(x, y)
else:
limit = Point(x - 1, y)
else:
if move:
limit = Point(x + len(s), y)
else:
limit = Point(x + len(s) + 1, y)
indices.reverse()
for i in indices:
if (direction == 'next' and ranges[i][0] > limit) or ranges[i][1] < limit:
ranges[i][3] = 'magenta'
newc = ranges[i][0]
break
if ranges and not newc:
return
app.clear_highlighted_ranges()
if newc:
old_w.goto(newc)
for (p1, p2, fg, bg) in ranges:
if p1 < old_w.first:
continue
elif p2 > old_w.last:
break
app.add_highlighted_range(old_w, p1, p2, fg, bg)
def _find_previous(old_w, new_w, move=False):
return _find(old_w, new_w, move, 'previous')
app = old_w.application
s = new_w.buffer.make_string()
c = old_w.logical_cursor()
(x, y) = c.xy()
if move:
x -= 1
limit = Point(x + len(s) + 1, y)
newc = None
ranges = _find_ranges(old_w, s)
l = len(ranges) - 1
for i in range(0, len(ranges)):
if ranges[l - i][1] < limit:
ranges[l - i][3] = 'magenta'
newc = ranges[l - i][0]
break
if ranges and not newc:
return
app.clear_highlighted_ranges()
if newc:
old_w.goto(newc)
for (p1, p2, fg, bg) in ranges:
if p1 < old_w.first:
continue
elif p2 > old_w.last:
break
app.add_highlighted_range(old_w, p1, p2, fg, bg)
def _find_next(old_w, new_w, move=False):
#return _find(old_w, new_w, move, 'next') # in time
app = old_w.application
s = new_w.buffer.make_string()
c = old_w.logical_cursor()
(x, y) = c.xy()
if move:
x += 1
limit = Point(x - 1, y)
newc = None
ranges = _find_ranges(old_w, s)
l = len(ranges) - 1
for i in range(0, len(ranges)):
if ranges[i][0] > limit:
ranges[i][3] = 'magenta'
newc = ranges[i][0]
break
if ranges and not newc:
return
app.clear_highlighted_ranges()
if newc:
old_w.goto(newc)
for (p1, p2, fg, bg) in ranges:
if p1 < old_w.first:
continue
elif p2 > old_w.last:
break
app.add_highlighted_range(old_w, p1, p2, fg, bg)

View File

@ -1,4 +1,5 @@
class Point(tuple):
'''Represents an (x,y) coordinate'''
def __new__(cls, x, y):
return tuple.__new__(cls, (y, x))
def __getattr__(self, name):
@ -14,13 +15,18 @@ class Point(tuple):
return '(%d,%d)' % (self[1], self[0])
def xy(self):
'''Returns a tuple (x,y)'''
return (self[1], self[0])
def add(self, x, y):
assert x >= 0, y >= 0
return Point(self[1] + x, self[0] + y)
def vadd(self, x, y):
assert x >= 0, y >= 0
if y > 0:
return Point(x, self[0] + y)
def yx(self):
'''Returns a tuple (x,y)'''
return tuple(self)
def add(self, xdelta, ydelta):
'''Returns a new point, applying xdelta and ydelta'''
return Point(self[1] + xdelta, self[0] + ydelta)
def vadd(self, xdelta, ydelta):
'''Returns a new point. If ydelta > 0, xdelta is absolute; otherwise, xdelta is relative'''
assert xdelta >= 0 and ydelta >= 0, str((xdelta, ydelta))
if ydelta != 0:
return Point(xdelta, self[0] + ydelta)
else:
return Point(self[1] + x, self[0])
return Point(self[1] + xdelta, self[0])

63
search.py Normal file
View File

@ -0,0 +1,63 @@
from point2 import Point
bg_color = 'black'
selected_color = 'magenta'
unselected_color = 'yellow'
def find_ranges(s, w):
(x, y) = (0, 0)
ranges = []
while y < len(w.buffer.lines):
while x < len(w.buffer.lines[y]):
try:
i = w.buffer.lines[y].index(s, x)
x = i + len(s)
ranges.append([Point(i, y), Point(x, y), bg_color, unselected_color])
except ValueError:
break
x = 0
y += 1
return ranges
def find(s, w, move=False, direction='next'):
app = w.application
c = w.logical_cursor()
newc = None
ranges = find_ranges(s, w)
indices = range(0, len(ranges))
(x, y) = c.xy()
if direction == 'next':
if move:
limit = Point(x, y)
else:
limit = Point(x - 1, y)
else:
if move:
limit = Point(x + len(s), y)
else:
limit = Point(x + len(s) + 1, y)
indices.reverse()
for i in indices:
if ((direction == 'next' and ranges[i][0] > limit) or
(direction != 'next' and ranges[i][1] < limit)):
ranges[i][3] = selected_color
newc = (ranges[i][0], ranges[i][1])
break
if ranges and not newc:
return None
app.clear_highlighted_ranges()
if newc:
w.goto(newc[0])
for (p1, p2, fg, bg) in ranges:
if p1 < w.first:
continue
elif p2 > w.last:
break
app.add_highlighted_range(w, p1, p2, fg, bg)
return newc
def find_previous(s, w, move=False):
return find(s, w, move, 'previous')
def find_next(s, w, move=False):
return find(s, w, move, 'next')

View File

@ -3,7 +3,6 @@ import regex
from point2 import Point
WORD_LETTERS = list(string.letters + string.digits)
#WORD_LETTERS = string.letters + string.digits + "_"
# note about the cursor: the cursor position will insert in front of the
# character it highlights. to this end, it needs to be able to highlight behind
@ -350,6 +349,9 @@ class Window(object):
else:
x += self.width
counter += 1
if y == len(self.buffer.lines):
y -= 1
x = len(self.buffer.lines[y])
return Point(orig_x, y)
def page_up(self):
first_point = self.buffer.get_buffer_start()
@ -418,8 +420,10 @@ class Window(object):
(x, y) = (0, 0)
break
counter += 1
self.first = Point(x - (x % self.width), y)
self.redraw()
if not self.cursor_is_visible():
self.first = Point(x - (x % self.width), y)
self.redraw()
# mark manipulation
def set_mark_point(self, p):