import sets, string import color, method, minibuffer, mode2 from point2 import Point class Search(mode2.Fundamental): '''This is the default mode''' def __init__(self, w): mode2.Fundamental.__init__(self, w) # clear out all the defaults that we don't want/need self.actions = {} self.bindings = {} # add some useful bindings self.add_action_and_bindings(SearchNext(), ('C-s',)) self.add_action_and_bindings(SearchPrevious(), ('C-r',)) self.add_action_and_bindings(EndSearch(), ('RETURN', 'C-n', 'C-p', 'C-a', 'C-e', 'C-f', 'C-b')) self.add_action_and_bindings(CancelSearch(), ('C-]',)) self.add_action_and_bindings(SearchDeleteLeft(), ('DELETE', 'BACKSPACE',)) self.add_action_and_bindings(SearchDeleteLeftWord(), ('M-DELETE', 'M-BACKSPACE',)) # 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, w, **vargs): w.buffer.method.direction = 'next' 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) class SearchPrevious(method.Method): def execute(self, w, **vargs): w.buffer.method.direction = 'previous' if not w.buffer.make_string(): return else: old_w = w.buffer.method.old_window _find_previous(old_w, w, move=True) class EndSearch(method.Method): def execute(self, w, **vargs): _end(w) w.buffer.method.old_window.set_mark_point(w.buffer.method.old_cursor) w.set_error("Mark set to search start") class CancelSearch(method.Method): def execute(self, w, **vargs): w.buffer.method.old_window.goto(w.buffer.method.old_cursor) _end(w) w.set_error("Search cancelled") class SearchDeleteLeft(method.Method): def execute(self, w, **vargs): w.left_delete() old_cursor = w.buffer.method.old_cursor old_w = w.buffer.method.old_window old_w.goto(old_cursor) if w.buffer.method.direction == 'next': _find_next(old_w, w, move=False) else: _find_previous(old_w, w, move=False) class SearchDeleteLeftWord(method.Method): def execute(self, w, **vargs): w.kill_left_word() old_cursor = w.buffer.method.old_cursor old_w = w.buffer.method.old_window old_w.goto(old_cursor) if w.buffer.method.direction == 'next': _find_next(old_w, w, move=False) else: _find_previous(old_w, w, 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, w, **vargs): w.insert_string_at_cursor(self.string) s = w.buffer.make_string() if not s: return else: old_w = w.buffer.method.old_window if w.buffer.method.direction == 'next': _find_next(old_w, w, move=False) else: _find_previous(old_w, w, move=False) def _end(w): w.application.close_mini_buffer() w.application.clear_highlighted_ranges() w.application.last_search = w.buffer.make_string() w.buffer.method.old_cursor = None w.buffer.method.old_window = None def _find_previous(old_w, new_w, move=False): s = new_w.buffer.make_string() old_b = old_w.buffer c = old_w.logical_cursor() (x, y) = (c.x, c.y) if move: x -= 1 l = old_b.lines[y][:x + len(s)] # for each line available while y >= 0: if s in l: # success x = l.rindex(s) (p1, p2) = (Point(x,y), Point(x + len(s), y)) old_w.goto(p1) old_w.application.clear_highlighted_ranges() new_w.application.add_highlighted_range(old_w, p1, p2) break elif y >= len(old_b.lines) - 1: # failure break else: # keep trying y -= 1 l = old_b.lines[y] x = 0 def _find_next(old_w, new_w, move=False): s = new_w.buffer.make_string() old_b = old_w.buffer c = old_w.logical_cursor() (x, y) = (c.x, c.y) if move: x += 1 l = old_b.lines[y][x:] # for each line available while y < len(old_b.lines): if s in l: # success x = l.index(s) + x (p1, p2) = (Point(x,y), Point(x + len(s), y)) old_w.goto(p1) old_w.application.clear_highlighted_ranges() new_w.application.add_highlighted_range(old_w, p1, p2) break elif y >= len(old_b.lines) - 1: # failure break else: # keep trying y += 1 l = old_b.lines[y] x = 0