diff --git a/plugins/completers/example_completer/__init__.py b/plugins/code/completers/example_completer/__init__.py similarity index 100% rename from plugins/completers/example_completer/__init__.py rename to plugins/code/completers/example_completer/__init__.py diff --git a/plugins/completers/example_completer/__main__.py b/plugins/code/completers/example_completer/__main__.py similarity index 100% rename from plugins/completers/example_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/lsp_completer/__init__.py b/plugins/code/completers/lsp_completer/__init__.py similarity index 100% rename from plugins/completers/lsp_completer/__init__.py rename to plugins/code/completers/lsp_completer/__init__.py diff --git a/plugins/completers/lsp_completer/__main__.py b/plugins/code/completers/lsp_completer/__main__.py similarity index 100% rename from plugins/completers/lsp_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/snippets_completer/__init__.py similarity index 100% rename from plugins/completers/snippets_completer/__init__.py rename to plugins/code/completers/snippets_completer/__init__.py diff --git a/plugins/completers/snippets_completer/__main__.py b/plugins/code/completers/snippets_completer/__main__.py similarity index 100% rename from plugins/completers/snippets_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/completers/words_completer/__init__.py b/plugins/code/completers/words_completer/__init__.py similarity index 100% rename from plugins/completers/words_completer/__init__.py rename to plugins/code/completers/words_completer/__init__.py diff --git a/plugins/completers/words_completer/__main__.py b/plugins/code/completers/words_completer/__main__.py similarity index 100% rename from plugins/completers/words_completer/__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/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 68% rename from plugins/template/plugin.py rename to plugins/ui/template/plugin.py index 0133dc7..fd843eb 100644 --- a/plugins/template/plugin.py +++ b/plugins/ui/template/plugin.py @@ -8,11 +8,11 @@ from gi.repository import Gtk # Application imports from libs.dto.base_event import BaseEvent -from plugins.plugin_base import PluginBase +from plugins.plugin_types import PluginUI -class Plugin(PluginBase): +class Plugin(PluginUI): def __init__(self): super(Plugin, self).__init__() @@ -21,14 +21,14 @@ class Plugin(PluginBase): ... 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(PluginBase): 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/core/containers/footer_container.py b/src/core/containers/footer_container.py index d7c70eb..1cfd25b 100644 --- a/src/core/containers/footer_container.py +++ b/src/core/containers/footer_container.py @@ -26,7 +26,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/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..462f3f5 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_prettify_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/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]