1616
1717from gi .repository import Gdk
1818from gi .repository import Gtk
19- import re
19+ from gi . repository import GtkSource
2020
2121from meld import misc
2222from . import gnomeglade
@@ -28,7 +28,7 @@ class FindBar(gnomeglade.Component):
2828 def __init__ (self , parent ):
2929 gnomeglade .Component .__init__ (self , "findbar.ui" , "findbar" ,
3030 ["arrow_left" , "arrow_right" ])
31- self .textview = None
31+ self .set_text_view ( None )
3232 context = self .find_entry .get_style_context ()
3333 self .orig_base_color = context .get_background_color (Gtk .StateFlags .NORMAL )
3434 self .arrow_left .show ()
@@ -43,12 +43,20 @@ def on_focus_child(self, container, widget):
4343 return False
4444
4545 def hide (self ):
46- self .textview = None
46+ self .set_text_view ( None )
4747 self .wrap_box .set_visible (False )
4848 self .widget .hide ()
4949
50- def start_find (self , textview , text = None ):
50+ def set_text_view (self , textview ):
5151 self .textview = textview
52+ if textview is not None :
53+ self .search_context = GtkSource .SearchContext .new (
54+ textview .get_buffer (), None )
55+ else :
56+ self .search_context = None
57+
58+ def start_find (self , textview , text = None ):
59+ self .set_text_view (textview )
5260 self .replace_label .hide ()
5361 self .replace_entry .hide ()
5462 self .hbuttonbox2 .hide ()
@@ -59,21 +67,21 @@ def start_find(self, textview, text=None):
5967 self .find_entry .grab_focus ()
6068
6169 def start_find_next (self , textview ):
62- self .textview = textview
70+ self .set_text_view ( textview )
6371 if self .find_entry .get_text ():
6472 self .on_find_next_button_clicked (self .find_next_button )
6573 else :
6674 self .start_find (self .textview )
6775
6876 def start_find_previous (self , textview , text = None ):
69- self .textview = textview
77+ self .set_text_view ( textview )
7078 if self .find_entry .get_text ():
7179 self .on_find_previous_button_clicked (self .find_previous_button )
7280 else :
7381 self .start_find (self .textview )
7482
7583 def start_replace (self , textview , text = None ):
76- self .textview = textview
84+ self .set_text_view ( textview )
7785 if text :
7886 self .find_entry .set_text (text )
7987 self .widget .set_row_spacing (6 )
@@ -128,52 +136,41 @@ def _find_text(self, start_offset=1, backwards=False, wrap=True):
128136 whole_word = self .whole_word .get_active ()
129137 regex = self .regex .get_active ()
130138 assert self .textview
139+ assert self .search_context
131140 buf = self .textview .get_buffer ()
132141 insert = buf .get_iter_at_mark (buf .get_insert ())
133142 tofind_utf8 = self .find_entry .get_text ()
134143 tofind = tofind_utf8 .decode ("utf-8" )
144+ self .search_context .get_settings ().set_case_sensitive (match_case )
145+ self .search_context .get_settings ().set_at_word_boundaries (whole_word )
146+ self .search_context .get_settings ().set_regex_enabled (regex )
147+ self .search_context .get_settings ().set_search_text (tofind )
148+ self .search_context .get_settings ().set_wrap_around (wrap )
149+ self .search_context .set_highlight (True )
135150 start , end = buf .get_bounds ()
136- text = buf .get_text (start , end , False ).decode ("utf-8" )
137- if not regex :
138- tofind = re .escape (tofind )
139- if whole_word :
140- tofind = r'\b' + tofind + r'\b'
141- try :
142- flags = re .M if match_case else re .M | re .I
143- pattern = re .compile (tofind , flags )
144- except re .error as e :
145- misc .error_dialog (_ ("Regular expression error" ), str (e ))
151+ self .wrap_box .set_visible (False )
152+ if not backwards :
153+ insert .forward_chars (start_offset )
154+ match , start_iter , end_iter = self .search_context .forward (insert )
155+ if match and (start_iter .get_offset () < insert .get_offset ()):
156+ self .wrap_box .set_visible (True )
157+ else :
158+ match , start_iter , end_iter = self .search_context .backward (insert )
159+ if match and (start_iter .get_offset () > insert .get_offset ()):
160+ self .wrap_box .set_visible (True )
161+ if match :
162+ buf .place_cursor (start_iter )
163+ buf .move_mark (buf .get_selection_bound (), end_iter )
164+ self .textview .scroll_to_mark (
165+ buf .get_insert (), 0.25 , True , 0.5 , 0.5 )
166+ return True
146167 else :
168+ buf .place_cursor (buf .get_iter_at_mark (buf .get_insert ()))
169+ # FIXME: Even though docs suggest this should work, it does
170+ # not. It just sets the selection colour on the text, without
171+ # affecting the entry colour at all.
172+ color = Gdk .RGBA ()
173+ color .parse ("#ffdddd" )
174+ self .find_entry .override_background_color (
175+ Gtk .StateType .NORMAL , color )
147176 self .wrap_box .set_visible (False )
148- if not backwards :
149- match = pattern .search (text ,
150- insert .get_offset () + start_offset )
151- if match is None and wrap :
152- self .wrap_box .set_visible (True )
153- match = pattern .search (text , 0 )
154- else :
155- match = None
156- for m in pattern .finditer (text , 0 , insert .get_offset ()):
157- match = m
158- if match is None and wrap :
159- self .wrap_box .set_visible (True )
160- for m in pattern .finditer (text , insert .get_offset ()):
161- match = m
162- if match :
163- it = buf .get_iter_at_offset (match .start ())
164- buf .place_cursor (it )
165- it .forward_chars (match .end () - match .start ())
166- buf .move_mark (buf .get_selection_bound (), it )
167- self .textview .scroll_to_mark (
168- buf .get_insert (), 0.25 , True , 0.5 , 0.5 )
169- return True
170- else :
171- buf .place_cursor (buf .get_iter_at_mark (buf .get_insert ()))
172- # FIXME: Even though docs suggest this should work, it does
173- # not. It just sets the selection colour on the text, without
174- # affecting the entry colour at all.
175- color = Gdk .RGBA ()
176- color .parse ("#ffdddd" )
177- self .find_entry .override_background_color (
178- Gtk .StateType .NORMAL , color )
179- self .wrap_box .set_visible (False )
0 commit comments