From 61b8bbc5faf7a15cf3ed18c0f9162d0aa9ca3555 Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Wed, 18 Feb 2026 23:49:01 -0600 Subject: [PATCH] Moved plugins and refactor command system - Moved plugins to apropriate sub folders - Refactor command system with new add_command method and rename GetCommandSystemEvent to GetNewCommandSystemEvent - Add RegisterCommandEvent for dynamic command registration - Change footer container orientation to VERTICAL - Add search-highlight tag to source buffer - Add file change detection (deleted, externally modified) in source_file - Add JSON prettify option to source view popup menu - Enable hexpand on VTE widget - Update plugins_controller_mixin to use widget_registry --- .../commentzar}/__init__.py | 0 .../commentzar}/__main__.py | 0 plugins/code/commentzar/commenter.py | 66 ++++ .../commentzar/manifest.json | 5 +- plugins/code/commentzar/mixins/__init__.py | 3 + .../mixins/code_comment_tags_mixin.py | 30 ++ plugins/code/commentzar/plugin.py | 49 +++ .../completers/example_completer}/__init__.py | 0 .../completers/example_completer}/__main__.py | 0 .../example_completer/manifest.json | 0 .../completers/example_completer/plugin.py | 5 +- .../completers/example_completer/provider.py | 8 +- .../provider_response_cache.py | 4 + .../completers/lsp_completer}/__init__.py | 0 .../completers/lsp_completer}/__main__.py | 0 .../completers/lsp_completer/manifest.json | 0 .../completers/lsp_completer/plugin.py | 5 +- .../completers/lsp_completer/provider.py | 0 .../lsp_completer/provider_response_cache.py | 12 +- .../completers/python_completer}/__init__.py | 0 .../completers/python_completer}/__main__.py | 0 .../completers/python_completer/manifest.json | 0 .../completers/python_completer/plugin.py | 5 +- .../completers/python_completer/provider.py | 0 .../provider_response_cache.py | 0 .../snippets_completer}/__init__.py | 0 .../snippets_completer}/__main__.py | 0 .../snippets_completer/cson/__init__.py | 0 .../snippets_completer/cson/parser.py | 0 .../snippets_completer/cson/speg/__init__.py | 0 .../snippets_completer/cson/speg/peg.py | 0 .../snippets_completer/cson/writer.py | 0 .../snippets_completer/manifest.json | 0 .../completers/snippets_completer/plugin.py | 5 +- .../completers/snippets_completer/provider.py | 0 .../provider_response_cache.py | 0 .../snippets_completer/snippets.cson | 0 .../completers/words_completer}/__init__.py | 0 .../completers/words_completer}/__main__.py | 0 .../words_completer/alt_provider.py | 0 .../completers/words_completer/manifest.json | 0 .../completers/words_completer/plugin.py | 5 +- .../completers/words_completer/provider.py | 5 + .../provider_response_cache.py | 16 +- .../search_replace/__init__.py | 0 .../search_replace/__main__.py | 0 .../images/only-in-selection.png | Bin 0 -> 6270 bytes .../code/search_replace/images/whole-word.png | Bin 0 -> 6651 bytes plugins/code/search_replace/manifest.json | 7 + .../code/search_replace/mixins/__init__.py | 3 + .../search_replace/mixins/replace_mixin.py | 50 +++ .../search_replace/mixins/search_mixin.py | 79 +++++ .../mixins/search_replace_mixin.py | 88 ++++++ plugins/code/search_replace/mode_buttons.py | 75 +++++ plugins/code/search_replace/plugin.py | 65 ++++ plugins/code/search_replace/search_replace.py | 152 +++++++++ .../commentzar/add_comment_mixin.py | 66 ---- .../depricated/commentzar/codecomment_tags.py | 30 -- plugins/depricated/commentzar/plugin.py | 118 ------- .../commentzar/remove_comment_mixin.py | 49 --- .../depricated/search_replace/manifest.json | 12 - plugins/depricated/search_replace/plugin.py | 221 ------------- .../search_replace/replace_mixin.py | 94 ------ .../search_replace/search_replace.glade | 299 ------------------ .../search_replace/styling_mixin.py | 66 ---- plugins/{ => ui}/template/__init__.py | 0 plugins/{ => ui}/template/__main__.py | 0 plugins/{ => ui}/template/manifest.json | 0 plugins/{ => ui}/template/plugin.py | 7 +- src/__builtins__.py | 1 + src/core/containers/footer_container.py | 2 +- src/core/controllers/base_controller.py | 1 + .../code/command_system/command_system.py | 3 + .../code/command_system/commands/__init__.py | 2 +- .../commands/dnd_load_file_to_buffer.py | 8 +- .../code/controllers/commands_controller.py | 6 +- .../views/source_views_controller.py | 18 +- .../code/controllers/views/state_manager.py | 1 + src/core/widgets/code/key_mapper.py | 38 +-- src/core/widgets/code/source_buffer.py | 7 +- src/core/widgets/code/source_file.py | 16 + src/core/widgets/code/source_view.py | 32 ++ src/core/widgets/vte_widget.py | 1 + src/libs/dto/code/__init__.py | 3 +- ...ent.py => get_new_command_system_event.py} | 2 +- src/libs/dto/code/register_command_event.py | 20 ++ src/libs/event_factory.py | 2 +- src/plugins/plugin_types/plugin_code.py | 3 + src/plugins/plugins_controller_mixin.py | 9 +- 89 files changed, 850 insertions(+), 1029 deletions(-) rename plugins/{completers/example_completer => code/commentzar}/__init__.py (100%) rename plugins/{completers/example_completer => code/commentzar}/__main__.py (100%) create mode 100644 plugins/code/commentzar/commenter.py rename plugins/{depricated => code}/commentzar/manifest.json (51%) create mode 100644 plugins/code/commentzar/mixins/__init__.py create mode 100755 plugins/code/commentzar/mixins/code_comment_tags_mixin.py create mode 100644 plugins/code/commentzar/plugin.py rename plugins/{completers/lsp_completer => code/completers/example_completer}/__init__.py (100%) rename plugins/{completers/lsp_completer => code/completers/example_completer}/__main__.py (100%) rename plugins/{ => code}/completers/example_completer/manifest.json (100%) rename plugins/{ => code}/completers/example_completer/plugin.py (83%) rename plugins/{ => code}/completers/example_completer/provider.py (89%) rename plugins/{ => code}/completers/example_completer/provider_response_cache.py (92%) rename plugins/{completers/python_completer => code/completers/lsp_completer}/__init__.py (100%) rename plugins/{completers/python_completer => code/completers/lsp_completer}/__main__.py (100%) rename plugins/{ => code}/completers/lsp_completer/manifest.json (100%) rename plugins/{ => code}/completers/lsp_completer/plugin.py (84%) rename plugins/{ => code}/completers/lsp_completer/provider.py (100%) rename plugins/{ => code}/completers/lsp_completer/provider_response_cache.py (75%) rename plugins/{completers/snippets_completer => code/completers/python_completer}/__init__.py (100%) rename plugins/{completers/snippets_completer => code/completers/python_completer}/__main__.py (100%) rename plugins/{ => code}/completers/python_completer/manifest.json (100%) rename plugins/{ => code}/completers/python_completer/plugin.py (83%) rename plugins/{ => code}/completers/python_completer/provider.py (100%) rename plugins/{ => code}/completers/python_completer/provider_response_cache.py (100%) rename plugins/{completers/words_completer => code/completers/snippets_completer}/__init__.py (100%) rename plugins/{completers/words_completer => code/completers/snippets_completer}/__main__.py (100%) rename plugins/{ => code}/completers/snippets_completer/cson/__init__.py (100%) rename plugins/{ => code}/completers/snippets_completer/cson/parser.py (100%) rename plugins/{ => code}/completers/snippets_completer/cson/speg/__init__.py (100%) rename plugins/{ => code}/completers/snippets_completer/cson/speg/peg.py (100%) rename plugins/{ => code}/completers/snippets_completer/cson/writer.py (100%) rename plugins/{ => code}/completers/snippets_completer/manifest.json (100%) rename plugins/{ => code}/completers/snippets_completer/plugin.py (83%) rename plugins/{ => code}/completers/snippets_completer/provider.py (100%) rename plugins/{ => code}/completers/snippets_completer/provider_response_cache.py (100%) rename plugins/{ => code}/completers/snippets_completer/snippets.cson (100%) rename plugins/{depricated/commentzar => code/completers/words_completer}/__init__.py (100%) rename plugins/{depricated/commentzar => code/completers/words_completer}/__main__.py (100%) rename plugins/{ => code}/completers/words_completer/alt_provider.py (100%) rename plugins/{ => code}/completers/words_completer/manifest.json (100%) rename plugins/{ => code}/completers/words_completer/plugin.py (83%) rename plugins/{ => code}/completers/words_completer/provider.py (89%) rename plugins/{ => code}/completers/words_completer/provider_response_cache.py (88%) rename plugins/{depricated => code}/search_replace/__init__.py (100%) rename plugins/{depricated => code}/search_replace/__main__.py (100%) create mode 100644 plugins/code/search_replace/images/only-in-selection.png create mode 100644 plugins/code/search_replace/images/whole-word.png create mode 100644 plugins/code/search_replace/manifest.json create mode 100644 plugins/code/search_replace/mixins/__init__.py create mode 100644 plugins/code/search_replace/mixins/replace_mixin.py create mode 100644 plugins/code/search_replace/mixins/search_mixin.py create mode 100644 plugins/code/search_replace/mixins/search_replace_mixin.py create mode 100644 plugins/code/search_replace/mode_buttons.py create mode 100644 plugins/code/search_replace/plugin.py create mode 100644 plugins/code/search_replace/search_replace.py delete mode 100755 plugins/depricated/commentzar/add_comment_mixin.py delete mode 100755 plugins/depricated/commentzar/codecomment_tags.py delete mode 100644 plugins/depricated/commentzar/plugin.py delete mode 100755 plugins/depricated/commentzar/remove_comment_mixin.py delete mode 100644 plugins/depricated/search_replace/manifest.json delete mode 100644 plugins/depricated/search_replace/plugin.py delete mode 100644 plugins/depricated/search_replace/replace_mixin.py delete mode 100644 plugins/depricated/search_replace/search_replace.glade delete mode 100644 plugins/depricated/search_replace/styling_mixin.py rename plugins/{ => ui}/template/__init__.py (100%) rename plugins/{ => ui}/template/__main__.py (100%) rename plugins/{ => ui}/template/manifest.json (100%) rename plugins/{ => ui}/template/plugin.py (76%) rename src/libs/dto/code/{get_command_system_event.py => get_new_command_system_event.py} (77%) create mode 100644 src/libs/dto/code/register_command_event.py diff --git a/plugins/completers/example_completer/__init__.py b/plugins/code/commentzar/__init__.py similarity index 100% rename from plugins/completers/example_completer/__init__.py rename to plugins/code/commentzar/__init__.py diff --git a/plugins/completers/example_completer/__main__.py b/plugins/code/commentzar/__main__.py similarity index 100% rename from plugins/completers/example_completer/__main__.py rename to plugins/code/commentzar/__main__.py diff --git a/plugins/code/commentzar/commenter.py b/plugins/code/commentzar/commenter.py new file mode 100644 index 0000000..3724934 --- /dev/null +++ b/plugins/code/commentzar/commenter.py @@ -0,0 +1,66 @@ +# Python imports + +# Lib imports + +# Application imports +from .mixins.code_comment_tags_mixin import CodeCommentTagsMixin + + + +class Commenter(CodeCommentTagsMixin): + def __init__(self): + ... + + + def keyboard_tggl_comment(self, buffer): + language = buffer.get_language() + if language is None: return + + start_tag, end_tag = self.get_comment_tags(language) + # Note: Only handling line comment tag- no block comment option + if not start_tag and not end_tag: return + + bounds = buffer.get_selection_bounds() + if bounds: + self._bounds_comment( + start_tag, end_tag, bounds, buffer + ) + else: + self._line_comment(start_tag, end_tag, buffer) + + + def _line_comment(self, start_tag, end_tag, buffer): + start_itr = buffer.get_iter_at_mark( buffer.get_insert() ).copy() + end_itr = start_itr.copy() + if not start_itr.starts_line(): + start_itr.set_line_offset(0) + if not end_itr.ends_line(): + end_itr.forward_to_line_end() + + text = buffer.get_text(start_itr, end_itr, True) + text = text.replace(start_tag, "") if text.startswith(start_tag) else start_tag + text + + buffer.begin_user_action() + buffer.delete(start_itr, end_itr) + buffer.insert(start_itr, text) + buffer.end_user_action() + + + def _bounds_comment(self, start_tag, end_tag, bounds, buffer): + start_itr, end_itr = bounds + if not start_itr.starts_line(): + start_itr.set_line_offset(0) + if not end_itr.ends_line(): + end_itr.forward_to_line_end() + + text = buffer.get_text(start_itr, end_itr, True) + text = "\n".join( + line.replace(start_tag, "") if line.startswith(start_tag) else start_tag + line + for line in text.splitlines() + ) + + buffer.begin_user_action() + buffer.delete(start_itr, end_itr) + buffer.insert(start_itr, text) + buffer.end_user_action() + diff --git a/plugins/depricated/commentzar/manifest.json b/plugins/code/commentzar/manifest.json similarity index 51% rename from plugins/depricated/commentzar/manifest.json rename to plugins/code/commentzar/manifest.json index 8197cc3..4100da1 100644 --- a/plugins/depricated/commentzar/manifest.json +++ b/plugins/code/commentzar/manifest.json @@ -4,8 +4,5 @@ "credit": "Hamad Al Marri", "version": "0.0.1", "support": "", - "requests": { - "pass_events": true, - "bind_keys": ["Commentzar||keyboard_tggl_comment:slash"] - } + "requests": {} } diff --git a/plugins/code/commentzar/mixins/__init__.py b/plugins/code/commentzar/mixins/__init__.py new file mode 100644 index 0000000..7987b9a --- /dev/null +++ b/plugins/code/commentzar/mixins/__init__.py @@ -0,0 +1,3 @@ +""" + Pligin Module Mixin +""" diff --git a/plugins/code/commentzar/mixins/code_comment_tags_mixin.py b/plugins/code/commentzar/mixins/code_comment_tags_mixin.py new file mode 100755 index 0000000..2f962d5 --- /dev/null +++ b/plugins/code/commentzar/mixins/code_comment_tags_mixin.py @@ -0,0 +1,30 @@ +# Python imports + +# Lib imports + +# Application imports + + + +class CodeCommentTagsMixin: + def get_comment_tags(self, language): + start_tag, end_tag = self.get_line_comment_tags(language) + if (start_tag, end_tag) == (None, None): + start_tag, end_tag = self.get_block_comment_tags(language) + + return start_tag, end_tag + + def get_block_comment_tags(self, language): + start_tag = language.get_metadata('block-comment-start') + end_tag = language.get_metadata('block-comment-end') + + if start_tag and end_tag: return (start_tag, end_tag) + + return (None, None) + + def get_line_comment_tags(self, language): + start_tag = language.get_metadata('line-comment-start') + + if start_tag: return (start_tag, None) + + return (None, None) diff --git a/plugins/code/commentzar/plugin.py b/plugins/code/commentzar/plugin.py new file mode 100644 index 0000000..e3b1597 --- /dev/null +++ b/plugins/code/commentzar/plugin.py @@ -0,0 +1,49 @@ +# Python imports + +# Lib imports +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk + +# Application imports +from libs.event_factory import Event_Factory, Code_Event_Types + +from plugins.plugin_types import PluginCode + +from .commenter import Commenter + + + +commenter = Commenter() + + + +class Plugin(PluginCode): + def __init__(self): + super(Plugin, self).__init__() + + + def _controller_message(self, event: Code_Event_Types.CodeEvent): + ... + + def load(self): + event = Event_Factory.create_event("register_command", + command_name = "keyboard_tggl_comment", + command = Handler, + binding_mode = "released", + binding = "slash" + ) + + self.message_to("source_views", event) + + def run(self): + ... + + +class Handler: + @staticmethod + def execute( + view: any + ): + logger.debug("Command: Toggle Comment") + commenter.keyboard_tggl_comment( view.get_buffer() ) \ No newline at end of file diff --git a/plugins/completers/lsp_completer/__init__.py b/plugins/code/completers/example_completer/__init__.py similarity index 100% rename from plugins/completers/lsp_completer/__init__.py rename to plugins/code/completers/example_completer/__init__.py diff --git a/plugins/completers/lsp_completer/__main__.py b/plugins/code/completers/example_completer/__main__.py similarity index 100% rename from plugins/completers/lsp_completer/__main__.py rename to plugins/code/completers/example_completer/__main__.py diff --git a/plugins/completers/example_completer/manifest.json b/plugins/code/completers/example_completer/manifest.json similarity index 100% rename from plugins/completers/example_completer/manifest.json rename to plugins/code/completers/example_completer/manifest.json diff --git a/plugins/completers/example_completer/plugin.py b/plugins/code/completers/example_completer/plugin.py similarity index 83% rename from plugins/completers/example_completer/plugin.py rename to plugins/code/completers/example_completer/plugin.py index f13331f..479fdd0 100644 --- a/plugins/completers/example_completer/plugin.py +++ b/plugins/code/completers/example_completer/plugin.py @@ -6,8 +6,7 @@ gi.require_version('Gtk', '3.0') from gi.repository import Gtk # Application imports -from libs.dto.base_event import BaseEvent -from libs.event_factory import Event_Factory +from libs.event_factory import Event_Factory, Code_Event_Types from plugins.plugin_types import PluginCode @@ -22,7 +21,7 @@ class Plugin(PluginCode): self.provider: Provider = None - def _controller_message(self, event: BaseEvent): + def _controller_message(self, event: Code_Event_Types.CodeEvent): ... def load(self): diff --git a/plugins/completers/example_completer/provider.py b/plugins/code/completers/example_completer/provider.py similarity index 89% rename from plugins/completers/example_completer/provider.py rename to plugins/code/completers/example_completer/provider.py index a7d27bb..d736210 100644 --- a/plugins/completers/example_completer/provider.py +++ b/plugins/code/completers/example_completer/provider.py @@ -30,13 +30,13 @@ class Provider(GObject.GObject, GtkSource.CompletionProvider): return 'Example Code Completion' def do_match(self, context): - # word = context.get_word() - # if not word or len(word) < 2: return False + # Note: If provider is in interactive activation then need to check + # view focus as otherwise non focus views start trying to grab it. + completion = context.get_property("completion") + if not completion.get_view().has_focus(): return - """ Get whether the provider match the context of completion detailed in context. """ word = self.response_cache.get_word(context) if not word or len(word) < 2: return False - return True def do_get_priority(self): diff --git a/plugins/completers/example_completer/provider_response_cache.py b/plugins/code/completers/example_completer/provider_response_cache.py similarity index 92% rename from plugins/completers/example_completer/provider_response_cache.py rename to plugins/code/completers/example_completer/provider_response_cache.py index 87af042..bc6d50b 100644 --- a/plugins/completers/example_completer/provider_response_cache.py +++ b/plugins/code/completers/example_completer/provider_response_cache.py @@ -1,4 +1,5 @@ # Python imports +from concurrent.futures import ThreadPoolExecutor import re # Lib imports @@ -21,6 +22,9 @@ class ProviderResponseCache(ProviderResponseCacheBase): def __init__(self): super(ProviderResponseCache, self).__init__() + # Note: Using asyncio.run causes a keyboard trap that prevents app + # closure from terminal. ThreadPoolExecutor seems to not have such issues... + self.executor = ThreadPoolExecutor(max_workers = 1) self.matchers: dict = { "hello": { "label": "Hello, World!", diff --git a/plugins/completers/python_completer/__init__.py b/plugins/code/completers/lsp_completer/__init__.py similarity index 100% rename from plugins/completers/python_completer/__init__.py rename to plugins/code/completers/lsp_completer/__init__.py diff --git a/plugins/completers/python_completer/__main__.py b/plugins/code/completers/lsp_completer/__main__.py similarity index 100% rename from plugins/completers/python_completer/__main__.py rename to plugins/code/completers/lsp_completer/__main__.py diff --git a/plugins/completers/lsp_completer/manifest.json b/plugins/code/completers/lsp_completer/manifest.json similarity index 100% rename from plugins/completers/lsp_completer/manifest.json rename to plugins/code/completers/lsp_completer/manifest.json diff --git a/plugins/completers/lsp_completer/plugin.py b/plugins/code/completers/lsp_completer/plugin.py similarity index 84% rename from plugins/completers/lsp_completer/plugin.py rename to plugins/code/completers/lsp_completer/plugin.py index 7de452e..b37a718 100644 --- a/plugins/completers/lsp_completer/plugin.py +++ b/plugins/code/completers/lsp_completer/plugin.py @@ -6,8 +6,7 @@ gi.require_version('Gtk', '3.0') from gi.repository import Gtk # Application imports -from libs.dto.base_event import BaseEvent -from libs.event_factory import Event_Factory +from libs.event_factory import Event_Factory, Code_Event_Types from plugins.plugin_types import PluginCode @@ -22,7 +21,7 @@ class Plugin(PluginCode): self.provider: Provider = None - def _controller_message(self, event: BaseEvent): + def _controller_message(self, event: Code_Event_Types.CodeEvent): ... def load(self): diff --git a/plugins/completers/lsp_completer/provider.py b/plugins/code/completers/lsp_completer/provider.py similarity index 100% rename from plugins/completers/lsp_completer/provider.py rename to plugins/code/completers/lsp_completer/provider.py diff --git a/plugins/completers/lsp_completer/provider_response_cache.py b/plugins/code/completers/lsp_completer/provider_response_cache.py similarity index 75% rename from plugins/completers/lsp_completer/provider_response_cache.py rename to plugins/code/completers/lsp_completer/provider_response_cache.py index b1bf2d2..58288d1 100644 --- a/plugins/completers/lsp_completer/provider_response_cache.py +++ b/plugins/code/completers/lsp_completer/provider_response_cache.py @@ -1,4 +1,5 @@ # Python imports +from concurrent.futures import ThreadPoolExecutor # Lib imports import gi @@ -17,9 +18,13 @@ class ProviderResponseCache(ProviderResponseCacheBase): def __init__(self): super(ProviderResponseCache, self).__init__() + self.executor = ThreadPoolExecutor(max_workers = 1) + self.matchers: dict = {} + def process_file_load(self, event: Code_Event_Types.AddedNewFileEvent): - ... + buffer = event.file.buffer + self.executor.submit(self._handle_change, buffer) def process_file_close(self, event: Code_Event_Types.RemovedFileEvent): ... @@ -28,8 +33,13 @@ class ProviderResponseCache(ProviderResponseCacheBase): ... def process_file_change(self, event: Code_Event_Types.TextChangedEvent): + buffer = event.file.buffer + self.executor.submit(self._handle_change, buffer) + + def _handle_change(self, buffer): ... + def filter(self, word: str) -> list[dict]: return [] diff --git a/plugins/completers/snippets_completer/__init__.py b/plugins/code/completers/python_completer/__init__.py similarity index 100% rename from plugins/completers/snippets_completer/__init__.py rename to plugins/code/completers/python_completer/__init__.py diff --git a/plugins/completers/snippets_completer/__main__.py b/plugins/code/completers/python_completer/__main__.py similarity index 100% rename from plugins/completers/snippets_completer/__main__.py rename to plugins/code/completers/python_completer/__main__.py diff --git a/plugins/completers/python_completer/manifest.json b/plugins/code/completers/python_completer/manifest.json similarity index 100% rename from plugins/completers/python_completer/manifest.json rename to plugins/code/completers/python_completer/manifest.json diff --git a/plugins/completers/python_completer/plugin.py b/plugins/code/completers/python_completer/plugin.py similarity index 83% rename from plugins/completers/python_completer/plugin.py rename to plugins/code/completers/python_completer/plugin.py index 1d8f81d..5be143b 100644 --- a/plugins/completers/python_completer/plugin.py +++ b/plugins/code/completers/python_completer/plugin.py @@ -6,8 +6,7 @@ gi.require_version('Gtk', '3.0') from gi.repository import Gtk # Application imports -from libs.dto.base_event import BaseEvent -from libs.event_factory import Event_Factory +from libs.event_factory import Event_Factory, Code_Event_Types from plugins.plugin_types import PluginCode @@ -22,7 +21,7 @@ class Plugin(PluginCode): self.provider: Provider = None - def _controller_message(self, event: BaseEvent): + def _controller_message(self, event: Code_Event_Types.CodeEvent): ... def load(self): diff --git a/plugins/completers/python_completer/provider.py b/plugins/code/completers/python_completer/provider.py similarity index 100% rename from plugins/completers/python_completer/provider.py rename to plugins/code/completers/python_completer/provider.py diff --git a/plugins/completers/python_completer/provider_response_cache.py b/plugins/code/completers/python_completer/provider_response_cache.py similarity index 100% rename from plugins/completers/python_completer/provider_response_cache.py rename to plugins/code/completers/python_completer/provider_response_cache.py diff --git a/plugins/completers/words_completer/__init__.py b/plugins/code/completers/snippets_completer/__init__.py similarity index 100% rename from plugins/completers/words_completer/__init__.py rename to plugins/code/completers/snippets_completer/__init__.py diff --git a/plugins/completers/words_completer/__main__.py b/plugins/code/completers/snippets_completer/__main__.py similarity index 100% rename from plugins/completers/words_completer/__main__.py rename to plugins/code/completers/snippets_completer/__main__.py diff --git a/plugins/completers/snippets_completer/cson/__init__.py b/plugins/code/completers/snippets_completer/cson/__init__.py similarity index 100% rename from plugins/completers/snippets_completer/cson/__init__.py rename to plugins/code/completers/snippets_completer/cson/__init__.py diff --git a/plugins/completers/snippets_completer/cson/parser.py b/plugins/code/completers/snippets_completer/cson/parser.py similarity index 100% rename from plugins/completers/snippets_completer/cson/parser.py rename to plugins/code/completers/snippets_completer/cson/parser.py diff --git a/plugins/completers/snippets_completer/cson/speg/__init__.py b/plugins/code/completers/snippets_completer/cson/speg/__init__.py similarity index 100% rename from plugins/completers/snippets_completer/cson/speg/__init__.py rename to plugins/code/completers/snippets_completer/cson/speg/__init__.py diff --git a/plugins/completers/snippets_completer/cson/speg/peg.py b/plugins/code/completers/snippets_completer/cson/speg/peg.py similarity index 100% rename from plugins/completers/snippets_completer/cson/speg/peg.py rename to plugins/code/completers/snippets_completer/cson/speg/peg.py diff --git a/plugins/completers/snippets_completer/cson/writer.py b/plugins/code/completers/snippets_completer/cson/writer.py similarity index 100% rename from plugins/completers/snippets_completer/cson/writer.py rename to plugins/code/completers/snippets_completer/cson/writer.py diff --git a/plugins/completers/snippets_completer/manifest.json b/plugins/code/completers/snippets_completer/manifest.json similarity index 100% rename from plugins/completers/snippets_completer/manifest.json rename to plugins/code/completers/snippets_completer/manifest.json diff --git a/plugins/completers/snippets_completer/plugin.py b/plugins/code/completers/snippets_completer/plugin.py similarity index 83% rename from plugins/completers/snippets_completer/plugin.py rename to plugins/code/completers/snippets_completer/plugin.py index 100c641..45f7f17 100644 --- a/plugins/completers/snippets_completer/plugin.py +++ b/plugins/code/completers/snippets_completer/plugin.py @@ -6,8 +6,7 @@ gi.require_version('Gtk', '3.0') from gi.repository import Gtk # Application imports -from libs.dto.base_event import BaseEvent -from libs.event_factory import Event_Factory +from libs.event_factory import Event_Factory, Code_Event_Types from plugins.plugin_types import PluginCode @@ -22,7 +21,7 @@ class Plugin(PluginCode): self.provider: Provider = None - def _controller_message(self, event: BaseEvent): + def _controller_message(self, event: Code_Event_Types.CodeEvent): ... def load(self): diff --git a/plugins/completers/snippets_completer/provider.py b/plugins/code/completers/snippets_completer/provider.py similarity index 100% rename from plugins/completers/snippets_completer/provider.py rename to plugins/code/completers/snippets_completer/provider.py diff --git a/plugins/completers/snippets_completer/provider_response_cache.py b/plugins/code/completers/snippets_completer/provider_response_cache.py similarity index 100% rename from plugins/completers/snippets_completer/provider_response_cache.py rename to plugins/code/completers/snippets_completer/provider_response_cache.py diff --git a/plugins/completers/snippets_completer/snippets.cson b/plugins/code/completers/snippets_completer/snippets.cson similarity index 100% rename from plugins/completers/snippets_completer/snippets.cson rename to plugins/code/completers/snippets_completer/snippets.cson diff --git a/plugins/depricated/commentzar/__init__.py b/plugins/code/completers/words_completer/__init__.py similarity index 100% rename from plugins/depricated/commentzar/__init__.py rename to plugins/code/completers/words_completer/__init__.py diff --git a/plugins/depricated/commentzar/__main__.py b/plugins/code/completers/words_completer/__main__.py similarity index 100% rename from plugins/depricated/commentzar/__main__.py rename to plugins/code/completers/words_completer/__main__.py diff --git a/plugins/completers/words_completer/alt_provider.py b/plugins/code/completers/words_completer/alt_provider.py similarity index 100% rename from plugins/completers/words_completer/alt_provider.py rename to plugins/code/completers/words_completer/alt_provider.py diff --git a/plugins/completers/words_completer/manifest.json b/plugins/code/completers/words_completer/manifest.json similarity index 100% rename from plugins/completers/words_completer/manifest.json rename to plugins/code/completers/words_completer/manifest.json diff --git a/plugins/completers/words_completer/plugin.py b/plugins/code/completers/words_completer/plugin.py similarity index 83% rename from plugins/completers/words_completer/plugin.py rename to plugins/code/completers/words_completer/plugin.py index abb4acf..937cb00 100644 --- a/plugins/completers/words_completer/plugin.py +++ b/plugins/code/completers/words_completer/plugin.py @@ -6,8 +6,7 @@ gi.require_version('Gtk', '3.0') from gi.repository import Gtk # Application imports -from libs.dto.base_event import BaseEvent -from libs.event_factory import Event_Factory +from libs.event_factory import Event_Factory, Code_Event_Types from plugins.plugin_types import PluginCode @@ -22,7 +21,7 @@ class Plugin(PluginCode): self.provider: Provider = None - def _controller_message(self, event: BaseEvent): + def _controller_message(self, event: Code_Event_Types.CodeEvent): ... def load(self): diff --git a/plugins/completers/words_completer/provider.py b/plugins/code/completers/words_completer/provider.py similarity index 89% rename from plugins/completers/words_completer/provider.py rename to plugins/code/completers/words_completer/provider.py index b0d6bbc..845acc8 100644 --- a/plugins/completers/words_completer/provider.py +++ b/plugins/code/completers/words_completer/provider.py @@ -30,6 +30,11 @@ class Provider(GObject.GObject, GtkSource.CompletionProvider): return 'Words Completion' def do_match(self, context): + # Note: If provider is in interactive activation then need to check + # view focus as otherwise non focus views start trying to grab it. + completion = context.get_property("completion") + if not completion.get_view().has_focus(): return + word = self.response_cache.get_word(context) if not word or len(word) < 2: return False return True diff --git a/plugins/completers/words_completer/provider_response_cache.py b/plugins/code/completers/words_completer/provider_response_cache.py similarity index 88% rename from plugins/completers/words_completer/provider_response_cache.py rename to plugins/code/completers/words_completer/provider_response_cache.py index 00a20f6..5a55313 100644 --- a/plugins/completers/words_completer/provider_response_cache.py +++ b/plugins/code/completers/words_completer/provider_response_cache.py @@ -1,5 +1,5 @@ # Python imports -import asyncio +from concurrent.futures import ThreadPoolExecutor # Lib imports import gi @@ -24,7 +24,8 @@ class ProviderResponseCache(ProviderResponseCacheBase): def process_file_load(self, event: Code_Event_Types.AddedNewFileEvent): buffer = event.file.buffer - asyncio.run( self._handle_change(buffer) ) + with ThreadPoolExecutor(max_workers = 1) as executor: + executor.submit(self._handle_change, buffer) def process_file_close(self, event: Code_Event_Types.RemovedFileEvent): self.matchers[event.file.buffer] = set() @@ -35,13 +36,14 @@ class ProviderResponseCache(ProviderResponseCacheBase): def process_file_change(self, event: Code_Event_Types.TextChangedEvent): buffer = event.file.buffer - asyncio.run( self._handle_change(buffer) ) + with ThreadPoolExecutor(max_workers = 1) as executor: + executor.submit(self._handle_change, buffer) - async def _handle_change(self, buffer): + def _handle_change(self, buffer): start_itr = buffer.get_start_iter() end_itr = buffer.get_end_iter() data = buffer.get_text(start_itr, end_itr, False) - + if not data: GLib.idle_add(self.load_empty_set, buffer) return @@ -67,6 +69,9 @@ class ProviderResponseCache(ProviderResponseCacheBase): buffer = self.get_iter_correctly(context).get_buffer() word = self.get_word(context).rstrip() + if not buffer in self.matchers: + self.matchers[buffer] = set() + response: list[dict] = [] for entry in self.matchers[buffer]: if not entry.rstrip().startswith(word): continue @@ -81,7 +86,6 @@ class ProviderResponseCache(ProviderResponseCacheBase): return response - def load_empty_set(self, buffer): self.matchers[buffer] = set() diff --git a/plugins/depricated/search_replace/__init__.py b/plugins/code/search_replace/__init__.py similarity index 100% rename from plugins/depricated/search_replace/__init__.py rename to plugins/code/search_replace/__init__.py diff --git a/plugins/depricated/search_replace/__main__.py b/plugins/code/search_replace/__main__.py similarity index 100% rename from plugins/depricated/search_replace/__main__.py rename to plugins/code/search_replace/__main__.py diff --git a/plugins/code/search_replace/images/only-in-selection.png b/plugins/code/search_replace/images/only-in-selection.png new file mode 100644 index 0000000000000000000000000000000000000000..3c35fc3f6dbf8fdc5b59df53656d530d5ac1168c GIT binary patch literal 6270 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 KO_6or=6?Yu9o_N( literal 0 HcmV?d00001 diff --git a/plugins/code/search_replace/images/whole-word.png b/plugins/code/search_replace/images/whole-word.png new file mode 100644 index 0000000000000000000000000000000000000000..d147682c5511c630f529540bda883593998d8262 GIT binary patch literal 6651 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"] - - } -} diff --git a/plugins/depricated/search_replace/plugin.py b/plugins/depricated/search_replace/plugin.py deleted file mode 100644 index b387f07..0000000 --- a/plugins/depricated/search_replace/plugin.py +++ /dev/null @@ -1,221 +0,0 @@ -# Python imports -import os -import re -import threading - -# Lib imports -import gi -gi.require_version('Gtk', '3.0') -gi.require_version('Gdk', '3.0') -from gi.repository import Gtk -from gi.repository import Gdk -from gi.repository import GLib - -# Application imports -from plugins.plugin_base import PluginBase -from .styling_mixin import StylingMixin -from .replace_mixin import ReplaceMixin - - - -class Plugin(StylingMixin, ReplaceMixin, PluginBase): - def __init__(self): - super().__init__() - - self.name = "Search/Replace" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus - # where self.name should not be needed for message comms - self.path = os.path.dirname(os.path.realpath(__file__)) - self._GLADE_FILE = f"{self.path}/search_replace.glade" - - self._search_replace_dialog = None - self._find_entry = None - self._replace_entry = None - self._active_src_view = None - self._buffer = None - self._tag_table = None - - self.use_regex = False - self.use_case_sensitive = False - self.search_only_in_selection = False - self.use_whole_word_search = False - - self.timer = None - self.search_time = 0.35 - self.find_text = "" - self.search_tag = "search_tag" - self.highlight_color = "#FBF719" - self.text_color = "#000000" - self.alpha_num_under = re.compile(r"[a-zA-Z0-9_]") - - - def run(self): - self._builder = Gtk.Builder() - self._builder.add_from_file(self._GLADE_FILE) - self._connect_builder_signals(self, self._builder) - - separator_botton = self._ui_objects[0] - self._search_replace_dialog = self._builder.get_object("search_replace_dialog") - self._find_status_lbl = self._builder.get_object("find_status_lbl") - self._find_options_lbl = self._builder.get_object("find_options_lbl") - - self._find_entry = self._builder.get_object("find_entry") - self._replace_entry = self._builder.get_object("replace_entry") - - self._search_replace_dialog.set_relative_to(separator_botton) - self._search_replace_dialog.set_hexpand(True) - - def generate_reference_ui_element(self): - ... - - 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) - - 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() - - - 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 - - - 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 on_enter_search(self, widget, eve): - text = widget.get_text() - if not text: return - - keyname = Gdk.keyval_name(eve.keyval) - if keyname == "Return": - self.find_next(widget) - - def search_for_string(self, widget): - 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() - # Also clears tag from buffer so if no query we're clean in ui - search_tag = self.get_search_tag(buffer) - - self.update_style(1) - if not query: - self._find_status_lbl.set_label(f"Find in current buffer") - self.update_style(0) - return - - 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 search(self, start_itr = None, query = None, limit = 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: - flags = flags | Gtk.TextSearchFlags.CASE_INSENSITIVE - - if self.search_only_in_selection and self._buffer.get_has_selection(): - start_itr, limit = self._buffer.get_selection_bounds() - - _results = [] - while True: - result = start_itr.forward_search(query, flags, limit) - if not result: break - - _results.append(result) - start_itr = result[1] - - 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() - - 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): - ... \ No newline at end of file diff --git a/plugins/depricated/search_replace/replace_mixin.py b/plugins/depricated/search_replace/replace_mixin.py deleted file mode 100644 index 9d5a2f0..0000000 --- a/plugins/depricated/search_replace/replace_mixin.py +++ /dev/null @@ -1,94 +0,0 @@ -# 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(search_tag) - self._do_replace(iter, replace_text) - self._active_src_view.scroll_to_iter( iter, 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: - 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 diff --git a/plugins/depricated/search_replace/search_replace.glade b/plugins/depricated/search_replace/search_replace.glade deleted file mode 100644 index ccab6c8..0000000 --- a/plugins/depricated/search_replace/search_replace.glade +++ /dev/null @@ -1,299 +0,0 @@ - - - - - - True - False - gtk-close - - - True - False - ../../icons/only-in-selection.png - - - True - False - ../../icons/whole-word.png - - - False - False - False - none - - - True - False - vertical - - - True - False - - - True - False - 5 - Find in Current Buffer - 0 - - - True - True - 0 - - - - - True - False - - - True - False - 20 - Finding with Options: Case Insensitive - 0 - - - False - True - 0 - - - - - True - False - start - - - .* - True - False - True - False - True - Use Regex - - - - True - True - 0 - - - - - Aa - True - True - False - True - Match Case - - - - True - True - 1 - - - - - True - True - False - True - Only In Selection - only-in-selection - True - - - - True - True - 2 - - - - - True - True - False - True - Whole Word - whole-word - True - - - - True - True - 3 - - - - - True - True - False - True - Close Panel - close_img - True - - - - True - True - 4 - - - - - False - True - 1 - - - - - False - True - 1 - - - - - False - True - 0 - - - - - - True - False - True - - - Replace All - True - True - False - True - Replace All - 5 - 5 - 5 - 5 - - - - 9 - 1 - - - - - Replace - True - True - False - True - Replace Next - 5 - 10 - 5 - 5 - - - - 8 - 1 - - - - - Find All - True - True - False - True - 5 - 5 - 5 - 5 - - - - 9 - 0 - - - - - Find - True - True - False - True - 5 - 5 - 5 - 5 - - - - 8 - 0 - - - - - True - True - edit-find-symbolic - False - False - Find in current buffer - - - - - 0 - 0 - 8 - - - - - True - True - edit-find-symbolic - False - False - Replace in current buffer - - - 0 - 1 - 8 - - - - - False - True - 10 - 3 - - - - - - diff --git a/plugins/depricated/search_replace/styling_mixin.py b/plugins/depricated/search_replace/styling_mixin.py deleted file mode 100644 index 3336bec..0000000 --- a/plugins/depricated/search_replace/styling_mixin.py +++ /dev/null @@ -1,66 +0,0 @@ -# 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} result{plural} found for '{query}'") diff --git a/plugins/template/__init__.py b/plugins/ui/template/__init__.py similarity index 100% rename from plugins/template/__init__.py rename to plugins/ui/template/__init__.py diff --git a/plugins/template/__main__.py b/plugins/ui/template/__main__.py similarity index 100% rename from plugins/template/__main__.py rename to plugins/ui/template/__main__.py diff --git a/plugins/template/manifest.json b/plugins/ui/template/manifest.json similarity index 100% rename from plugins/template/manifest.json rename to plugins/ui/template/manifest.json diff --git a/plugins/template/plugin.py b/plugins/ui/template/plugin.py similarity index 76% rename from plugins/template/plugin.py rename to plugins/ui/template/plugin.py index 6fb6694..fd843eb 100644 --- a/plugins/template/plugin.py +++ b/plugins/ui/template/plugin.py @@ -21,14 +21,14 @@ class Plugin(PluginUI): ... def load(self): - ui_element = self.requests_ui_element("plugin_control_list") + ui_element = self.requests_ui_element("header-container") ui_element.add( self.generate_plugin_element() ) def run(self): ... def generate_plugin_element(self): - button = Gtk.Button(label = self.name) + button = Gtk.Button(label = "Hello, World!") button.connect("button-release-event", self.send_message) button.show() @@ -36,6 +36,5 @@ class Plugin(PluginUI): return button def send_message(self, widget = None, eve = None): - message = "Hello, World!" - self.emit("display_message", ("warning", message, None)) + logger.info("Hello, World!") \ No newline at end of file diff --git a/src/__builtins__.py b/src/__builtins__.py index 5359fe8..c43ebec 100644 --- a/src/__builtins__.py +++ b/src/__builtins__.py @@ -68,6 +68,7 @@ builtins.call_chain = call_chain_wrapper # def custom_except_hook(exc_type, exc_value, exc_traceback): # if issubclass(exc_type, KeyboardInterrupt): # sys.__excepthook__(exc_type, exc_value, exc_traceback) +# sys.__excepthook__(exc_type, exc_value, exc_traceback) # return # logger.error("Uncaught exception", exc_info = (exc_type, exc_value, exc_traceback)) diff --git a/src/core/containers/footer_container.py b/src/core/containers/footer_container.py index 9d7d0fa..4dcdd71 100644 --- a/src/core/containers/footer_container.py +++ b/src/core/containers/footer_container.py @@ -27,7 +27,7 @@ class FooterContainer(Gtk.Box): self.ctx = self.get_style_context() self.ctx.add_class("footer-container") - self.set_orientation(Gtk.Orientation.HORIZONTAL) + self.set_orientation(Gtk.Orientation.VERTICAL) self.set_hexpand(True) def _setup_signals(self): diff --git a/src/core/controllers/base_controller.py b/src/core/controllers/base_controller.py index 92adf74..523b53d 100644 --- a/src/core/controllers/base_controller.py +++ b/src/core/controllers/base_controller.py @@ -12,6 +12,7 @@ from libs.mixins.ipc_signals_mixin import IPCSignalsMixin from libs.mixins.keyboard_signals_mixin import KeyboardSignalsMixin from ..containers.base_container import BaseContainer +from ..containers.code.code_container import CodeContainer from .base_controller_mixin import BaseControllerMixin from .bridge_controller import BridgeController diff --git a/src/core/widgets/code/command_system/command_system.py b/src/core/widgets/code/command_system/command_system.py index 48af7ed..0cbfbd0 100644 --- a/src/core/widgets/code/command_system/command_system.py +++ b/src/core/widgets/code/command_system/command_system.py @@ -37,6 +37,9 @@ class CommandSystem: method = getattr(commands, command) return method.execute(*args) + def add_command(self, command_name: str, command: callable): + setattr(commands, command_name, command) + def emit(self, event: Code_Event_Types.CodeEvent): """ Monkey patch 'emit' from command controller... """ diff --git a/src/core/widgets/code/command_system/commands/__init__.py b/src/core/widgets/code/command_system/commands/__init__.py index d249eb4..54539e2 100644 --- a/src/core/widgets/code/command_system/commands/__init__.py +++ b/src/core/widgets/code/command_system/commands/__init__.py @@ -9,7 +9,7 @@ __all__ = [] for loader, module_name, is_pkg in pkgutil.walk_packages(__path__): module = importlib.import_module(f"{__name__}.{module_name}") - globals()[module_name] = module # Add module to package namespace + # globals()[module_name] = module # Add module to package namespace __all__.append(module_name) del pkgutil diff --git a/src/core/widgets/code/command_system/commands/dnd_load_file_to_buffer.py b/src/core/widgets/code/command_system/commands/dnd_load_file_to_buffer.py index 713f7a3..653cc40 100644 --- a/src/core/widgets/code/command_system/commands/dnd_load_file_to_buffer.py +++ b/src/core/widgets/code/command_system/commands/dnd_load_file_to_buffer.py @@ -18,12 +18,7 @@ def execute( uri: str ): logger.debug("Command: DnD Load File To Buffer") - - file = view.command.get_file(view) - buffer = file.buffer - - if not file.ftype == "buffer": - file = view.command.new_file(view) + file = view.command.new_file(view) gfile = Gio.File.new_for_uri(uri) view.command.exec_with_args( @@ -31,4 +26,5 @@ def execute( (view, gfile, file) ) + view.set_buffer(file.buffer) update_info_bar_if_focused(view.command, view) diff --git a/src/core/widgets/code/controllers/commands_controller.py b/src/core/widgets/code/controllers/commands_controller.py index e1aec04..532bb07 100644 --- a/src/core/widgets/code/controllers/commands_controller.py +++ b/src/core/widgets/code/controllers/commands_controller.py @@ -17,10 +17,10 @@ class CommandsController(ControllerBase, list): def _controller_message(self, event: Code_Event_Types.CodeEvent): - if isinstance(event, Code_Event_Types.GetCommandSystemEvent): - event.response = self.get_command_system() + if isinstance(event, Code_Event_Types.GetNewCommandSystemEvent): + event.response = self.get_new_command_system() - def get_command_system(self): + def get_new_command_system(self): command_system = CommandSystem() command_system.emit = self.emit command_system.emit_to = self.emit_to diff --git a/src/core/widgets/code/controllers/views/source_views_controller.py b/src/core/widgets/code/controllers/views/source_views_controller.py index f5c7e60..e183daa 100644 --- a/src/core/widgets/code/controllers/views/source_views_controller.py +++ b/src/core/widgets/code/controllers/views/source_views_controller.py @@ -27,6 +27,8 @@ class SourceViewsController(ControllerBase, list): def _controller_message(self, event: Code_Event_Types.CodeEvent): if isinstance(event, Code_Event_Types.RemovedFileEvent): self._remove_file(event) + elif isinstance(event, Code_Event_Types.RegisterCommandEvent): + self. _register_command(event) if not self.signal_mapper.active_view: return @@ -40,8 +42,22 @@ class SourceViewsController(ControllerBase, list): elif isinstance(event, Code_Event_Types.TextInsertedEvent): self.signal_mapper.insert_text(event.file, event.text) + def _register_command(self, event: Code_Event_Types.RegisterCommandEvent): + self.state_manager.key_mapper.map_command( + event.command_name, + { + f"{event.binding_mode}": event.binding + } + ) + + for view in self: + view.command.add_command( + event.command_name, + event.command + ) + def _get_command_system(self): - event = Event_Factory.create_event("get_command_system") + event = Event_Factory.create_event("get_new_command_system") self.message_to("commands", event) command = event.response diff --git a/src/core/widgets/code/controllers/views/state_manager.py b/src/core/widgets/code/controllers/views/state_manager.py index 8bae1a1..4aa3201 100644 --- a/src/core/widgets/code/controllers/views/state_manager.py +++ b/src/core/widgets/code/controllers/views/state_manager.py @@ -10,6 +10,7 @@ from ...key_mapper import KeyMapper from .states import * + class SourceViewStateManager: def __init__(self): self.key_mapper: KeyMapper = KeyMapper() diff --git a/src/core/widgets/code/key_mapper.py b/src/core/widgets/code/key_mapper.py index 9193401..862bea7 100644 --- a/src/core/widgets/code/key_mapper.py +++ b/src/core/widgets/code/key_mapper.py @@ -70,29 +70,31 @@ class KeyMapper: with open(bindings_file, 'r') as f: data = json.load(f)["keybindings"] - for command in data: - press_state = "held" if "held" in data[command] else "released" - keyname = data[command][press_state] - - state = NoKeyState - if "" in keyname: - state = state | CtrlKeyState - if "" in keyname: - state = state | ShiftKeyState - if "" in keyname: - state = state | AltKeyState - - keyname = keyname.replace("", "") \ - .replace("", "") \ - .replace("", "") \ - .lower() - - getattr(self.states[state], press_state)[keyname] = command + self.map_command( command, data[command] ) def re_map(self): self.states = copy.deepcopy(self._map) + def map_command(self, command, entry): + press_state = "held" if "held" in entry else "released" + keyname = entry[press_state] + + state = NoKeyState + if "" in keyname: + state = state | CtrlKeyState + if "" in keyname: + state = state | ShiftKeyState + if "" in keyname: + state = state | AltKeyState + + keyname = keyname.replace("", "") \ + .replace("", "") \ + .replace("", "") \ + .lower() + + getattr(self.states[state], press_state)[keyname] = command + def _key_press_event(self, eve): keyname = Gdk.keyval_name(eve.keyval).lower() diff --git a/src/core/widgets/code/source_buffer.py b/src/core/widgets/code/source_buffer.py index 8751128..da8cfbb 100644 --- a/src/core/widgets/code/source_buffer.py +++ b/src/core/widgets/code/source_buffer.py @@ -13,9 +13,14 @@ class SourceBuffer(GtkSource.Buffer): def __init__(self): super(SourceBuffer, self).__init__() + self._handler_ids = [] self.is_processing_completion: bool = False - self._handler_ids = [] + self.create_tag( + "search-highlight", + background = "yellow", + foreground = "black" + ) def set_signals( diff --git a/src/core/widgets/code/source_file.py b/src/core/widgets/code/source_file.py index 43288af..216b33f 100644 --- a/src/core/widgets/code/source_file.py +++ b/src/core/widgets/code/source_file.py @@ -43,10 +43,26 @@ class SourceFile(GtkSource.File): ) def _changed(self, buffer: SourceBuffer): + self.check_file_on_disk() + event = Event_Factory.create_event("text_changed", buffer = buffer) event.file = self self.emit(event) + if self.is_deleted(): + print("deleted") + # event = Event_Factory.create_event("file_deleted", buffer = buffer) + # event.file = self + # self.emit(event) + return + + if self.is_externally_modified(): + print("is_externally_modified") + # event = Event_Factory.create_event("file_externally_modified", buffer = buffer) + # event.file = self + # self.emit(event) + return + def _insert_text( self, buffer: SourceBuffer, diff --git a/src/core/widgets/code/source_view.py b/src/core/widgets/code/source_view.py index bbb752d..1a94a71 100644 --- a/src/core/widgets/code/source_view.py +++ b/src/core/widgets/code/source_view.py @@ -59,6 +59,7 @@ class SourceView(GtkSource.View, SourceViewDnDMixin): def _setup_signals(self): self.connect("drag-data-received", self._on_drag_data_received) + self.connect("populate-popup", self._on_populate_popup) def _subscribe_to_events(self): ... @@ -76,6 +77,37 @@ class SourceView(GtkSource.View, SourceViewDnDMixin): self._set_up_dnd() + def _on_populate_popup(self, view, menu): + buffer = self.get_buffer() + language = buffer.get_language() + + if language.get_id() == "json": + self._load_pretify_json(view, menu) + + menu.show_all() + + def _load_prettify_json(self, view, menu): + menu.append( Gtk.SeparatorMenuItem() ) + + def on_prettify_json(menuitem): + import json + + buffer = self.get_buffer() + start_itr, \ + end_itr = buffer.get_start_iter(), buffer.get_end_iter() + data = buffer.get_text(start_itr, end_itr, False) + text = json.dumps(json.loads(data), separators = (',', ':'), indent = 4) + + buffer.begin_user_action() + buffer.delete(start_itr, end_itr) + buffer.insert(start_itr, text) + buffer.end_user_action() + + item = Gtk.MenuItem(label = "Prettify JSON") + item.connect("activate", on_prettify_json) + menu.append(item) + + def clear_temp_cut_buffer_delayed(self): if self._cut_temp_timeout_id: GLib.source_remove(self._cut_temp_timeout_id) diff --git a/src/core/widgets/vte_widget.py b/src/core/widgets/vte_widget.py index 0325fa7..3e931d4 100644 --- a/src/core/widgets/vte_widget.py +++ b/src/core/widgets/vte_widget.py @@ -45,6 +45,7 @@ class VteWidget(Vte.Terminal): ctx.add_class("vte-widget") self.set_clear_background(False) + self.set_hexpand(True) self.set_enable_sixel(True) self.set_cursor_shape( Vte.CursorShape.IBEAM ) diff --git a/src/libs/dto/code/__init__.py b/src/libs/dto/code/__init__.py index b814883..aff9d7d 100644 --- a/src/libs/dto/code/__init__.py +++ b/src/libs/dto/code/__init__.py @@ -5,8 +5,9 @@ from .code_event import CodeEvent from .register_provider_event import RegisterProviderEvent +from .register_command_event import RegisterCommandEvent -from .get_command_system_event import GetCommandSystemEvent +from .get_new_command_system_event import GetNewCommandSystemEvent from .request_completion_event import RequestCompletionEvent from .cursor_moved_event import CursorMovedEvent from .modified_changed_event import ModifiedChangedEvent diff --git a/src/libs/dto/code/get_command_system_event.py b/src/libs/dto/code/get_new_command_system_event.py similarity index 77% rename from src/libs/dto/code/get_command_system_event.py rename to src/libs/dto/code/get_new_command_system_event.py index ae6b60e..f3831c7 100644 --- a/src/libs/dto/code/get_command_system_event.py +++ b/src/libs/dto/code/get_new_command_system_event.py @@ -9,5 +9,5 @@ from .code_event import CodeEvent @dataclass -class GetCommandSystemEvent(CodeEvent): +class GetNewCommandSystemEvent(CodeEvent): ... diff --git a/src/libs/dto/code/register_command_event.py b/src/libs/dto/code/register_command_event.py new file mode 100644 index 0000000..d4441fe --- /dev/null +++ b/src/libs/dto/code/register_command_event.py @@ -0,0 +1,20 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports +import gi +gi.require_version('GtkSource', '4') + +from gi.repository import GtkSource + +# Application imports +from ..base_event import BaseEvent + + + +@dataclass +class RegisterCommandEvent(BaseEvent): + command_name: str = "" + command: callable = None + binding_mode: str = "" + binding: str = "" diff --git a/src/libs/event_factory.py b/src/libs/event_factory.py index 7354eb4..699121d 100644 --- a/src/libs/event_factory.py +++ b/src/libs/event_factory.py @@ -15,11 +15,11 @@ from .dto import code class EventFactory(Singleton): def __init__(self): + self._event_classes: Dict[str, Type[BaseEvent]] = {} self._auto_register_events( code.__dict__.items() ) - def register_event(self, event_type: str, event_class: Type[BaseEvent]): self._event_classes[event_type] = event_class diff --git a/src/plugins/plugin_types/plugin_code.py b/src/plugins/plugin_types/plugin_code.py index 37438c1..76bd503 100644 --- a/src/plugins/plugin_types/plugin_code.py +++ b/src/plugins/plugin_types/plugin_code.py @@ -31,6 +31,9 @@ class PluginCode(PluginBase): def run(self): raise PluginCodeException("Plugin Code 'run' must be overriden by Plugin") + def requests_ui_element(self, element_id: str): + return self.plugin_context.requests_ui_element(element_id) + def message(self, event: BaseEvent): return self.plugin_context.message(event) diff --git a/src/plugins/plugins_controller_mixin.py b/src/plugins/plugins_controller_mixin.py index 3583ee3..565d04f 100644 --- a/src/plugins/plugins_controller_mixin.py +++ b/src/plugins/plugins_controller_mixin.py @@ -14,10 +14,7 @@ class InvalidPluginException(Exception): class PluginsControllerMixin: def requests_ui_element(self, target_id: str): - builder = settings_manager.get_builder() - ui_target = builder.get_object(target_id) + if not target_id in widget_registery.objects: + raise InvalidPluginException('Unknown UI "target_id" given in requests.') - if not ui_target: - raise InvalidPluginException('Unknown "target_id" given in requests.') - - return ui_target + return widget_registery.objects[target_id]