Skip to content

Commit 433b7b3

Browse files
evfoolkaiw
authored andcommitted
Use GtkSourceView support for searching and higlighting all matches.
https://bugzilla.gnome.org/show_bug.cgi?id=699486
1 parent 53647d5 commit 433b7b3

2 files changed

Lines changed: 47 additions & 50 deletions

File tree

bin/meld

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ def check_requirements():
131131
pyver = (2, 7)
132132
gtk_requirement = (3, 6)
133133
glib_requirement = (2, 34, 0)
134-
gtksourceview_requirement = (3, 6, 0)
134+
gtksourceview_requirement = (3, 10, 0)
135135

136136
def missing_reqs(mod, ver, exception=None):
137137
if isinstance(exception, ImportError):

meld/ui/findbar.py

Lines changed: 46 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
from gi.repository import Gdk
1818
from gi.repository import Gtk
19-
import re
19+
from gi.repository import GtkSource
2020

2121
from meld import misc
2222
from . 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

Comments
 (0)