diff --git a/plugins/README.txt b/plugins/README.txt deleted file mode 100644 index a85e24c..0000000 --- a/plugins/README.txt +++ /dev/null @@ -1,31 +0,0 @@ -### Note -Copy the example and rename it to your desired name. Plugins define a ui target slot with the 'ui_target' requests data but don't have to if not directly interacted with. -Plugins must have a run method defined; though, you do not need to necessarily do anything within it. The run method implies that the passed in event system or other data is ready for the plugin to use. - - -### Manifest Example (All are required even if empty.) -``` -class Manifest: - name: str = "Example Plugin" - author: str = "John Doe" - version: str = "0.0.1" - support: str = "" - pre_launch: bool = False - requests: {} = { - 'pass_ui_objects': ["plugin_control_list"], - 'pass_events': True, - 'bind_keys': [] - } -``` - - -### Requests -``` -requests: {} = { - 'pass_events': true, # If empty or not present will be ignored. - "pass_ui_objects": [""], # Request reference to a UI component. Will be passed back as array to plugin. - 'bind_keys': [f"{name}||send_message:f"], - f"{name}||do_save:s"] # Bind keys with method and key pare using list. Must pass "name" like shown with delimiter to its right. - -} -``` diff --git a/plugins/code/tabs_bar/__init__.py b/plugins/code/tabs_bar/__init__.py new file mode 100644 index 0000000..d36fa8c --- /dev/null +++ b/plugins/code/tabs_bar/__init__.py @@ -0,0 +1,3 @@ +""" + Pligin Module +""" diff --git a/plugins/code/tabs_bar/__main__.py b/plugins/code/tabs_bar/__main__.py new file mode 100644 index 0000000..a576329 --- /dev/null +++ b/plugins/code/tabs_bar/__main__.py @@ -0,0 +1,3 @@ +""" + Pligin Package +""" diff --git a/plugins/code/tabs_bar/manifest.json b/plugins/code/tabs_bar/manifest.json new file mode 100644 index 0000000..e02eb6f --- /dev/null +++ b/plugins/code/tabs_bar/manifest.json @@ -0,0 +1,7 @@ +{ + "name": "Tabs Bar", + "author": "ITDominator", + "version": "0.0.1", + "support": "", + "requests": {} +} diff --git a/plugins/code/tabs_bar/plugin.py b/plugins/code/tabs_bar/plugin.py new file mode 100644 index 0000000..bc3f934 --- /dev/null +++ b/plugins/code/tabs_bar/plugin.py @@ -0,0 +1,32 @@ +# Python imports + +# Lib imports + +# Application imports +from libs.event_factory import Event_Factory, Code_Event_Types + +from plugins.plugin_types import PluginCode + +from .tabs_controller import TabsController + + + +class Plugin(PluginCode): + def __init__(self): + super(Plugin, self).__init__() + + + def _controller_message(self, event: Code_Event_Types.CodeEvent): + ... + + def load(self): + tabs_controller = TabsController() + code_container = self.requests_ui_element("code-container") + + self.register_controller("tabs", tabs_controller) + + code_container.add( tabs_controller.tabs_widget ) + code_container.reorder_child(tabs_controller.tabs_widget, 0) + + def run(self): + ... diff --git a/src/core/widgets/code/tab_widget.py b/plugins/code/tabs_bar/tab_widget.py similarity index 100% rename from src/core/widgets/code/tab_widget.py rename to plugins/code/tabs_bar/tab_widget.py diff --git a/src/core/widgets/code/controllers/tabs_controller.py b/plugins/code/tabs_bar/tabs_controller.py similarity index 95% rename from src/core/widgets/code/controllers/tabs_controller.py rename to plugins/code/tabs_bar/tabs_controller.py index 4b7d6c8..42ef088 100644 --- a/src/core/widgets/code/controllers/tabs_controller.py +++ b/plugins/code/tabs_bar/tabs_controller.py @@ -9,10 +9,11 @@ from gi.repository import Gtk from libs.controllers.controller_base import ControllerBase from libs.event_factory import Event_Factory, Code_Event_Types -from ..tabs_widget import TabsWidget -from ..tab_widget import TabWidget +from core.widgets.code.source_view import SourceView + +from .tabs_widget import TabsWidget +from .tab_widget import TabWidget -from ..source_view import SourceView diff --git a/src/core/widgets/code/tabs_widget.py b/plugins/code/tabs_bar/tabs_widget.py similarity index 99% rename from src/core/widgets/code/tabs_widget.py rename to plugins/code/tabs_bar/tabs_widget.py index 067a2ac..5d13c71 100644 --- a/src/core/widgets/code/tabs_widget.py +++ b/plugins/code/tabs_bar/tabs_widget.py @@ -23,6 +23,8 @@ class TabsWidget(Gtk.Notebook): self._subscribe_to_events() self._load_widgets() + self.show() + def _setup_styling(self): self.set_scrollable(True) diff --git a/src/core/containers/code/code_container.py b/src/core/containers/code/code_container.py index 04598e0..c0bbe28 100644 --- a/src/core/containers/code/code_container.py +++ b/src/core/containers/code/code_container.py @@ -36,18 +36,15 @@ class CodeContainer(Gtk.Box): ... def _load_widgets(self): + widget_registery.expose_object("code-container", self) + code_base = CodeBase() - self.add( self._create_tabs_widgets(code_base) ) self.add( self._create_editor_widget(code_base) ) - def _create_tabs_widgets(self, code_base: CodeBase): - return code_base.get_tabs_widget() - def _create_editor_widget(self, code_base: CodeBase): editors_container = Gtk.Box() - widget_registery.expose_object("code-container", self) widget_registery.expose_object("editors-container", editors_container) editors_container.add( Separator("separator_left") ) diff --git a/src/core/widgets/code/code_base.py b/src/core/widgets/code/code_base.py index c60650d..34ed260 100644 --- a/src/core/widgets/code/code_base.py +++ b/src/core/widgets/code/code_base.py @@ -8,7 +8,6 @@ from plugins import plugins_controller from libs.controllers.controller_manager import ControllerManager from .controllers.files_controller import FilesController -from .controllers.tabs_controller import TabsController from .controllers.commands_controller import CommandsController from .controllers.completion_controller import CompletionController from .controllers.views.source_views_controller import SourceViewsController @@ -31,23 +30,18 @@ class CodeBase: def _load_controllers(self): files_controller = FilesController() - tabs_controller = TabsController() commands_controller = CommandsController() completion_controller = CompletionController() source_views_controller = SourceViewsController() # self.controller_manager.register_controller("base", self) self.controller_manager.register_controller("files", files_controller) - self.controller_manager.register_controller("tabs", tabs_controller) self.controller_manager.register_controller("commands", commands_controller) self.controller_manager.register_controller("completion", completion_controller) self.controller_manager.register_controller("source_views", source_views_controller) self.controller_manager.register_controller("plugins", plugins_controller) self.controller_manager.register_controller("widgets", widget_registery) - def get_tabs_widget(self): - return self.controller_manager["tabs"].get_tabs_widget() - def create_source_view(self): source_view = self.controller_manager["source_views"].create_source_view() self.controller_manager["completion"].register_completer( diff --git a/src/libs/controllers/controller_base.py b/src/libs/controllers/controller_base.py index 88d564d..39bd74f 100644 --- a/src/libs/controllers/controller_base.py +++ b/src/libs/controllers/controller_base.py @@ -39,3 +39,6 @@ class ControllerBase(Singleton, EmitDispatcher): def message_to_selected(self, names: list[str], event: BaseEvent): for name in names: self.controller_context.message_to_selected(name, event) + + def register_controller(self, name: str, controller): + self.controller_context.register_controller(name, controller) diff --git a/src/libs/controllers/controller_context.py b/src/libs/controllers/controller_context.py index ac0a661..dd33f91 100644 --- a/src/libs/controllers/controller_context.py +++ b/src/libs/controllers/controller_context.py @@ -25,3 +25,6 @@ class ControllerContext: def message_to_selected(self, name: list, event: BaseEvent): raise ControllerContextException("Controller Context 'message_to_selected' must be overriden by Controller Manager...") + + def register_controller(self, name: str, controller): + raise ControllerContextException("Controller Context 'register_controller' must be overriden by Controller Manager...") diff --git a/src/libs/controllers/controller_manager.py b/src/libs/controllers/controller_manager.py index 09311d2..abb4b08 100644 --- a/src/libs/controllers/controller_manager.py +++ b/src/libs/controllers/controller_manager.py @@ -22,9 +22,10 @@ class ControllerManager(Singleton, dict): def _crete_controller_context(self) -> ControllerContext: - controller_context = ControllerContext() - controller_context.message_to = self.message_to - controller_context.message = self.message + controller_context = ControllerContext() + controller_context.message_to = self.message_to + controller_context.message = self.message + controller_context.register_controller = self.register_controller return controller_context diff --git a/src/plugins/controller.py b/src/plugins/controller.py index 805baf5..c3888fa 100644 --- a/src/plugins/controller.py +++ b/src/plugins/controller.py @@ -67,31 +67,26 @@ class PluginsController(ControllerBase, PluginsControllerMixin, PluginReloadMixi parent_path = os.getcwd() for manifest_meta in manifest_metas: - path, folder, manifest = manifest_meta.path, manifest_meta.folder, manifest_meta.manifest - try: - target = join(path, "plugin.py") + path, \ + folder, \ + manifest = manifest_meta.path, manifest_meta.folder, manifest_meta.manifest + target = join(path, "plugin.py") + if not os.path.exists(target): - raise PluginsControllerException("Invalid Plugin Structure: Plugin doesn't have 'plugin.py'. Aboarting load...") + raise PluginsControllerException( + "Invalid Plugin Structure: Plugin doesn't have 'plugin.py'. Aboarting load..." + ) module = self._load_plugin_module(path, folder, target) - if is_pre_launch: - self._run_with_pool(module, manifest_meta) - else: - GLib.idle_add( - self._run_with_pool, module, manifest_meta - ) - except Exception as e: - logger.info(f"Malformed Plugin: Not loading -->: '{folder}' !") + self._handle_plugin_execute(is_pre_launch, module, manifest_meta) + except PluginsControllerException as e: + logger.info(f"Malformed Plugin: Not loading -->: '{manifest_meta.folder}' !") logger.debug(f"Trace: {traceback.print_exc()}") os.chdir(parent_path) - def _run_with_pool(self, module: type, manifest_meta: ManifestMeta): - with ThreadPoolExecutor(max_workers = 1) as executor: - executor.submit(self.execute_plugin, module, manifest_meta) - def _load_plugin_module(self, path, folder, target): os.chdir(path) @@ -105,17 +100,27 @@ class PluginsController(ControllerBase, PluginsControllerMixin, PluginReloadMixi return module - def create_plugin_context(self): - plugin_context: PluginContext = PluginContext() + def _handle_plugin_execute( + self, is_pre_launch: bool, module, manifest_meta + ): + if not is_pre_launch: + GLib.idle_add( + self._run_with_pool, module, manifest_meta + ) + return - plugin_context.requests_ui_element: callable = self.requests_ui_element - plugin_context.message: callable = self.message - plugin_context.message_to: callable = self.message_to - plugin_context.message_to_selected: callable = self.message_to_selected - plugin_context.emit: callable = event_system.emit - plugin_context.emit_and_await: callable = event_system.emit_and_await + self._run_with_pool(module, manifest_meta) - return plugin_context + def _run_with_pool(self, module: type, manifest_meta: ManifestMeta): + with ThreadPoolExecutor(max_workers = 1) as executor: + future = executor.submit(self.execute_plugin, module, manifest_meta) + future.add_done_callback(self._handle_future_exception) + + def _handle_future_exception(self, future): + try: + future.result() + except Exception: + logger.exception("Plugin crashed during execution...") def pre_launch_plugins(self) -> None: logger.info(f"Loading pre-launch plugins...") @@ -142,6 +147,18 @@ class PluginsController(ControllerBase, PluginsControllerMixin, PluginReloadMixi self._plugin_collection.append(manifest_meta) + def create_plugin_context(self): + plugin_context: PluginContext = PluginContext() + + plugin_context.requests_ui_element: callable = self.requests_ui_element + plugin_context.message: callable = self.message + plugin_context.message_to: callable = self.message_to + plugin_context.message_to_selected: callable = self.message_to_selected + plugin_context.emit: callable = event_system.emit + plugin_context.emit_and_await: callable = event_system.emit_and_await + plugin_context.register_controller: callable = self.register_controller + + return plugin_context plugins_controller = PluginsController() diff --git a/src/plugins/plugin_context.py b/src/plugins/plugin_context.py index ef37e32..0841392 100644 --- a/src/plugins/plugin_context.py +++ b/src/plugins/plugin_context.py @@ -38,3 +38,7 @@ class PluginContext: def emit_and_await(self, event_type: str, data: tuple = ()): raise PluginContextException("Plugin Context 'emit_and_await' must be overridden...") + + def register_controller(self, name: str, controller): + raise PluginContextException("Plugin Context 'register_controller' must be overridden...") + diff --git a/src/plugins/plugin_types/plugin_code.py b/src/plugins/plugin_types/plugin_code.py index 76bd503..26e0983 100644 --- a/src/plugins/plugin_types/plugin_code.py +++ b/src/plugins/plugin_types/plugin_code.py @@ -42,3 +42,6 @@ class PluginCode(PluginBase): def message_to_selected(self, names: list[str], event: BaseEvent): return self.plugin_context.message_to_selected(names, event) + + def register_controller(self, name: str, controller): + return self.plugin_context.register_controller(name, controller)