pmacs3/mode_search.py

184 lines
6.5 KiB
Python

import sets, string
import color, highlight, method, minibuffer, mode, point
class Search(mode.Fundamental):
'''This is the default mode'''
def __init__(self, w):
mode.Fundamental.__init__(self, w)
self.actions = {}
self.bindings = {}
default_actions = (
(SearchNext(), ('C-s',)),
(SearchPrevious(), ('C-r',)),
(EndSearch(), ('RETURN', 'C-n', 'C-p', 'C-a', 'C-e', 'C-f', 'C-b')),
(CancelSearch(), ('C-]',)),
(DeleteLeft(), ('DELETE', 'BACKSPACE',)),
(DeleteLeftWord(), ('M-DELETE', 'M-BACKSPACE',)),
)
# add the search actions
for pair in default_actions:
(action, sequences) = pair
assert type(sequences) == type(()), repr(pair)
self.add_action_and_bindings(action, sequences)
# create all the insert actions for the character ranges we like
for collection in (string.letters, string.digits, string.punctuation):
for c in collection:
self.add_action_and_bindings(InsertSearchString(c), (c,))
self.add_action_and_bindings(InsertSearchString(' '), ('SPACE',))
def name(self):
return "Search"
class SearchNext(method.Method):
def execute(self, window, **vargs):
window.buffer.method.direction = 'next'
s = window.buffer.make_string()
if not s:
s = window.application.last_search
window.buffer.set_data(s)
else:
old_window = window.buffer.method.old_window
_find_next(old_window, window, move=True)
class SearchPrevious(method.Method):
def execute(self, window, **vargs):
window.buffer.method.direction = 'previous'
s = window.buffer.make_string()
if not s:
return
else:
old_window = window.buffer.method.old_window
_find_previous(old_window, window, move=True)
class EndSearch(method.Method):
def execute(self, window, **vargs):
old_window = window.buffer.method.old_window
old_cursor = window.buffer.method.old_cursor
_end(window)
old_window.set_mark_point(old_cursor)
window.application.set_error("Mark set to search start")
class CancelSearch(method.Method):
def execute(self, window, **vargs):
old_window = window.buffer.method.old_window
old_cursor = window.buffer.method.old_cursor
old_window.goto(old_cursor)
_end(window)
window.application.set_error("Search cancelled")
class DeleteLeft(method.Method):
def execute(self, window, **vargs):
window.left_delete()
old_cursor = window.buffer.method.old_cursor
old_window = window.buffer.method.old_window
old_window.goto(old_cursor)
if window.buffer.method.direction == 'next':
_find_next(old_window, window, move=False)
else:
_find_previous(old_window, window, move=False)
class DeleteLeftWord(method.Method):
def execute(self, window, **vargs):
window.kill_left_word()
old_cursor = window.buffer.method.old_cursor
old_window = window.buffer.method.old_window
old_window.goto(old_cursor)
if window.buffer.method.direction == 'next':
_find_next(old_window, window, move=False)
else:
_find_previous(old_window, window, move=False)
class InsertSearchString(method.Method):
def __init__(self, s):
self.name = 'insert-search-string-%s' % (s)
self.string = s
self.args = []
self.help = None
def execute(self, window, **vargs):
window.insert_string(self.string)
s = window.buffer.make_string()
if not s:
return
else:
old_window = window.buffer.method.old_window
if window.buffer.method.direction == 'next':
_find_next(old_window, window, move=False)
else:
_find_previous(old_window, window, move=False)
def _end(window):
s = window.buffer.make_string()
window.application.last_search = s
window.application.close_mini_buffer()
#window.application.highlighted_range = []
window.application.clear_highlighted_ranges()
window.buffer.method.old_cursor = None
window.buffer.method.old_window = None
def _find_previous(old_window, new_window, move=False):
s = new_window.buffer.make_string()
old_buffer = old_window.buffer
c = old_window.logical_cursor()
(x, y) = (c.x, c.y)
if move:
x -= 1
l = old_buffer.lines[y][:x + len(s)]
# for each line available
while y >= 0:
if s in l:
# success
x = l.index(s)
old_window.goto(point.Point(x, y))
#new_window.application.highlighted_range = [old_window,
# point.Point(x,y),
# point.Point(x + len(s), y)]
old_window.application.clear_highlighted_ranges()
new_window.application.add_highlighted_range(old_window,
point.Point(x,y),
point.Point(x + len(s), y))
break
elif y >= len(old_buffer.lines) - 1:
# failure
break
else:
# keep trying
y -= 1
l = old_buffer.lines[y]
x = 0
def _find_next(old_window, new_window, move=False):
s = new_window.buffer.make_string()
old_buffer = old_window.buffer
c = old_window.logical_cursor()
(x, y) = (c.x, c.y)
if move:
x += 1
l = old_buffer.lines[y][x:]
# for each line available
while y < len(old_buffer.lines):
if s in l:
# success
x = l.index(s) + x
old_window.goto(point.Point(x, y))
#new_window.application.highlighted_range = [old_window,
# point.Point(x,y),
# point.Point(x + len(s), y)]
old_window.application.clear_highlighted_ranges()
new_window.application.add_highlighted_range(old_window,
point.Point(x,y),
point.Point(x + len(s), y))
break
elif y >= len(old_buffer.lines) - 1:
# failure
break
else:
# keep trying
y += 1
l = old_buffer.lines[y]
x = 0