I am trying to implement a simple Search and Replace
functionality in a Gtk.SourceView
widget.
As expected, when the user clicks on the Find Next
button:
- ALL the matches should be highlighted (possibly the current match should have a different color)
- then the user should be able to cycle (forward/backward) through the results (and replace them if he wants)
This is the relevant documentation that I managed to find.
GtkSource Documentation
GtkSource 3: Main - SearchContext Lazka (I am on Linux Mint 18.3 with Gtk 3.18.9)
(GtkSource 4: Main - SearchContext Lazka - SearchContext Gnome)
Based on this documentation, I wrote this code (dummie code to understand the functionality):
def on_srFindNextBtn_clicked(self, widget):
srSourceBuffer = self.sourceview.get_buffer()
srCursorMark = srSourceBuffer.get_insert()
srCursorIter = srSourceBuffer.get_iter_at_mark(srCursorMark)
srSearchSettings = GtkSource.SearchSettings.new()
srSearchSettings.set_search_text('ipsum')
srSearchContext = GtkSource.SearchContext.new(srSourceBuffer, srSearchSettings)
srSearchContext.set_highlight(True)
success, match_start, match_end = srSearchContext.forward(srCursorIter)
if success:
occurencePos = srSearchContext.get_occurrence_position(match_start, match_end)
print(occurencePos)
resultsNum = srSearchContext.get_occurrences_count()
print('Total occurences: ' + str(resultsNum))
else:
print('Forward search: False')
The first time I click on the Find Next
button I get this result:
1
Total occurences: -1
Questions:
- I guess that the search stops after the first match, right?
- so the
get_occurances_count()
method return-1
because the buffer is not already fully scanned, right? - should I manually implement a loop to call the
forward()
method until I reach the end of the buffer? But then, how can I cycle through the results? - Why the match found doesnāt get highlighted (even if the default themeās scheme āmatch-styleā is correctly set)?
OPTIONAL INFORMATION
On another note, the following is an example of a search function with a TextView
(not a SourceView
). I got the loop idea from there.
MULTILINE TEXT EDITOR
Example from the documentation (17. Multiline Text Editor ā Python GTK+ 3 Tutorial 3.4 documentation).
Here they make use of the Gtk.TextIter.forware_search()
method (Gtk.TextIter - Structures - Gtk 3.0).
def on_search_clicked(self, widget):
dialog = SearchDialog(self)
response = dialog.run()
if response == Gtk.ResponseType.OK:
cursor_mark = self.textbuffer.get_insert()
start = self.textbuffer.get_iter_at_mark(cursor_mark)
if start.get_offset() == self.textbuffer.get_char_count():
start = self.textbuffer.get_start_iter()
self.search_and_mark(dialog.entry.get_text(), start)
dialog.destroy()
def search_and_mark(self, text, start):
end = self.textbuffer.get_end_iter()
match = start.forward_search(text, 0, end)
if match is not None:
match_start, match_end = match
self.textbuffer.apply_tag(self.tag_found, match_start, match_end)
self.search_and_mark(text, match_end)
So, can anyone explain how I should go about implementing a search and replace functionality in a GtkSource
widget?