import re, string import color, method, minibuffer, mode, searchutil from point import Point selected_color = 'magenta' unselected_color = 'yellow' def _make_regex(w, s): try: if w.buffer.method.is_literal: s = searchutil.escape_literal(s) if s.islower(): return re.compile(s, re.IGNORECASE) else: return re.compile(s) else: return re.compile(s) except: raise searchutil.IllegalPatternError("failed to compile: %r" % s) class SearchNext(method.Method): def execute(self, w, **vargs): w.buffer.method.direction = 'next' s = w.buffer.make_string() if s: try: r = _make_regex(w, s) searchutil.find_next(r, w.buffer.method.old_window, move=True) except searchutil.IllegalPatternError: w.application.clear_highlighted_ranges('search') else: action = InsertSearchString(w.application.last_search) action.execute(w) class SearchPrevious(method.Method): def execute(self, w, **vargs): w.buffer.method.direction = 'previous' if not w.buffer.make_string(): return else: s = w.buffer.make_string() w2 = w.buffer.method.old_window try: r = _make_regex(w, s) searchutil.find_previous(r, w2, move=True) except searchutil.IllegalPatternError: w.application.clear_highlighted_ranges('search') class EndSearch(method.Method): def execute(self, w, **vargs): old_w = w.buffer.method.old_window old_c = w.buffer.method.old_cursor _end(w) old_w.set_mark_point(old_c) 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() _post_delete(w) class SearchDeleteLeftWord(method.Method): def execute(self, w, **vargs): w.delete_left_word() _post_delete(w) def _post_delete(w): old_cursor = w.buffer.method.old_cursor old_w = w.buffer.method.old_window old_w.goto(old_cursor) if not w.buffer.make_string(): w.application.clear_highlighted_ranges('search') return s = w.buffer.make_string() w2 = w.buffer.method.old_window try: r = _make_regex(w, s) if w.buffer.method.direction == 'next': searchutil.find_next(r, w2, move=False) else: searchutil.find_previous(r, w2, move=False) except searchutil.IllegalPatternError: w.application.clear_highlighted_ranges('search') class InsertSearchString(method.Method): def __init__(self, s): self.name = 'insert-search-string-%s' % (s) self.string = s self.args = [] self.help = '' def execute(self, w, **vargs): w.insert_string_at_cursor(self.string) s = w.buffer.make_string() if not s: w.application.clear_highlighted_ranges('search') return else: try: r = _make_regex(w, s) w2 = w.buffer.method.old_window if w.buffer.method.direction == 'next': searchutil.find_next(r, w2, move=False) else: searchutil.find_previous(r, w2, move=False) except searchutil.IllegalPatternError: w.application.clear_highlighted_ranges('search') def _end(w): w.application.close_mini_buffer() w.application.clear_highlighted_ranges('search') w.application.last_search = w.buffer.make_string() class Search(mode.Fundamental): modename = 'Search' actions = [SearchNext, SearchPrevious, EndSearch, CancelSearch, SearchDeleteLeft, SearchDeleteLeftWord] def __init__(self, w): mode.Fundamental.__init__(self, w) # clear out all the defaults that we don't want/need, and add ours self.actions = {} self.bindings = {} self.add_bindings('search-next', ('C-s',)) self.add_bindings('search-previous', ('C-r',)) self.add_bindings('end-search', ('RETURN', 'C-n', 'DOWN', 'C-p', 'UP', 'C-a', 'HOME', 'C-e', 'END', 'C-f', 'RIGHT', 'C-b', 'LEFT')) self.add_bindings('cancel-search', ('C-]', 'C-g',)) self.add_bindings('search-delete-left', ('DELETE', 'BACKSPACE',)) self.add_bindings('search-delete-left-word', ('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',)) install = Search.install