Clean up codebase and improve file loading
- Moved plugins to proper sub groups (autopairs, code_minimap, colorize, commentzar, info_bar, markdown_preview, prettify_json, search_replace, tabs_bar, telescope, toggle_source_view, lsp_client) - Add filter_out_loaded_files to prevent opening already-loaded files - Add INDEPENDENT source view state - Fix cursor scroll position on buffer switch - Fix signal blocking during file load - Fix word boundary in completion provider - Refactor code events into single events module
This commit is contained in:
3
plugins/code/ui/search_replace/mixins/__init__.py
Normal file
3
plugins/code/ui/search_replace/mixins/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
Pligin Module Mixins
|
||||
"""
|
||||
50
plugins/code/ui/search_replace/mixins/replace_mixin.py
Normal file
50
plugins/code/ui/search_replace/mixins/replace_mixin.py
Normal file
@@ -0,0 +1,50 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class ReplaceMixin:
|
||||
|
||||
def _replace_word(
|
||||
self,
|
||||
current_index: int,
|
||||
to_text: str,
|
||||
buffer: any
|
||||
):
|
||||
self.clear_highlight(buffer)
|
||||
|
||||
start_itr, end_itr = self.matches[current_index]
|
||||
self.active_view.scroll_to_iter(end_itr, 0.2, False, 0, 0)
|
||||
|
||||
buffer.begin_user_action()
|
||||
buffer.delete(start_itr, end_itr)
|
||||
buffer.insert(start_itr, to_text)
|
||||
buffer.end_user_action()
|
||||
|
||||
def _replace_all_words(self, to_text: str, buffer: any):
|
||||
marks: list = []
|
||||
|
||||
for start_itr, end_itr in self.matches:
|
||||
start_mark = buffer.create_mark(None, start_itr, left_gravity = True)
|
||||
end_mark = buffer.create_mark(None, end_itr, left_gravity = False)
|
||||
marks.append((start_mark, end_mark))
|
||||
|
||||
buffer.begin_user_action()
|
||||
|
||||
for start_mark, end_mark in reversed(marks):
|
||||
start_itr = buffer.get_iter_at_mark(start_mark)
|
||||
end_itr = buffer.get_iter_at_mark(end_mark)
|
||||
|
||||
buffer.delete(start_itr, end_itr)
|
||||
buffer.insert(start_itr, to_text)
|
||||
|
||||
buffer.end_user_action()
|
||||
|
||||
for start_mark, end_mark in marks:
|
||||
buffer.delete_mark(start_mark)
|
||||
buffer.delete_mark(end_mark)
|
||||
|
||||
self.find_entry.grab_focus()
|
||||
77
plugins/code/ui/search_replace/mixins/search_mixin.py
Normal file
77
plugins/code/ui/search_replace/mixins/search_mixin.py
Normal file
@@ -0,0 +1,77 @@
|
||||
# Python imports
|
||||
from contextlib import suppress
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class SearchMixin:
|
||||
def is_word_char(self, ch):
|
||||
return ch.isalnum() or ch == "_"
|
||||
|
||||
def is_whole_word(self, start_itr, end_itr, buffer):
|
||||
if start_itr.backward_char():
|
||||
prev_char = start_itr.get_char()
|
||||
if self.is_word_char(prev_char):
|
||||
return False
|
||||
|
||||
next_char = end_itr.get_char()
|
||||
if self.is_word_char(next_char):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def _find_all_matches(self, search_text, buffer):
|
||||
self.update_style(0)
|
||||
|
||||
self.matches.clear()
|
||||
self.current_index = -1
|
||||
|
||||
start_itr = buffer.get_start_iter()
|
||||
end_itr = buffer.get_end_iter()
|
||||
|
||||
case_mode = Gtk.TextSearchFlags.CASE_INSENSITIVE if not self.mode_bttn_box.match_case else Gtk.TextSearchFlags.TEXT_ONLY
|
||||
whole_word = self.mode_bttn_box.whole_word
|
||||
if self.mode_bttn_box.in_selection:
|
||||
with suppress(Exception):
|
||||
start_itr, end_itr = buffer.get_selection_bounds()
|
||||
|
||||
while True:
|
||||
match = start_itr.forward_search(
|
||||
search_text,
|
||||
case_mode,
|
||||
end_itr
|
||||
)
|
||||
|
||||
if not match: break
|
||||
|
||||
match_start, match_end = match
|
||||
if whole_word and not self.is_whole_word(match_start.copy(), match_end.copy(), buffer):
|
||||
start_itr = match_end
|
||||
continue
|
||||
|
||||
self.matches.append(
|
||||
(match_start.copy(), match_end.copy())
|
||||
)
|
||||
|
||||
start_itr = match_end
|
||||
|
||||
def _highlight_all_matches(self, buffer):
|
||||
self.clear_highlight(buffer)
|
||||
|
||||
for start_itr, end_itr in self.matches:
|
||||
buffer.apply_tag(self.highlight_tag, start_itr, end_itr)
|
||||
|
||||
def _search_for_next_word(self, buffer):
|
||||
self.current_index = (self.current_index + 1) % len(self.matches)
|
||||
self._highlight_current(self.current_index, buffer)
|
||||
|
||||
def _search_for_prev_word(self, buffer):
|
||||
self.current_index = (self.current_index - 1) % len(self.matches)
|
||||
self._highlight_current(self.current_index, buffer)
|
||||
@@ -0,0 +1,91 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gdk', '3.0')
|
||||
from gi.repository import Gdk
|
||||
|
||||
# Application imports
|
||||
from .search_mixin import SearchMixin
|
||||
from .replace_mixin import ReplaceMixin
|
||||
|
||||
|
||||
|
||||
class SearchReplaceMixin(SearchMixin, ReplaceMixin):
|
||||
|
||||
def _find_entry_focus_in_event(self, entry, event):
|
||||
search_text = entry.get_text()
|
||||
buffer = self.active_view.get_buffer()
|
||||
|
||||
if buffer.get_has_selection() and not search_text:
|
||||
if not self.mode_bttn_box.in_selection:
|
||||
start_itr, end_itr = buffer.get_selection_bounds()
|
||||
|
||||
entry.set_text(
|
||||
buffer.get_text(
|
||||
start_itr,
|
||||
end_itr,
|
||||
include_hidden_chars = False
|
||||
)
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
def _find_entry_search_change(self, entry):
|
||||
search_text = entry.get_text()
|
||||
buffer = self.active_view.get_buffer()
|
||||
self.highlight_tag = buffer.get_tag_table().lookup("search-highlight")
|
||||
|
||||
if not search_text:
|
||||
self.update_style(-1)
|
||||
self.clear_highlight(buffer)
|
||||
self.status_lbl.set_label("Find in current buffer...")
|
||||
return
|
||||
|
||||
self._find_all_matches(search_text, buffer)
|
||||
self._highlight_all_matches(buffer)
|
||||
self._update_status_lbl(len(self.matches), search_text)
|
||||
|
||||
def _find_entry_activate(self, entry):
|
||||
self._find_entry_next_match(entry)
|
||||
|
||||
def _find_entry_next_match(self, entry):
|
||||
search_text = entry.get_text()
|
||||
|
||||
if not search_text: return
|
||||
|
||||
buffer = self.active_view.get_buffer()
|
||||
self._search_for_next_word(buffer)
|
||||
|
||||
def _find_entry_previous_match(self, entry):
|
||||
search_text = entry.get_text()
|
||||
|
||||
if not search_text: return
|
||||
|
||||
buffer = self.active_view.get_buffer()
|
||||
self._search_for_prev_word(buffer)
|
||||
|
||||
def _replace_entry_activate(self, entry):
|
||||
to_text = entry.get_text()
|
||||
|
||||
if not to_text: return
|
||||
|
||||
buffer = self.active_view.get_buffer()
|
||||
self._replace_word(self.current_index, to_text, buffer)
|
||||
self._find_entry_search_change(self.find_entry)
|
||||
|
||||
def _replace_all_activate(self, entry):
|
||||
to_text = entry.get_text()
|
||||
|
||||
if not to_text: return
|
||||
|
||||
buffer = self.active_view.get_buffer()
|
||||
self._replace_all_words(to_text, buffer)
|
||||
|
||||
def _highlight_current(self, current_index, buffer):
|
||||
self.clear_highlight(buffer)
|
||||
|
||||
start_itr, end_itr = self.matches[current_index]
|
||||
buffer.apply_tag(self.highlight_tag, start_itr, end_itr)
|
||||
|
||||
self.active_view.scroll_to_iter(end_itr, 0.2, False, 0, 0)
|
||||
Reference in New Issue
Block a user