From dc2997ec16cd113628fe6b342f54e1e78f79fa75 Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Sat, 28 Mar 2026 16:14:04 -0500 Subject: [PATCH] feat(lsp, ui, core): refactor LSP initialization, improve config handling, and clean up TreeSitter * LSP Client & Manager Refactored initialization flow to use internal state instead of passing params Added workspace_path and init_opts to LSPClient Simplified send_initialize_message() (no external args) Updated manager/client APIs to require explicit workspace_path and typed init_opts Improved client lifecycle handling and UI button toggling * LSP Manager UI Added {user.home} substitution support in configs Use live editor buffer for JSON config parsing instead of static template Minor cleanup and formatting improvements * Core Widgets Prevent external modification checks for buffer-only files in SourceFile Minor formatting cleanup in SourceView * Plugins / Manifest Expanded manifest schema: added description and copyright, reordered fields * Cleanup Removed TreeSitter compile script and TODO entry General code formatting and small consistency fixes chore: remove unused TreeSitter tooling and related TODO entry --- TODO.md | 1 - .../event-watchers/tree_sitter/compile.py | 39 ------------------- .../lsp_manager/client/lsp_client.py | 27 ++++++++----- .../lsp_manager/client/lsp_client_events.py | 9 +++-- .../lsp_manager/lsp_manager.py | 22 ++++++----- .../lsp_manager/lsp_manager_client.py | 10 +++-- .../lsp_manager/lsp_manager_ui.py | 17 +++++--- src/core/widgets/code/source_file.py | 5 ++- src/core/widgets/code/source_view.py | 6 +-- src/libs/dto/plugins/manifest.py | 4 +- 10 files changed, 62 insertions(+), 78 deletions(-) delete mode 100644 plugins/code/event-watchers/tree_sitter/compile.py diff --git a/TODO.md b/TODO.md index c369f18..b24fcb1 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,5 @@ ___ ### Add -1. Add TreeSitter 1. Add Collapsable code blocks 1. Add Godot LSP Client 1. Add Terminal plugin diff --git a/plugins/code/event-watchers/tree_sitter/compile.py b/plugins/code/event-watchers/tree_sitter/compile.py deleted file mode 100644 index ac8fb2f..0000000 --- a/plugins/code/event-watchers/tree_sitter/compile.py +++ /dev/null @@ -1,39 +0,0 @@ -from .libs.tree_sitter_language_pack import \ - init, download, get_language, get_parser, available_languages, process, ProcessConfig - -# Optional: Pre-download specific languages for offline use -#init(["python", "javascript", "rust"]) - -# Get a language (auto-downloads if not cached) -language = get_language("python") - -# Get a pre-configured parser (auto-downloads if needed) -parser = get_parser("python") -tree = parser.parse(b"def hello(): pass") -print(tree.root_node) - -# List all available languages -for lang in available_languages(): - print(lang) - - -# Extract file intelligence (auto-downloads language if needed) -result = process( - "def hello(): pass", - ProcessConfig( language = "python") -) -print(f"Functions: {len(result['structure'])}") - -# Pre-download languages for offline use -download(["python", "javascript"]) - -# With chunking -result = process( - source, - ProcessConfig( - language = "python", - chunk_max_size = 1000, - comments = True - ) -) -print(f"Chunks: {len(result['chunks'])}") diff --git a/plugins/code/language_server_clients/lsp_manager/client/lsp_client.py b/plugins/code/language_server_clients/lsp_manager/client/lsp_client.py index 816e711..a36f069 100644 --- a/plugins/code/language_server_clients/lsp_manager/client/lsp_client.py +++ b/plugins/code/language_server_clients/lsp_manager/client/lsp_client.py @@ -19,13 +19,10 @@ class LSPClient(LSPClientWebsocket): def __init__(self): super(LSPClient, self).__init__() - # https://github.com/microsoft/multilspy/tree/main/src/multilspy/language_servers - # initialize-params-slim.json was created off of jedi_language_server one - # self._init_params = settings_manager.get_lsp_init_data() - self._language: str = "" + self._workspace_path: str = "" self._init_params: dict = {} - self._event_history: dict[int, str] = {} + self._init_opts: dict = {} try: _USER_HOME = path.expanduser('~') @@ -33,19 +30,29 @@ class LSPClient(LSPClientWebsocket): _LSP_INIT_CONFIG = f"{_SCRIPT_PTH}/../configs/initialize-params-slim.json" with open(_LSP_INIT_CONFIG) as file: - data = file.read().replace("{user.home}", _USER_HOME) + data = file.read() self._init_params = json.loads(data) except Exception as e: logger.error( f"LSP Controller: {_LSP_INIT_CONFIG}\n\t\t{repr(e)}" ) - self._message_id: int = -1 - self._socket = None - self.read_lock = threading.Lock() - self.write_lock = threading.Lock() + + self._socket = None + self._message_id: int = -1 + self._event_history: dict[int, str] = {} + + self.read_lock = threading.Lock() + self.write_lock = threading.Lock() + def set_language(self, language: str): self._language = language + def set_workspace_path(self, workspace_path: str): + self._workspace_path = workspace_path + + def set_init_opts(self, init_opts: dict[str, str]): + self._init_opts = init_opts + def set_socket(self, socket: str): self._socket = socket diff --git a/plugins/code/language_server_clients/lsp_manager/client/lsp_client_events.py b/plugins/code/language_server_clients/lsp_manager/client/lsp_client_events.py index a4f2bac..df52d8e 100644 --- a/plugins/code/language_server_clients/lsp_manager/client/lsp_client_events.py +++ b/plugins/code/language_server_clients/lsp_manager/client/lsp_client_events.py @@ -17,11 +17,12 @@ from ..dto.code.lsp.lsp_messages import symbols_request class LSPClientEvents: - def send_initialize_message(self, init_ops: dict, workspace_file: str, workspace_uri: str): - folder_name = os.path.basename(workspace_file) + def send_initialize_message(self): + folder_name = os.path.basename(self._workspace_path) + workspace_uri = f"file://{self._workspace_path}" self._init_params["processId"] = None - self._init_params["rootPath"] = workspace_file + self._init_params["rootPath"] = self._workspace_path self._init_params["rootUri"] = workspace_uri self._init_params["workspaceFolders"] = [ { @@ -30,7 +31,7 @@ class LSPClientEvents: } ] - self._init_params["initializationOptions"] = init_ops + self._init_params["initializationOptions"] = self._init_opts self.send_request("initialize", self._init_params) def send_initialized_message(self): diff --git a/plugins/code/language_server_clients/lsp_manager/lsp_manager.py b/plugins/code/language_server_clients/lsp_manager/lsp_manager.py index cbfce28..a806b89 100644 --- a/plugins/code/language_server_clients/lsp_manager/lsp_manager.py +++ b/plugins/code/language_server_clients/lsp_manager/lsp_manager.py @@ -54,17 +54,21 @@ class LSPManager(ControllerBase): self.response_registry.unregister_handler(event.lang_id) self.lsp_manager_ui.remove_client_listing(event.lang_id) - def _on_create_client(self, ui, lang_id: str, workspace_uri: str) -> bool: + def _on_create_client(self, ui, lang_id: str, workspace_path: str) -> bool: init_opts = ui.get_init_opts(lang_id) - result = self.create_client(lang_id, workspace_uri, init_opts) + result = self.create_client(lang_id, workspace_path, init_opts) + if result: - ui.toggle_client_buttons(show_close=True) + ui.toggle_client_buttons(show_close = True) + return result def _on_close_client(self, ui, lang_id: str) -> bool: result = self.close_client(lang_id) + if result: - ui.toggle_client_buttons(show_close=False) + ui.toggle_client_buttons(show_close = False) + return result def handle_destroy(self): @@ -73,12 +77,12 @@ class LSPManager(ControllerBase): def create_client( self, - lang_id: str = "python", - workspace_uri: str = "", - init_opts: dict = {} + lang_id: str, + workspace_path: str, + init_opts: dict[str, str] ) -> bool: client = self.lsp_manager_client.create_client( - lang_id, workspace_uri, init_opts + lang_id, workspace_path, init_opts ) handler = self.response_registry.get_handler(lang_id) self.lsp_manager_client.active_language_id = lang_id @@ -92,7 +96,7 @@ class LSPManager(ControllerBase): handler.set_response_cache(self.response_cache) client.handle_lsp_response = self.server_response - client.send_initialize_message(init_opts, "", f"file://{workspace_uri}") + client.send_initialize_message() return True diff --git a/plugins/code/language_server_clients/lsp_manager/lsp_manager_client.py b/plugins/code/language_server_clients/lsp_manager/lsp_manager_client.py index 8e649dd..9befbe5 100644 --- a/plugins/code/language_server_clients/lsp_manager/lsp_manager_client.py +++ b/plugins/code/language_server_clients/lsp_manager/lsp_manager_client.py @@ -22,9 +22,9 @@ class LSPManagerClient(LSPClientEventsMixin): def create_client( self, - lang_id: str = "python", - workspace_uri: str = "", - init_opts: dict = {} + lang_id: str, + workspace_path: str, + init_opts: dict[str, str] ) -> LSPClient: if lang_id in self.clients: return None @@ -33,8 +33,10 @@ class LSPManagerClient(LSPClientEventsMixin): uri = f"ws://{address}:{port}/{lang_id}" client = LSPClient() - client.set_language(lang_id) client.set_socket(uri) + client.set_language(lang_id) + client.set_workspace_path(workspace_path) + client.set_init_opts(init_opts) client.start_client() if not client.ws_client.wait_for_connection(timeout = 5.0): diff --git a/plugins/code/language_server_clients/lsp_manager/lsp_manager_ui.py b/plugins/code/language_server_clients/lsp_manager/lsp_manager_ui.py index 740dd0d..47c84c0 100644 --- a/plugins/code/language_server_clients/lsp_manager/lsp_manager_ui.py +++ b/plugins/code/language_server_clients/lsp_manager/lsp_manager_ui.py @@ -1,4 +1,5 @@ # Python imports +from os import path import json # Lib imports @@ -24,9 +25,11 @@ class LSPManagerUI(Gtk.Dialog): def __init__(self): super(LSPManagerUI, self).__init__() + self._USER_HOME = path.expanduser('~') + self.client_configs: dict[str, str] = {} - self.source_view = None + self.source_view = None self._setup_styling() self._setup_signals() @@ -167,9 +170,11 @@ class LSPManagerUI(Gtk.Dialog): lang_id = self.combo_box.get_active_text() if not lang_id: return - json_str = self.client_configs[lang_id].replace("{workspace.folder}", workspace_dir) - buffer = self.source_view.get_buffer() + json_str = self.client_configs[lang_id] \ + .replace("{workspace.folder}", workspace_dir) \ + .replace("{user.home}", self._USER_HOME) + buffer = self.source_view.get_buffer() buffer.set_text(json_str, -1) def map_parent_resize_event(self, parent): @@ -204,7 +209,7 @@ class LSPManagerUI(Gtk.Dialog): model = self.combo_box.get_model() for i, row in enumerate(model): - if row[0] == lang_id: # assuming text is in column 0 + if row[0] == lang_id: self.combo_box.remove(i) break @@ -215,7 +220,9 @@ class LSPManagerUI(Gtk.Dialog): if not lang_id or lang_id not in self.client_configs: return {} try: - lang_config = json.loads(self.client_configs[lang_id]) + buffer = self.source_view.get_buffer() + json_str = buffer.get_text(*buffer.get_bounds(), -1) + lang_config = json.loads(json_str) except json.JSONDecodeError as e: logger.error(f"Invalid JSON for {lang_id}: {e}") return {} diff --git a/src/core/widgets/code/source_file.py b/src/core/widgets/code/source_file.py index 6fe1d7b..038cecc 100644 --- a/src/core/widgets/code/source_file.py +++ b/src/core/widgets/code/source_file.py @@ -155,9 +155,10 @@ class SourceFile(GtkSource.File): self.buffer.unblock_modified_changed_signal() def is_externally_modified(self) -> bool: - stat = os.stat(self.fpath) - current = (stat.st_mtime_ns, stat.st_size) + if self.fname == "buffer": return + stat = os.stat(self.fpath) + current = (stat.st_mtime_ns, stat.st_size) is_modified = \ hasattr(self, "last_state") and not current == self.last_state diff --git a/src/core/widgets/code/source_view.py b/src/core/widgets/code/source_view.py index 4f348cd..d5ad4ca 100644 --- a/src/core/widgets/code/source_view.py +++ b/src/core/widgets/code/source_view.py @@ -19,10 +19,10 @@ class SourceView(GtkSource.View, SourceViewDnDMixin): def __init__(self, state: SourceViewStates = SourceViewStates.INSERT): super(SourceView, self).__init__() - self.state = state + self.state = state - self.sibling_right = None - self.sibling_left = None + self.sibling_right = None + self.sibling_left = None self._setup_styles() self._setup_signals() diff --git a/src/libs/dto/plugins/manifest.py b/src/libs/dto/plugins/manifest.py index 03c1a9c..4840aa8 100644 --- a/src/libs/dto/plugins/manifest.py +++ b/src/libs/dto/plugins/manifest.py @@ -13,9 +13,11 @@ from .requests import Requests class Manifest: name: str = "" author: str = "" - credit: str = "" + description: str = "" version: str = "0.0.1" support: str = "support@mail.com" + credit: str = "" + copyright: str = "GPLv2" pre_launch: bool = False autoload: bool = True requests: Requests = field(default_factory = lambda: Requests())