generated from itdominator/Python-With-Gtk-Template
More work on search and replace
This commit is contained in:
parent
3ad7c3b65d
commit
f10f4fcc72
|
@ -115,7 +115,7 @@ class Plugin(PluginBase):
|
||||||
if not start_itr or not query: return None, None
|
if not start_itr or not query: return None, None
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
flags = Gtk.TextSearchFlags.VISIBLE_ONLY & Gtk.TextSearchFlags.TEXT_ONLY
|
flags = Gtk.TextSearchFlags.VISIBLE_ONLY | Gtk.TextSearchFlags.TEXT_ONLY
|
||||||
while True:
|
while True:
|
||||||
result = start_itr.forward_search(query, flags, end_itr)
|
result = start_itr.forward_search(query, flags, end_itr)
|
||||||
if not result: break
|
if not result: break
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Python imports
|
# Python imports
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
# Lib imports
|
# Lib imports
|
||||||
import gi
|
import gi
|
||||||
|
@ -25,13 +26,18 @@ class Plugin(PluginBase):
|
||||||
self._find_entry = None
|
self._find_entry = None
|
||||||
self._replace_entry = None
|
self._replace_entry = None
|
||||||
self._active_src_view = None
|
self._active_src_view = None
|
||||||
|
self._buffer = None
|
||||||
|
self._tag_table = None
|
||||||
|
|
||||||
self.use_regex = False
|
self.use_regex = False
|
||||||
self.use_case_sensitive = False
|
self.use_case_sensitive = False
|
||||||
self.use_only_in_selection = False
|
self.search_only_in_selection = False
|
||||||
self.use_whole_word_search = False
|
self.use_whole_word_search = False
|
||||||
|
|
||||||
|
self.search_tag = "search_tag"
|
||||||
self.highlight_color = "#FBF719"
|
self.highlight_color = "#FBF719"
|
||||||
self.text_color = "#000000"
|
self.text_color = "#000000"
|
||||||
|
self.alpha_num_under = re.compile(r"[a-zA-Z0-9_]")
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
@ -59,6 +65,8 @@ class Plugin(PluginBase):
|
||||||
|
|
||||||
def _set_active_src_view(self, source_view):
|
def _set_active_src_view(self, source_view):
|
||||||
self._active_src_view = source_view
|
self._active_src_view = source_view
|
||||||
|
self._buffer = self._active_src_view.get_buffer()
|
||||||
|
self._tag_table = self._buffer.get_tag_table()
|
||||||
self.search_for_string(self._find_entry)
|
self.search_for_string(self._find_entry)
|
||||||
|
|
||||||
def _show_search_replace(self, widget = None, eve = None):
|
def _show_search_replace(self, widget = None, eve = None):
|
||||||
|
@ -86,18 +94,22 @@ class Plugin(PluginBase):
|
||||||
def tggle_regex(self, widget):
|
def tggle_regex(self, widget):
|
||||||
self.use_regex = not widget.get_active()
|
self.use_regex = not widget.get_active()
|
||||||
self._set_find_options_lbl()
|
self._set_find_options_lbl()
|
||||||
|
self.search_for_string(self._find_entry)
|
||||||
|
|
||||||
def tggle_case_sensitive(self, widget):
|
def tggle_case_sensitive(self, widget):
|
||||||
self.use_case_sensitive = not widget.get_active()
|
self.use_case_sensitive = widget.get_active()
|
||||||
self._set_find_options_lbl()
|
self._set_find_options_lbl()
|
||||||
|
self.search_for_string(self._find_entry)
|
||||||
|
|
||||||
def tggle_selection_only_scan(self, widget):
|
def tggle_selection_only_scan(self, widget):
|
||||||
self.use_only_in_selection = not widget.get_active()
|
self.search_only_in_selection = widget.get_active()
|
||||||
self._set_find_options_lbl()
|
self._set_find_options_lbl()
|
||||||
|
self.search_for_string(self._find_entry)
|
||||||
|
|
||||||
def tggle_whole_word_search(self, widget):
|
def tggle_whole_word_search(self, widget):
|
||||||
self.use_whole_word_search = not widget.get_active()
|
self.use_whole_word_search = widget.get_active()
|
||||||
self._set_find_options_lbl()
|
self._set_find_options_lbl()
|
||||||
|
self.search_for_string(self._find_entry)
|
||||||
|
|
||||||
def _set_find_options_lbl(self):
|
def _set_find_options_lbl(self):
|
||||||
# Finding with Options: Case Insensitive
|
# Finding with Options: Case Insensitive
|
||||||
|
@ -106,8 +118,8 @@ class Plugin(PluginBase):
|
||||||
# f"Finding with Options: {regex}, {case}, {selection}, {word}"
|
# f"Finding with Options: {regex}, {case}, {selection}, {word}"
|
||||||
...
|
...
|
||||||
|
|
||||||
def _update_status_lbl(self, total_count: int = None, query: str = None):
|
def _update_status_lbl(self, total_count: int = 0, query: str = None):
|
||||||
if not total_count or not query: return
|
if not query: return
|
||||||
|
|
||||||
count = total_count if total_count > 0 else "No"
|
count = total_count if total_count > 0 else "No"
|
||||||
plural = "s" if total_count > 1 else ""
|
plural = "s" if total_count > 1 else ""
|
||||||
|
@ -115,16 +127,13 @@ class Plugin(PluginBase):
|
||||||
|
|
||||||
def get_search_tag(self, buffer):
|
def get_search_tag(self, buffer):
|
||||||
tag_table = buffer.get_tag_table()
|
tag_table = buffer.get_tag_table()
|
||||||
search_tag = tag_table.lookup("search_tag")
|
search_tag = tag_table.lookup(self.search_tag)
|
||||||
if not search_tag:
|
if not search_tag:
|
||||||
search_tag = buffer.create_tag("search_tag", background = self.highlight_color, foreground = self.text_color)
|
search_tag = buffer.create_tag(self.search_tag, background = self.highlight_color, foreground = self.text_color)
|
||||||
|
|
||||||
buffer.remove_tag_by_name("search_tag", buffer.get_start_iter(), buffer.get_end_iter())
|
buffer.remove_tag_by_name(self.search_tag, buffer.get_start_iter(), buffer.get_end_iter())
|
||||||
return search_tag
|
return search_tag
|
||||||
|
|
||||||
def find_next_entry(self, widget, eve, use_data = None):
|
|
||||||
...
|
|
||||||
|
|
||||||
def search_for_string(self, widget):
|
def search_for_string(self, widget):
|
||||||
query = widget.get_text()
|
query = widget.get_text()
|
||||||
buffer = self._active_src_view.get_buffer()
|
buffer = self._active_src_view.get_buffer()
|
||||||
|
@ -139,36 +148,70 @@ class Plugin(PluginBase):
|
||||||
end_itr = buffer.get_end_iter()
|
end_itr = buffer.get_end_iter()
|
||||||
|
|
||||||
results, total_count = self.search(start_itr, query)
|
results, total_count = self.search(start_itr, query)
|
||||||
|
self._update_status_lbl(total_count, query)
|
||||||
for start, end in results:
|
for start, end in results:
|
||||||
buffer.apply_tag(search_tag, start, end)
|
buffer.apply_tag(search_tag, start, end)
|
||||||
self._update_status_lbl(total_count, query)
|
|
||||||
|
|
||||||
def search(self, start_itr = None, query = None):
|
def search(self, start_itr = None, query = None, limit = None):
|
||||||
if not start_itr or not query: return None, None
|
if not start_itr or not query: return None, None
|
||||||
|
|
||||||
|
flags = Gtk.TextSearchFlags.VISIBLE_ONLY | Gtk.TextSearchFlags.TEXT_ONLY
|
||||||
if not self.use_case_sensitive:
|
if not self.use_case_sensitive:
|
||||||
_flags = Gtk.TextSearchFlags.VISIBLE_ONLY & Gtk.TextSearchFlags.TEXT_ONLY & Gtk.TextSearchFlags.CASE_INSENSITIVE
|
flags = flags | Gtk.TextSearchFlags.CASE_INSENSITIVE
|
||||||
else:
|
|
||||||
_flags = Gtk.TextSearchFlags.VISIBLE_ONLY & Gtk.TextSearchFlags.TEXT_ONLY
|
|
||||||
|
|
||||||
results = []
|
if self.search_only_in_selection and self._buffer.get_has_selection():
|
||||||
|
start_itr, limit = self._buffer.get_selection_bounds()
|
||||||
|
|
||||||
|
_results = []
|
||||||
while True:
|
while True:
|
||||||
result = start_itr.forward_search(query, flags = _flags, limit = None)
|
result = start_itr.forward_search(query, flags, limit)
|
||||||
if not result: break
|
if not result: break
|
||||||
|
|
||||||
results.append(result)
|
_results.append(result)
|
||||||
start_itr = result[1]
|
start_itr = result[1]
|
||||||
|
|
||||||
|
results = self.apply_filters(_results, query)
|
||||||
return results, len(results)
|
return results, len(results)
|
||||||
|
|
||||||
|
def apply_filters(self, _results, query):
|
||||||
|
results = []
|
||||||
|
for start, end in _results:
|
||||||
|
text = self._buffer.get_slice(start, end, include_hidden_chars = False)
|
||||||
|
if self.use_whole_word_search:
|
||||||
|
end.forward_char()
|
||||||
|
start.backward_char()
|
||||||
|
|
||||||
|
match = self.alpha_num_under.match( start.get_char() )
|
||||||
|
if not match is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
match = self.alpha_num_under.match( end.get_char() )
|
||||||
|
if not match is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
end.backward_char()
|
||||||
|
start.forward_char()
|
||||||
|
|
||||||
|
results.append([start, end])
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
def find_next(self, widget, eve = None, use_data = None):
|
||||||
|
mark = self._buffer.get_insert()
|
||||||
|
iter = self._buffer.get_iter_at_mark(mark)
|
||||||
|
iter.forward_line()
|
||||||
|
|
||||||
|
search_tag = self._tag_table.lookup(self.search_tag)
|
||||||
|
next_tag_found = iter.forward_to_tag_toggle(search_tag)
|
||||||
|
if not next_tag_found:
|
||||||
|
self._buffer.place_cursor( self._buffer.get_start_iter() )
|
||||||
|
mark = self._buffer.get_insert()
|
||||||
|
iter = self._buffer.get_iter_at_mark(mark)
|
||||||
|
iter.forward_to_tag_toggle(search_tag)
|
||||||
|
|
||||||
|
self._buffer.place_cursor(iter)
|
||||||
|
self._active_src_view.scroll_to_mark( self._buffer.get_insert(), 0.0, True, 0.0, 0.0 )
|
||||||
|
|
||||||
def find_next(self, widget):
|
|
||||||
...
|
|
||||||
|
|
||||||
def find_all(self, widget):
|
def find_all(self, widget):
|
||||||
...
|
...
|
||||||
|
|
|
@ -72,6 +72,7 @@
|
||||||
<object class="GtkToggleButton">
|
<object class="GtkToggleButton">
|
||||||
<property name="label" translatable="yes">.*</property>
|
<property name="label" translatable="yes">.*</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
<property name="sensitive">False</property>
|
||||||
<property name="can-focus">True</property>
|
<property name="can-focus">True</property>
|
||||||
<property name="focus-on-click">False</property>
|
<property name="focus-on-click">False</property>
|
||||||
<property name="receives-default">True</property>
|
<property name="receives-default">True</property>
|
||||||
|
@ -187,8 +188,8 @@
|
||||||
<property name="margin-top">5</property>
|
<property name="margin-top">5</property>
|
||||||
<property name="margin-bottom">5</property>
|
<property name="margin-bottom">5</property>
|
||||||
<property name="placeholder-text" translatable="yes">Find in current buffer</property>
|
<property name="placeholder-text" translatable="yes">Find in current buffer</property>
|
||||||
|
<signal name="activate" handler="find_next" swapped="no"/>
|
||||||
<signal name="changed" handler="search_for_string" swapped="no"/>
|
<signal name="changed" handler="search_for_string" swapped="no"/>
|
||||||
<signal name="key-release-event" handler="find_next_entry" swapped="no"/>
|
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left-attach">0</property>
|
<property name="left-attach">0</property>
|
||||||
|
@ -255,6 +256,7 @@
|
||||||
<property name="label" translatable="yes">Find All</property>
|
<property name="label" translatable="yes">Find All</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">True</property>
|
<property name="can-focus">True</property>
|
||||||
|
<property name="focus-on-click">False</property>
|
||||||
<property name="receives-default">True</property>
|
<property name="receives-default">True</property>
|
||||||
<property name="margin-start">5</property>
|
<property name="margin-start">5</property>
|
||||||
<property name="margin-end">5</property>
|
<property name="margin-end">5</property>
|
||||||
|
@ -272,6 +274,7 @@
|
||||||
<property name="label" translatable="yes">Find</property>
|
<property name="label" translatable="yes">Find</property>
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">True</property>
|
<property name="can-focus">True</property>
|
||||||
|
<property name="focus-on-click">False</property>
|
||||||
<property name="receives-default">True</property>
|
<property name="receives-default">True</property>
|
||||||
<property name="margin-start">5</property>
|
<property name="margin-start">5</property>
|
||||||
<property name="margin-end">5</property>
|
<property name="margin-end">5</property>
|
||||||
|
|
Loading…
Reference in New Issue