multi file open setup; search/replace plugin initial rework

This commit is contained in:
itdominator 2024-02-25 15:46:51 -06:00
parent 070d94abc1
commit 5fcf2d6f1a
7 changed files with 247 additions and 128 deletions

View File

@ -69,64 +69,70 @@ class Plugin(StylingMixin, ReplaceMixin, PluginBase):
def subscribe_to_events(self):
self._event_system.subscribe("tggl_search_replace", self._tggl_search_replace)
self._event_system.subscribe("set_active_src_view", self._set_active_src_view)
# self._event_system.subscribe("set_active_src_view", self._set_active_src_view)
def _set_active_src_view(self, 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)
# def _set_active_src_view(self, 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)
def _show_search_replace(self, widget = None, eve = None):
self._search_replace_dialog.popup()
def _tggl_search_replace(self, widget = None, eve = None):
is_visible = self._search_replace_dialog.is_visible()
buffer = self._active_src_view.get_buffer()
data = None
if buffer.get_has_selection():
start, end = buffer.get_selection_bounds()
data = buffer.get_text(start, end, include_hidden_chars = False)
if data:
self._find_entry.set_text(data)
if not is_visible:
self._search_replace_dialog.popup();
self._find_entry.grab_focus()
elif not data and is_visible:
self._search_replace_dialog.popdown()
self._find_entry.set_text("")
else:
self._find_entry.grab_focus()
self._search_replace_dialog.popdown();
# buffer = self._active_src_view.get_buffer()
# data = None
# if buffer.get_has_selection():
# start, end = buffer.get_selection_bounds()
# data = buffer.get_text(start, end, include_hidden_chars = False)
# if data:
# self._find_entry.set_text(data)
# if not is_visible:
# self._search_replace_dialog.popup();
# self._find_entry.grab_focus()
# elif not data and is_visible:
# self._search_replace_dialog.popdown()
# self._find_entry.set_text("")
# else:
# self._find_entry.grab_focus()
def get_search_tag(self, buffer):
tag_table = buffer.get_tag_table()
search_tag = tag_table.lookup(self.search_tag)
if not search_tag:
search_tag = buffer.create_tag(self.search_tag, background = self.highlight_color, foreground = self.text_color)
# def get_search_tag(self, buffer):
# tag_table = buffer.get_tag_table()
# search_tag = tag_table.lookup(self.search_tag)
# if not search_tag:
# search_tag = buffer.create_tag(self.search_tag, background = self.highlight_color, foreground = self.text_color)
buffer.remove_tag_by_name(self.search_tag, buffer.get_start_iter(), buffer.get_end_iter())
return search_tag
# buffer.remove_tag_by_name(self.search_tag, buffer.get_start_iter(), buffer.get_end_iter())
# return search_tag
def cancel_timer(self):
if self.timer:
self.timer.cancel()
GLib.idle_remove_by_data(None)
# 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_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)
# 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()
# self.timer = threading.Timer(wait_time, self.delay_search_glib)
# self.timer.daemon = True
# self.timer.start()
def on_enter_search(self, widget, eve):
@ -138,84 +144,133 @@ class Plugin(StylingMixin, ReplaceMixin, PluginBase):
self.find_next(widget)
def search_for_string(self, widget):
self.cancel_timer()
# query = self._find_entry.get_text()
query = widget.get_text()
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)
if not query: return
isBackwwards = True
isWrap = True
isCaseSensitive = self.use_case_sensitive
useWholeWord = self.use_whole_word_search
useRegExp = self.use_regex
# self.search_only_in_selection
self._event_system.emit(
"find_entry",
(
query,
isBackwwards,
isWrap,
isCaseSensitive,
useWholeWord,
useRegExp,
)
)
def _do_highlight(self, query = None):
query = self.find_text if not query else query
buffer = self._active_src_view.get_buffer()
# Also clears tag from buffer so if no query we're clean in ui
search_tag = self.get_search_tag(buffer)
# def search_for_string(self, widget):
# self.cancel_timer()
self.update_style(1)
if not query:
self._find_status_lbl.set_label(f"Find in current buffer")
self.update_style(0)
return
# 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)
start_itr = buffer.get_start_iter()
end_itr = buffer.get_end_iter()
results, total_count = self.search(start_itr, query)
self._update_status_lbl(total_count, query)
for start, end in results:
buffer.apply_tag(search_tag, start, end)
# def _do_highlight(self, query = None):
# query = self.find_text if not query else query
# buffer = self._active_src_view.get_buffer()
# # Also clears tag from buffer so if no query we're clean in ui
# search_tag = self.get_search_tag(buffer)
def search(self, start_itr = None, query = None, limit = None):
if not start_itr or not query: return None, None
# self.update_style(1)
# if not query:
# self._find_status_lbl.set_label(f"Find in current buffer")
# self.update_style(0)
# return
flags = Gtk.TextSearchFlags.VISIBLE_ONLY | Gtk.TextSearchFlags.TEXT_ONLY
if not self.use_case_sensitive:
flags = flags | Gtk.TextSearchFlags.CASE_INSENSITIVE
# start_itr = buffer.get_start_iter()
# end_itr = buffer.get_end_iter()
if self.search_only_in_selection and self._buffer.get_has_selection():
start_itr, limit = self._buffer.get_selection_bounds()
# results, total_count = self.search(start_itr, query)
# self._update_status_lbl(total_count, query)
# for start, end in results:
# buffer.apply_tag(search_tag, start, end)
_results = []
while True:
result = start_itr.forward_search(query, flags, limit)
if not result: break
# def search(self, start_itr = None, query = None, limit = None):
# if not start_itr or not query: return None, None
_results.append(result)
start_itr = result[1]
# flags = Gtk.TextSearchFlags.VISIBLE_ONLY | Gtk.TextSearchFlags.TEXT_ONLY
# if not self.use_case_sensitive:
# flags = flags | Gtk.TextSearchFlags.CASE_INSENSITIVE
results = self.apply_filters(_results, query)
return results, len(results)
# if self.search_only_in_selection and self._buffer.get_has_selection():
# start_itr, limit = self._buffer.get_selection_bounds()
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:
if not self.is_whole_word(start, end):
continue
# _results = []
# while True:
# result = start_itr.forward_search(query, flags, limit)
# if not result: break
results.append([start, end])
# _results.append(result)
# start_itr = result[1]
return results
# results = self.apply_filters(_results, query)
# 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:
# if not self.is_whole_word(start, end):
# continue
# 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()
self._event_system.emit("find_next_entry")
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)
def find_prior(self, widget, eve = None, use_data = None):
self._event_system.emit("find_prior_entry")
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, 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_all(self, widget):
...
...
def replace(self, widget):
fromStr = self._find_entry.get_text()
toStr = self._replace_entry.get_text()
if not fromStr or not toStr: return
self._event_system.emit("replace_entry", (fromStr, toStr))
def replace_all(self, widget):
fromStr = self._find_entry.get_text()
toStr = self._replace_entry.get_text()
if not fromStr or not toStr: return
self._event_system.emit("replace_all", (fromStr, toStr))

View File

@ -72,7 +72,6 @@
<object class="GtkToggleButton">
<property name="label" translatable="yes">.*</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can-focus">True</property>
<property name="focus-on-click">False</property>
<property name="receives-default">True</property>

View File

@ -24,6 +24,10 @@ class BridgeController:
event_system.subscribe(f"keyboard_open_file", self.keyboard_open_file)
event_system.subscribe(f"keyboard_scale_up_text", self.keyboard_scale_up_text)
event_system.subscribe(f"keyboard_scale_down_text", self.keyboard_scale_down_text)
event_system.subscribe(f"find_entry", self.find_entry)
event_system.subscribe(f"find_next_entry", self.find_next_entry)
event_system.subscribe(f"find_previous_entry", self.find_previous_entry)
event_system.subscribe(f"replace_entry", self.replace_entry)
event_system.subscribe(f"toggle_highlight_line", self.toggle_highlight_line)
def keyboard_open_file(self, gfiles):
@ -38,6 +42,33 @@ class BridgeController:
def toggle_highlight_line(self):
event_system.emit(f"toggle_highlight_line_{self.originator}")
def find_entry(self, query, isBackwwards, isWrap, isCaseSensitive,
useWholeWord,
useRegExp):
event_system.emit(
f"find_entry_{self.originator}",
(
query,
isBackwwards,
isWrap,
isCaseSensitive,
useWholeWord,
useRegExp
)
)
def find_next_entry(self):
event_system.emit(f"find_next_entry_{self.originator}")
def find_previous_entry(self):
event_system.emit(f"find_previous_entry_{self.originator}")
def replace_entry(self, fromStr, toStr):
event_system.emit(f"replace_entry_{self.originator}", (fromStr, toStr,))
def replace_all(self, fromStr, toStr):
event_system.emit(f"replace_all_{self.originator}", (fromStr, toStr,))
def handle_bridge_event(self, event):
self.originator = event.originator
@ -56,10 +87,6 @@ class BridgeController:
event_system.emit(f"handle_file_event_{event.originator}", (event,))
case "tggl_search_replace":
event_system.emit(f"tggl_search_replace")
case "find_entry":
event_system.emit(f"find_entry_{event.originator}")
case "replace_entry":
event_system.emit(f"replace_entry_{event.originator}")
case "tggl_top_main_menubar":
event_system.emit("tggl_top_main_menubar")
case "set_info_labels":

View File

@ -86,7 +86,14 @@ class FilesController:
content = base64.b64decode( event.content.encode() ).decode("utf-8")
# event_system.emit(f"add_tab_with_name_{event.originator}", (event.fhash, content,))
case "open_file":
event_system.emit(f"open_files", (None, None, self.INDEX,))
_gfiles = event_system.emit_and_await(f"open_files", (None, None, event.fpath,))
if _gfiles:
event_system.emit(
f"set_pre_drop_dnd_{self.INDEX}",
(
_gfiles,
)
)
case _:
return

View File

@ -54,7 +54,10 @@ class AceEditor(WebKit2.WebView):
event_system.subscribe(f"keyboard_scale_down_text_{self.INDEX}", self.keyboard_scale_down_text)
event_system.subscribe(f"toggle_highlight_line_{self.INDEX}", self.toggle_highlight_line)
event_system.subscribe(f"find_entry_{self.INDEX}", self.find_entry)
event_system.subscribe(f"find_next_entry_{self.INDEX}", self.find_next_entry)
event_system.subscribe(f"find_previous_entry_{self.INDEX}", self.find_previous_entry)
event_system.subscribe(f"replace_entry_{self.INDEX}", self.replace_entry)
event_system.subscribe(f"replace_all_{self.INDEX}", self.replace_all)
event_system.subscribe(f"ui_message_{self.INDEX}", self.ui_message)
def _load_settings(self):
@ -126,8 +129,18 @@ class AceEditor(WebKit2.WebView):
command = f"displayMessage('{message}', '{mtype}', '3')"
self.run_javascript(command, None, None)
def find_entry(self, query):
command = f"findEntry('{query}')"
def find_entry(self, query, isBackwwards, isWrap, isCaseSensitive,
useWholeWord,
useRegExp):
command = f"findEntry('{query}', '{isBackwwards}', '{isWrap}', '{isCaseSensitive}', '{useWholeWord}', '{useRegExp}')"
self.run_javascript(command, None, None)
def find_next_entry(self):
command = f"findNextEntry()"
self.run_javascript(command, None, None)
def find_previous_entry(self):
command = f"findPreviousEntry()"
self.run_javascript(command, None, None)
def replace_entry(self, fromStr, toStr):

View File

@ -41,37 +41,46 @@ class OpenFileButton(Gtk.Button):
def _load_widgets(self):
...
def _open_files(self, widget = None, eve = None, widget_index = None):
chooser = Gtk.FileChooserDialog("Open File...", None,
def _open_files(self, widget = None, eve = None, fpath = None):
start_dir = None
gfile = Gio.File.new_for_path(fpath)
_gfiles = []
if gfile.query_exists():
start_dir = gfile.get_parent()
chooser = Gtk.FileChooserDialog("Open File(s)...", None,
Gtk.FileChooserAction.OPEN,
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
(
Gtk.STOCK_CANCEL,
Gtk.ResponseType.CANCEL,
Gtk.STOCK_OPEN,
Gtk.ResponseType.OK
)
)
chooser.set_select_multiple(True)
try:
folder = widget.get_current_file().get_parent()
chooser.set_current_folder( folder.get_uri() )
folder = widget.get_current_file().get_parent() if not start_dir else start_dir
chooser.set_current_folder( folder.get_path() )
except Exception as e:
...
response = chooser.run()
if not response == Gtk.ResponseType.OK:
chooser.destroy()
return
return _gfiles
filename = chooser.get_filename()
if not filename:
filenames = chooser.get_filenames()
if not filenames:
chooser.destroy()
return
return _gfiles
path = filename if os.path.isabs(filename) else os.path.abspath(filename)
_gfile = Gio.File.new_for_path(path)
event_system.emit(
f"set_pre_drop_dnd_{widget_index}" if widget_index else "keyboard_open_file",
(
[_gfile],
)
)
for file in filenames:
path = file if os.path.isabs(file) else os.path.abspath(file)
_gfiles.append( Gio.File.new_for_path(path) )
chooser.destroy()
return _gfiles

View File

@ -17,13 +17,22 @@ const editorCommands = [
editor.showKeyboardShortcuts();
})
}
}, {
name: "search",
bindKey: {win: "ctrl-f", mac: "ctrl-f"},
exec: function(editor) {
sendMessage("tggl_search_replace", "", "", "", "");
},
readOnly: true
}, {
name: "openFile",
bindKey: {win: "ctrl-o", mac: "ctrl-o"},
exec: function(editor) {
sendMessage("open_file", "", "", "", "");
fpath = aceSessions[currentSession]["fpath"]
sendMessage("open_file", "", "", fpath, "");
},
readOnly: true
}, {
name: "saveSession",
bindKey: {win: "ctrl-s", mac: "ctrl-s"},