generated from itdominator/Python-With-Gtk-Template
Refactored plugins; added replace functionality
This commit is contained in:
parent
f10f4fcc72
commit
7acb461c9b
63
plugins/colorize/color_converter_mixin.py
Normal file
63
plugins/colorize/color_converter_mixin.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# Python imports
|
||||||
|
import colorsys
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
class ColorConverterMixin:
|
||||||
|
def get_color_text(self, buffer, start, end):
|
||||||
|
text = buffer.get_text(start, end, include_hidden_chars = False)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if "hsl" in text:
|
||||||
|
text = self.hsl_to_rgb(text)
|
||||||
|
|
||||||
|
if "hsv" in text:
|
||||||
|
text = self.hsv_to_rgb(text)
|
||||||
|
except Exception as e:
|
||||||
|
...
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
||||||
|
def hsl_to_rgb(self, text):
|
||||||
|
_h, _s , _l = text.replace("hsl", "") \
|
||||||
|
.replace("deg", "") \
|
||||||
|
.replace("(", "") \
|
||||||
|
.replace(")", "") \
|
||||||
|
.replace("%", "") \
|
||||||
|
.replace(" ", "") \
|
||||||
|
.split(",")
|
||||||
|
|
||||||
|
h = None
|
||||||
|
s = None
|
||||||
|
l = None
|
||||||
|
|
||||||
|
h, s , l = int(_h) / 360, float(_s) / 100, float(_l) / 100
|
||||||
|
|
||||||
|
rgb = tuple(round(i * 255) for i in colorsys.hls_to_rgb(h, l, s))
|
||||||
|
rgb_sub = ','.join(map(str, rgb))
|
||||||
|
|
||||||
|
return f"rgb({rgb_sub})"
|
||||||
|
|
||||||
|
|
||||||
|
def hsv_to_rgb(self, text):
|
||||||
|
_h, _s , _v = text.replace("hsv", "") \
|
||||||
|
.replace("deg", "") \
|
||||||
|
.replace("(", "") \
|
||||||
|
.replace(")", "") \
|
||||||
|
.replace("%", "") \
|
||||||
|
.replace(" ", "") \
|
||||||
|
.split(",")
|
||||||
|
|
||||||
|
h = None
|
||||||
|
s = None
|
||||||
|
v = None
|
||||||
|
|
||||||
|
h, s , v = int(_h) / 360, float(_s) / 100, float(_v) / 100
|
||||||
|
|
||||||
|
rgb = tuple(round(i * 255) for i in colorsys.hsv_to_rgb(h,s,v))
|
||||||
|
rgb_sub = ','.join(map(str, rgb))
|
||||||
|
|
||||||
|
return f"rgb({rgb_sub})"
|
@ -1,9 +1,4 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
import os
|
|
||||||
import threading
|
|
||||||
import subprocess
|
|
||||||
import time
|
|
||||||
import colorsys
|
|
||||||
|
|
||||||
# Lib imports
|
# Lib imports
|
||||||
import gi
|
import gi
|
||||||
@ -14,26 +9,11 @@ from gi.repository import Gdk
|
|||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
from plugins.plugin_base import PluginBase
|
from plugins.plugin_base import PluginBase
|
||||||
|
from .color_converter_mixin import ColorConverterMixin
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(ColorConverterMixin, PluginBase):
|
||||||
# NOTE: Threads WILL NOT die with parent's destruction.
|
|
||||||
def threaded(fn):
|
|
||||||
def wrapper(*args, **kwargs):
|
|
||||||
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start()
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
# NOTE: Threads WILL die with parent's destruction.
|
|
||||||
def daemon_threaded(fn):
|
|
||||||
def wrapper(*args, **kwargs):
|
|
||||||
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Plugin(PluginBase):
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
@ -57,7 +37,7 @@ class Plugin(PluginBase):
|
|||||||
self._active_src_view = source_view
|
self._active_src_view = source_view
|
||||||
|
|
||||||
def _buffer_changed_first_load(self, buffer):
|
def _buffer_changed_first_load(self, buffer):
|
||||||
self._handle(buffer)
|
self._do_colorize(buffer)
|
||||||
|
|
||||||
|
|
||||||
def _buffer_changed(self, buffer):
|
def _buffer_changed(self, buffer):
|
||||||
@ -76,10 +56,10 @@ class Plugin(PluginBase):
|
|||||||
buffer.remove_tag(tag, start, end)
|
buffer.remove_tag(tag, start, end)
|
||||||
tag_table.remove(tag)
|
tag_table.remove(tag)
|
||||||
|
|
||||||
self._handle(buffer, start, end)
|
self._do_colorize(buffer, start, end)
|
||||||
|
|
||||||
|
|
||||||
def _handle(self, buffer = None, start_itr = None, end_itr = None):
|
def _do_colorize(self, buffer = None, start_itr = None, end_itr = None):
|
||||||
# rgb(a), hsl, hsv
|
# rgb(a), hsl, hsv
|
||||||
results = self.finalize_non_hex_matches( self.collect_preliminary_results(buffer, start_itr, end_itr) )
|
results = self.finalize_non_hex_matches( self.collect_preliminary_results(buffer, start_itr, end_itr) )
|
||||||
self.process_results(buffer, results)
|
self.process_results(buffer, results)
|
||||||
@ -171,20 +151,6 @@ class Plugin(PluginBase):
|
|||||||
tag = self.get_colorized_tag(buffer, text, color)
|
tag = self.get_colorized_tag(buffer, text, color)
|
||||||
buffer.apply_tag(tag, start, end)
|
buffer.apply_tag(tag, start, end)
|
||||||
|
|
||||||
def get_color_text(self, buffer, start, end):
|
|
||||||
text = buffer.get_text(start, end, include_hidden_chars = False)
|
|
||||||
|
|
||||||
try:
|
|
||||||
if "hsl" in text:
|
|
||||||
text = self.hsl_to_rgb(text)
|
|
||||||
|
|
||||||
if "hsv" in text:
|
|
||||||
text = self.hsv_to_rgb(text)
|
|
||||||
except Exception as e:
|
|
||||||
...
|
|
||||||
|
|
||||||
return text
|
|
||||||
|
|
||||||
def get_colorized_tag(self, buffer, tag, color: Gdk.RGBA):
|
def get_colorized_tag(self, buffer, tag, color: Gdk.RGBA):
|
||||||
tag_table = buffer.get_tag_table()
|
tag_table = buffer.get_tag_table()
|
||||||
colorize_tag = f"{self.tag_stub_name}_{tag}"
|
colorize_tag = f"{self.tag_stub_name}_{tag}"
|
||||||
@ -193,44 +159,3 @@ class Plugin(PluginBase):
|
|||||||
search_tag = buffer.create_tag(colorize_tag, background_rgba = color)
|
search_tag = buffer.create_tag(colorize_tag, background_rgba = color)
|
||||||
|
|
||||||
return search_tag
|
return search_tag
|
||||||
|
|
||||||
def hsl_to_rgb(self, text):
|
|
||||||
_h, _s , _l = text.replace("hsl", "") \
|
|
||||||
.replace("deg", "") \
|
|
||||||
.replace("(", "") \
|
|
||||||
.replace(")", "") \
|
|
||||||
.replace("%", "") \
|
|
||||||
.replace(" ", "") \
|
|
||||||
.split(",")
|
|
||||||
|
|
||||||
h = None
|
|
||||||
s = None
|
|
||||||
l = None
|
|
||||||
|
|
||||||
h, s , l = int(_h) / 360, float(_s) / 100, float(_l) / 100
|
|
||||||
|
|
||||||
rgb = tuple(round(i * 255) for i in colorsys.hls_to_rgb(h, l, s))
|
|
||||||
rgb_sub = ','.join(map(str, rgb))
|
|
||||||
|
|
||||||
return f"rgb({rgb_sub})"
|
|
||||||
|
|
||||||
|
|
||||||
def hsv_to_rgb(self, text):
|
|
||||||
_h, _s , _v = text.replace("hsv", "") \
|
|
||||||
.replace("deg", "") \
|
|
||||||
.replace("(", "") \
|
|
||||||
.replace(")", "") \
|
|
||||||
.replace("%", "") \
|
|
||||||
.replace(" ", "") \
|
|
||||||
.split(",")
|
|
||||||
|
|
||||||
h = None
|
|
||||||
s = None
|
|
||||||
v = None
|
|
||||||
|
|
||||||
h, s , v = int(_h) / 360, float(_s) / 100, float(_v) / 100
|
|
||||||
|
|
||||||
rgb = tuple(round(i * 255) for i in colorsys.hsv_to_rgb(h,s,v))
|
|
||||||
rgb_sub = ','.join(map(str, rgb))
|
|
||||||
|
|
||||||
return f"rgb({rgb_sub})"
|
|
||||||
|
@ -1,19 +1,22 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import threading
|
||||||
|
|
||||||
# Lib imports
|
# Lib imports
|
||||||
import gi
|
import gi
|
||||||
gi.require_version('Gtk', '3.0')
|
gi.require_version('Gtk', '3.0')
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import GLib
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
from plugins.plugin_base import PluginBase
|
from plugins.plugin_base import PluginBase
|
||||||
|
from .styling_mixin import StylingMixin
|
||||||
|
from .replace_mixin import ReplaceMixin
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(StylingMixin, ReplaceMixin, PluginBase):
|
||||||
class Plugin(PluginBase):
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
@ -34,6 +37,9 @@ class Plugin(PluginBase):
|
|||||||
self.search_only_in_selection = False
|
self.search_only_in_selection = False
|
||||||
self.use_whole_word_search = False
|
self.use_whole_word_search = False
|
||||||
|
|
||||||
|
self.timer = None
|
||||||
|
self.search_time = 0.35
|
||||||
|
self.find_text = ""
|
||||||
self.search_tag = "search_tag"
|
self.search_tag = "search_tag"
|
||||||
self.highlight_color = "#FBF719"
|
self.highlight_color = "#FBF719"
|
||||||
self.text_color = "#000000"
|
self.text_color = "#000000"
|
||||||
@ -91,39 +97,6 @@ class Plugin(PluginBase):
|
|||||||
self._search_replace_dialog.popdown()
|
self._search_replace_dialog.popdown()
|
||||||
self._find_entry.set_text("")
|
self._find_entry.set_text("")
|
||||||
|
|
||||||
def tggle_regex(self, widget):
|
|
||||||
self.use_regex = not widget.get_active()
|
|
||||||
self._set_find_options_lbl()
|
|
||||||
self.search_for_string(self._find_entry)
|
|
||||||
|
|
||||||
def tggle_case_sensitive(self, widget):
|
|
||||||
self.use_case_sensitive = widget.get_active()
|
|
||||||
self._set_find_options_lbl()
|
|
||||||
self.search_for_string(self._find_entry)
|
|
||||||
|
|
||||||
def tggle_selection_only_scan(self, widget):
|
|
||||||
self.search_only_in_selection = widget.get_active()
|
|
||||||
self._set_find_options_lbl()
|
|
||||||
self.search_for_string(self._find_entry)
|
|
||||||
|
|
||||||
def tggle_whole_word_search(self, widget):
|
|
||||||
self.use_whole_word_search = widget.get_active()
|
|
||||||
self._set_find_options_lbl()
|
|
||||||
self.search_for_string(self._find_entry)
|
|
||||||
|
|
||||||
def _set_find_options_lbl(self):
|
|
||||||
# Finding with Options: Case Insensitive
|
|
||||||
# Finding with Options: Regex, Case Sensitive, Within Current Selection, Whole Word
|
|
||||||
# Finding with Options: Regex, Case Inensitive, Within Current Selection, Whole Word
|
|
||||||
# f"Finding with Options: {regex}, {case}, {selection}, {word}"
|
|
||||||
...
|
|
||||||
|
|
||||||
def _update_status_lbl(self, total_count: int = 0, query: str = None):
|
|
||||||
if not query: return
|
|
||||||
|
|
||||||
count = total_count if total_count > 0 else "No"
|
|
||||||
plural = "s" if total_count > 1 else ""
|
|
||||||
self._find_status_lbl.set_label(f"{count} results{plural} found for '{query}'")
|
|
||||||
|
|
||||||
def get_search_tag(self, buffer):
|
def get_search_tag(self, buffer):
|
||||||
tag_table = buffer.get_tag_table()
|
tag_table = buffer.get_tag_table()
|
||||||
@ -134,14 +107,44 @@ class Plugin(PluginBase):
|
|||||||
buffer.remove_tag_by_name(self.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 cancel_timer(self):
|
||||||
|
if self.timer:
|
||||||
|
self.timer.cancel()
|
||||||
|
GLib.idle_remove_by_data(None)
|
||||||
|
|
||||||
|
def delay_search_glib(self):
|
||||||
|
GLib.idle_add(self._do_highlight)
|
||||||
|
|
||||||
|
def delay_search(self):
|
||||||
|
wait_time = self.search_time / len(self.find_text)
|
||||||
|
wait_time = max(wait_time, 0.05)
|
||||||
|
|
||||||
|
self.timer = threading.Timer(wait_time, self.delay_search_glib)
|
||||||
|
self.timer.daemon = True
|
||||||
|
self.timer.start()
|
||||||
|
|
||||||
|
|
||||||
def search_for_string(self, widget):
|
def search_for_string(self, widget):
|
||||||
query = widget.get_text()
|
self.cancel_timer()
|
||||||
|
|
||||||
|
self.find_text = widget.get_text()
|
||||||
|
if len(self.find_text) > 0 and len(self.find_text) < 5:
|
||||||
|
self.delay_search()
|
||||||
|
else:
|
||||||
|
self._do_highlight(self.find_text)
|
||||||
|
|
||||||
|
|
||||||
|
def _do_highlight(self, query = None):
|
||||||
|
query = self.find_text if not query else query
|
||||||
buffer = self._active_src_view.get_buffer()
|
buffer = self._active_src_view.get_buffer()
|
||||||
# Also clears tag from buffer so if no query we're clean in ui
|
# Also clears tag from buffer so if no query we're clean in ui
|
||||||
search_tag = self.get_search_tag(buffer)
|
search_tag = self.get_search_tag(buffer)
|
||||||
|
|
||||||
|
self.update_style(1)
|
||||||
if not query:
|
if not query:
|
||||||
self._find_status_lbl.set_label(f"Find in current buffer")
|
self._find_status_lbl.set_label(f"Find in current buffer")
|
||||||
|
self.update_style(0)
|
||||||
return
|
return
|
||||||
|
|
||||||
start_itr = buffer.get_start_iter()
|
start_itr = buffer.get_start_iter()
|
||||||
@ -178,20 +181,9 @@ class Plugin(PluginBase):
|
|||||||
for start, end in _results:
|
for start, end in _results:
|
||||||
text = self._buffer.get_slice(start, end, include_hidden_chars = False)
|
text = self._buffer.get_slice(start, end, include_hidden_chars = False)
|
||||||
if self.use_whole_word_search:
|
if self.use_whole_word_search:
|
||||||
end.forward_char()
|
if not self.is_whole_word(start, end):
|
||||||
start.backward_char()
|
|
||||||
|
|
||||||
match = self.alpha_num_under.match( start.get_char() )
|
|
||||||
if not match is None:
|
|
||||||
continue
|
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])
|
results.append([start, end])
|
||||||
|
|
||||||
return results
|
return results
|
||||||
@ -215,9 +207,3 @@ class Plugin(PluginBase):
|
|||||||
|
|
||||||
def find_all(self, widget):
|
def find_all(self, widget):
|
||||||
...
|
...
|
||||||
|
|
||||||
def replace(self, widget):
|
|
||||||
...
|
|
||||||
|
|
||||||
def replace_all(self, widget):
|
|
||||||
...
|
|
94
plugins/search_replace/replace_mixin.py
Normal file
94
plugins/search_replace/replace_mixin.py
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ReplaceMixin:
|
||||||
|
def replace(self, widget):
|
||||||
|
replace_text = self._replace_entry.get_text()
|
||||||
|
if self.find_text and replace_text:
|
||||||
|
self._buffer.begin_user_action()
|
||||||
|
|
||||||
|
iter = self._buffer.get_start_iter()
|
||||||
|
search_tag = self._tag_table.lookup(self.search_tag)
|
||||||
|
|
||||||
|
iter.forward_to_tag_toggle(replace_text)
|
||||||
|
self._do_replace(iter, find_text)
|
||||||
|
self._active_src_view.scroll_to_mark( self._buffer.get_insert(), 0.0, True, 0.0, 0.0 )
|
||||||
|
|
||||||
|
self._buffer.end_user_action()
|
||||||
|
|
||||||
|
def replace_all(self, widget):
|
||||||
|
replace_text = self._replace_entry.get_text()
|
||||||
|
if self.find_text and replace_text:
|
||||||
|
self._buffer.begin_user_action()
|
||||||
|
|
||||||
|
mark = self._buffer.get_insert()
|
||||||
|
iter = self._buffer.get_start_iter()
|
||||||
|
search_tag = self._tag_table.lookup(self.search_tag)
|
||||||
|
|
||||||
|
while iter.forward_to_tag_toggle(search_tag):
|
||||||
|
self._do_replace(iter, replace_text)
|
||||||
|
iter = self._buffer.get_start_iter()
|
||||||
|
|
||||||
|
self._buffer.end_user_action()
|
||||||
|
|
||||||
|
|
||||||
|
def _do_replace(self, iter, text):
|
||||||
|
start, end = self.get_start_end(iter)
|
||||||
|
self.replace_in_buffer(start, end, text)
|
||||||
|
|
||||||
|
def replace_in_buffer(self, start, end, text):
|
||||||
|
pos_mark = self._buffer.create_mark("find-replace", end, True)
|
||||||
|
self._buffer.delete(start, end)
|
||||||
|
replace_iter = self._buffer.get_iter_at_mark(pos_mark)
|
||||||
|
self._buffer.insert(replace_iter, text)
|
||||||
|
|
||||||
|
def get_start_end(self, iter):
|
||||||
|
start = iter.copy()
|
||||||
|
end = None
|
||||||
|
|
||||||
|
while True:
|
||||||
|
iter.forward_char()
|
||||||
|
tags = iter.get_tags()
|
||||||
|
valid = False
|
||||||
|
for tag in tags:
|
||||||
|
if tag.props.name and self.search_tag in tag.props.name:
|
||||||
|
valid = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if valid:
|
||||||
|
continue
|
||||||
|
|
||||||
|
end = iter.copy()
|
||||||
|
break
|
||||||
|
|
||||||
|
return start, end
|
||||||
|
|
||||||
|
# NOTE: Below, lovingly taken from Hamad Al Marri's Gamma text editor.
|
||||||
|
# Link: https://gitlab.com/hamadmarri/gamma-text-editor
|
||||||
|
def is_whole_word(self, match_start, match_end):
|
||||||
|
is_prev_a_char = True
|
||||||
|
is_next_a_char = True
|
||||||
|
|
||||||
|
prev_iter = match_start.copy()
|
||||||
|
next_iter = match_end.copy()
|
||||||
|
if not prev_iter.backward_char():
|
||||||
|
is_prev_a_char = False
|
||||||
|
else:
|
||||||
|
c = prev_iter.get_char()
|
||||||
|
is_prev_a_char = (c.isalpha() or c.isdigit())
|
||||||
|
|
||||||
|
if not next_iter:
|
||||||
|
is_next_a_char = False
|
||||||
|
else:
|
||||||
|
c = next_iter.get_char()
|
||||||
|
is_next_a_char = (c.isalpha() or c.isdigit())
|
||||||
|
|
||||||
|
is_word = (not is_prev_a_char and not is_next_a_char)
|
||||||
|
|
||||||
|
# Note: Both must be false to be a word...
|
||||||
|
return is_word
|
@ -179,40 +179,6 @@
|
|||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can-focus">False</property>
|
<property name="can-focus">False</property>
|
||||||
<property name="column-homogeneous">True</property>
|
<property name="column-homogeneous">True</property>
|
||||||
<child>
|
|
||||||
<object class="GtkEntry" id="find_entry">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can-focus">True</property>
|
|
||||||
<property name="margin-start">5</property>
|
|
||||||
<property name="margin-end">10</property>
|
|
||||||
<property name="margin-top">5</property>
|
|
||||||
<property name="margin-bottom">5</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"/>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left-attach">0</property>
|
|
||||||
<property name="top-attach">0</property>
|
|
||||||
<property name="width">8</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkEntry" id="replace_entry">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can-focus">True</property>
|
|
||||||
<property name="margin-start">5</property>
|
|
||||||
<property name="margin-end">10</property>
|
|
||||||
<property name="margin-top">5</property>
|
|
||||||
<property name="margin-bottom">5</property>
|
|
||||||
<property name="placeholder-text" translatable="yes">Replace in current buffer</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left-attach">0</property>
|
|
||||||
<property name="top-attach">1</property>
|
|
||||||
<property name="width">8</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkButton">
|
<object class="GtkButton">
|
||||||
<property name="label" translatable="yes">Replace All</property>
|
<property name="label" translatable="yes">Replace All</property>
|
||||||
@ -287,6 +253,37 @@
|
|||||||
<property name="top-attach">0</property>
|
<property name="top-attach">0</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkSearchEntry" id="find_entry">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="primary-icon-name">edit-find-symbolic</property>
|
||||||
|
<property name="primary-icon-activatable">False</property>
|
||||||
|
<property name="primary-icon-sensitive">False</property>
|
||||||
|
<property name="placeholder-text" translatable="yes">Find in current buffer</property>
|
||||||
|
<signal name="search-changed" handler="search_for_string" swapped="no"/>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">0</property>
|
||||||
|
<property name="top-attach">0</property>
|
||||||
|
<property name="width">8</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkSearchEntry" id="replace_entry">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="primary-icon-name">edit-find-symbolic</property>
|
||||||
|
<property name="primary-icon-activatable">False</property>
|
||||||
|
<property name="primary-icon-sensitive">False</property>
|
||||||
|
<property name="placeholder-text" translatable="yes">Replace in current buffer</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">0</property>
|
||||||
|
<property name="top-attach">1</property>
|
||||||
|
<property name="width">8</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
|
66
plugins/search_replace/styling_mixin.py
Normal file
66
plugins/search_replace/styling_mixin.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class StylingMixin:
|
||||||
|
def tggle_regex(self, widget):
|
||||||
|
self.use_regex = not widget.get_active()
|
||||||
|
self._set_find_options_lbl()
|
||||||
|
self.search_for_string(self._find_entry)
|
||||||
|
|
||||||
|
def tggle_case_sensitive(self, widget):
|
||||||
|
self.use_case_sensitive = widget.get_active()
|
||||||
|
self._set_find_options_lbl()
|
||||||
|
self.search_for_string(self._find_entry)
|
||||||
|
|
||||||
|
def tggle_selection_only_scan(self, widget):
|
||||||
|
self.search_only_in_selection = widget.get_active()
|
||||||
|
self._set_find_options_lbl()
|
||||||
|
self.search_for_string(self._find_entry)
|
||||||
|
|
||||||
|
def tggle_whole_word_search(self, widget):
|
||||||
|
self.use_whole_word_search = widget.get_active()
|
||||||
|
self._set_find_options_lbl()
|
||||||
|
self.search_for_string(self._find_entry)
|
||||||
|
|
||||||
|
def _set_find_options_lbl(self):
|
||||||
|
find_options = "Finding with Options: "
|
||||||
|
|
||||||
|
if self.use_regex:
|
||||||
|
find_options += "Regex"
|
||||||
|
|
||||||
|
find_options += ", " if self.use_regex else ""
|
||||||
|
find_options += "Case Sensitive" if self.use_case_sensitive else "Case Inensitive"
|
||||||
|
|
||||||
|
if self.search_only_in_selection:
|
||||||
|
find_options += ", Within Current Selection"
|
||||||
|
|
||||||
|
if self.use_whole_word_search:
|
||||||
|
find_options += ", Whole Word"
|
||||||
|
|
||||||
|
self._find_options_lbl.set_label(find_options)
|
||||||
|
|
||||||
|
def update_style(self, state):
|
||||||
|
self._find_entry.get_style_context().remove_class("searching")
|
||||||
|
self._find_entry.get_style_context().remove_class("search_success")
|
||||||
|
self._find_entry.get_style_context().remove_class("search_fail")
|
||||||
|
|
||||||
|
if state == 0:
|
||||||
|
self._find_entry.get_style_context().add_class("searching")
|
||||||
|
elif state == 1:
|
||||||
|
self._find_entry.get_style_context().add_class("search_success")
|
||||||
|
elif state == 2:
|
||||||
|
self._find_entry.get_style_context().add_class("search_fail")
|
||||||
|
|
||||||
|
def _update_status_lbl(self, total_count: int = 0, query: str = None):
|
||||||
|
if not query: return
|
||||||
|
|
||||||
|
count = total_count if total_count > 0 else "No"
|
||||||
|
plural = "s" if total_count > 1 else ""
|
||||||
|
|
||||||
|
if total_count == 0: self.update_style(2)
|
||||||
|
self._find_status_lbl.set_label(f"{count} results{plural} found for '{query}'")
|
@ -103,6 +103,25 @@ popover {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.searching,
|
||||||
|
.search_success,
|
||||||
|
.search_fail {
|
||||||
|
border-style: solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searching {
|
||||||
|
border-color: rgba(0, 225, 225, 0.64);
|
||||||
|
}
|
||||||
|
.search_success {
|
||||||
|
background: rgba(136, 204, 39, 0.12);
|
||||||
|
border-color: rgba(136, 204, 39, 1);
|
||||||
|
}
|
||||||
|
.search_fail {
|
||||||
|
background: rgba(170, 18, 18, 0.12);
|
||||||
|
border-color: rgba(200, 18, 18, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.error_txt { color: rgb(170, 18, 18); }
|
.error_txt { color: rgb(170, 18, 18); }
|
||||||
.warning_txt { color: rgb(255, 168, 0); }
|
.warning_txt { color: rgb(255, 168, 0); }
|
||||||
.success_txt { color: rgb(136, 204, 39); }
|
.success_txt { color: rgb(136, 204, 39); }
|
||||||
|
Loading…
Reference in New Issue
Block a user