From 0dece2cec96254cc2644ff5478bd87dcf1e5e6cb Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Tue, 4 Oct 2022 02:30:46 -0500 Subject: [PATCH] More searcher plugin updates, added additional file settings --- plugins/searcher/mixins/grep_search_mixin.py | 3 +- plugins/searcher/utils/search.py | 69 ++++++++++++++----- .../searcher/widgets/grep_preview_widget.py | 52 +++++++------- 3 files changed, 78 insertions(+), 46 deletions(-) diff --git a/plugins/searcher/mixins/grep_search_mixin.py b/plugins/searcher/mixins/grep_search_mixin.py index 860a346..cdf1c58 100644 --- a/plugins/searcher/mixins/grep_search_mixin.py +++ b/plugins/searcher/mixins/grep_search_mixin.py @@ -70,4 +70,5 @@ class GrepSearchMixin: grep_result = jdata[key] widget = GrepPreviewWidget(key, sub_keys, grep_result) - self._grep_list.add(widget) + GLib.idle_add(self._grep_list.add, widget) + # self._grep_list.add(widget) diff --git a/plugins/searcher/utils/search.py b/plugins/searcher/utils/search.py index f06f3fa..1355f1d 100755 --- a/plugins/searcher/utils/search.py +++ b/plugins/searcher/utils/search.py @@ -2,7 +2,7 @@ # Python imports -import os, traceback, argparse, json, base64 +import os, traceback, argparse, threading, json, base64, time from setproctitle import setproctitle from multiprocessing.connection import Client @@ -16,11 +16,20 @@ from multiprocessing.connection import Client _ipc_address = f'/tmp/solarfm-search_grep-ipc.sock' _ipc_authkey = b'' + bytes(f'solarfm-search_grep-ipc', 'utf-8') -filter = (".mkv", ".mp4", ".webm", ".avi", ".mov", ".m4v", ".mpg", ".mpeg", ".wmv", ".flv") + \ - (".png", ".jpg", ".jpeg", ".gif", ".ico", ".tga", ".webp") + \ - (".psf", ".mp3", ".ogg", ".flac", ".m4a") +filter = (".cpp", ".css", ".c", ".go", ".html", ".htm", ".java", ".js", ".json", ".lua", ".md", ".py", ".rs", ".toml", ".xml", ".pom") + \ + (".txt", ".text", ".sh", ".cfg", ".conf", ".log") -file_result_set = [] +# 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 def send_ipc_message(message) -> None: @@ -42,7 +51,7 @@ def file_search(path, query): if os.path.isdir(target): file_search(target, query) else: - if query.lower() in file.lower(): + if query in file.lower(): data = f"SEARCH|{json.dumps([target, file])}" send_ipc_message(data) except Exception as e: @@ -52,21 +61,40 @@ def file_search(path, query): def _search_for_string(file, query): b64_file = base64.urlsafe_b64encode(file.encode('utf-8')).decode('utf-8') grep_result_set = {} - + padding = 15 with open(file, 'r') as fp: - for i, line in enumerate(fp): - if query in line: - b64_line = base64.urlsafe_b64encode(line.encode('utf-8')).decode('utf-8') + # NOTE: I know there's an issue if there's a very large file with content all on one line will lower and dupe it. + # And, yes, it will only return one instance from the file. + for i, raw in enumerate(fp): + line = None + llower = raw.lower() + if not query in llower: + continue - if f"{b64_file}" in grep_result_set.keys(): - grep_result_set[f"{b64_file}"][f"{i+1}"] = b64_line - else: - grep_result_set[f"{b64_file}"] = {} - grep_result_set[f"{b64_file}"] = {f"{i+1}": b64_line} + if len(raw) > 72: + start = 0 + end = len(raw) - 1 + index = llower.index(query) + sindex = llower.index(query) - 15 if index >= 15 else abs(start - index) - index + eindex = sindex + 15 if end > (index + 15) else abs(index - end) + index + line = raw[sindex:eindex] + else: + line = raw + + b64_line = base64.urlsafe_b64encode(line.encode('utf-8')).decode('utf-8') + if f"{b64_file}" in grep_result_set.keys(): + grep_result_set[f"{b64_file}"][f"{i+1}"] = b64_line + else: + grep_result_set[f"{b64_file}"] = {} + grep_result_set[f"{b64_file}"] = {f"{i+1}": b64_line} data = f"GREP|{json.dumps(grep_result_set)}" send_ipc_message(data) +@daemon_threaded +def _search_for_string_threaded(file, query): + _search_for_string(file, query) + def grep_search(path, query): try: @@ -75,18 +103,23 @@ def grep_search(path, query): if os.path.isdir(target): grep_search(target, query) else: - if not target.lower().endswith(filter): + if target.lower().endswith(filter): + size = os.path.getsize(target) + if size < 5000: _search_for_string(target, query) + else: + _search_for_string_threaded(target, query) + except Exception as e: print("Couldn't traverse to path. Might be permissions related...") traceback.print_exc() def search(args): if args.type == "file_search": - file_search(args.dir, args.query) + file_search(args.dir, args.query.lower()) if args.type == "grep_search": - grep_search(args.dir, args.query) + grep_search(args.dir, args.query.lower()) if __name__ == "__main__": diff --git a/plugins/searcher/widgets/grep_preview_widget.py b/plugins/searcher/widgets/grep_preview_widget.py index 85aa2f8..899d309 100644 --- a/plugins/searcher/widgets/grep_preview_widget.py +++ b/plugins/searcher/widgets/grep_preview_widget.py @@ -10,37 +10,35 @@ from gi.repository import Gtk class GrepPreviewWidget(Gtk.Box): - def __init__(self, _path, sub_keys, data): + def __init__(self, _path, sub_keys, _data): super(GrepPreviewWidget, self).__init__() self.set_orientation(Gtk.Orientation.VERTICAL) self.line_color = "#e0cc64" - path = base64.urlsafe_b64decode(_path.encode('utf-8')).decode('utf-8') - _label = '/'.join( path.split("/")[-3:] ) - title = Gtk.LinkButton.new_with_label(uri=f"file://{path}", label=_label) + path = self.decode_str(_path) + _label = '/'.join( path.split("/")[-3:] ) + title = Gtk.LinkButton.new_with_label(uri=f"file://{path}", label=_label) + + text_view = Gtk.TextView() + text_view.set_editable(False) + text_view.set_wrap_mode(Gtk.WrapMode.NONE) + buffer = text_view.get_buffer() + + for i, key in enumerate(sub_keys): + line_num = self.make_utf8_line_num(self.line_color, key) + text = f"\t\t{ self.decode_str(_data[key]) }" + + itr = buffer.get_end_iter() + buffer.insert_markup(itr, line_num, len(line_num)) + itr = buffer.get_end_iter() + buffer.insert(itr, text, length=len(text)) self.add(title) - for key in sub_keys: - line_num = key - text = base64.urlsafe_b64decode(data[key].encode('utf-8')).decode('utf-8') - - - box = Gtk.Box() - number_label = Gtk.Label() - text_view = Gtk.Label(label=text[:-1]) - label_text = f"{line_num}" - - number_label.set_markup(label_text) - number_label.set_margin_left(15) - number_label.set_margin_right(5) - number_label.set_margin_top(5) - number_label.set_margin_bottom(5) - text_view.set_margin_top(5) - text_view.set_margin_bottom(5) - text_view.set_line_wrap(True) - - box.add(number_label) - box.add(text_view) - self.add(box) - + self.add(text_view) self.show_all() + + def decode_str(self, target): + return base64.urlsafe_b64decode(target.encode('utf-8')).decode('utf-8') + + def make_utf8_line_num(self, color, target): + return bytes(f"\n{target}", "utf-8").decode("utf-8")