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
This commit is contained in:
2026-03-28 16:14:04 -05:00
parent 70877a7ee1
commit dc2997ec16
10 changed files with 62 additions and 78 deletions

View File

@@ -1,6 +1,5 @@
___
### Add
1. Add TreeSitter
1. Add Collapsable code blocks
1. Add Godot LSP Client
1. Add Terminal plugin

View File

@@ -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'])}")

View File

@@ -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._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

View File

@@ -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):

View File

@@ -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

View File

@@ -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):

View File

@@ -1,4 +1,5 @@
# Python imports
from os import path
import json
# Lib imports
@@ -24,6 +25,8 @@ 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
@@ -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 {}

View File

@@ -155,9 +155,10 @@ class SourceFile(GtkSource.File):
self.buffer.unblock_modified_changed_signal()
def is_externally_modified(self) -> bool:
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

View File

@@ -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())