From 74f386e819e6526600c777cf32faccc5195d3d55 Mon Sep 17 00:00:00 2001 From: cschen Date: Sat, 28 Sep 2024 19:55:20 +0200 Subject: [PATCH] fix: switched to the proper config chore: switched to bundled codemp library in sublime fix: fixed circular dependency contd: small step towards rewrite. --- main.py | 6 +-- plugin/commands/client.py | 28 +++++------- plugin/core/buffers.py | 30 ++++++------ plugin/core/client.py | 96 --------------------------------------- plugin/core/registry.py | 5 -- plugin/core/session.py | 3 +- plugin/core/workspace.py | 19 ++++---- src/workspace.py | 0 8 files changed, 39 insertions(+), 148 deletions(-) delete mode 100644 plugin/core/client.py delete mode 100644 plugin/core/registry.py delete mode 100644 src/workspace.py diff --git a/main.py b/main.py index fd8432a..016d28b 100644 --- a/main.py +++ b/main.py @@ -3,11 +3,11 @@ import sublime import sublime_plugin import logging -from lib import codemp +import codemp from .plugin.utils import safe_listener_detach from .plugin.core.session import session -from .plugin.core.registry import workspaces -from .plugin.core.registry import buffers +from .plugin.core.workspace import workspaces +from .plugin.core.buffers import buffers from .plugin.commands.client import CodempConnectCommand from .plugin.commands.client import CodempDisconnectCommand diff --git a/plugin/commands/client.py b/plugin/commands/client.py index ca63cda..52335b7 100644 --- a/plugin/commands/client.py +++ b/plugin/commands/client.py @@ -3,10 +3,10 @@ import sublime_plugin import logging import random -from ...lib import codemp +import codemp from ..core.session import session -from ..core.registry import workspaces -from ..core.registry import buffers +from ..core.workspace import workspaces +from ..core.buffers import buffers from input_handlers import SimpleTextInput from input_handlers import SimpleListInput @@ -14,14 +14,13 @@ from input_handlers import SimpleListInput logger = logging.getLogger(__name__) class CodempConnectCommand(sublime_plugin.WindowCommand): - def run(self, server_host, user_name, password): # pyright: ignore[reportIncompatibleMethodOverride] def _(): try: - config = codemp.get_default_config() - config.host = server_host - config.username = user_name - config.password = password + config = codemp.Config( + username = user_name, + password = password, + host = server_host) session.connect(config) except Exception as e: sublime.error_message( @@ -72,15 +71,14 @@ class CodempDisconnectCommand(sublime_plugin.WindowCommand): # Join Workspace Command class CodempJoinWorkspaceCommand(sublime_plugin.WindowCommand): def is_enabled(self) -> bool: - return client.codemp is not None + return session.is_active() def run(self, workspace_id): # pyright: ignore[reportIncompatibleMethodOverride] - assert client.codemp is not None if workspace_id is None: return logger.info(f"Joining workspace: '{workspace_id}'...") - promise = client.codemp.join_workspace(workspace_id) + promise = session.client.join_workspace(workspace_id) active_window = sublime.active_window() def _(): @@ -92,19 +90,15 @@ class CodempJoinWorkspaceCommand(sublime_plugin.WindowCommand): ) sublime.error_message(f"Could not join workspace '{workspace_id}'") return - client.install_workspace(workspace, active_window) - + workspaces.add(workspace) sublime.set_timeout_async(_) - # the else shouldn't really happen, and if it does, it should already be instantiated. - # ignore. def input_description(self): return "Join:" def input(self, args): - assert client.codemp is not None if "workspace_id" not in args: - list = client.codemp.list_workspaces(True, True) + list = session.client.list_workspaces(True, True) return SimpleListInput( ("workspace_id", list.wait()), ) diff --git a/plugin/core/buffers.py b/plugin/core/buffers.py index 7df05b2..1da5d8b 100644 --- a/plugin/core/buffers.py +++ b/plugin/core/buffers.py @@ -1,8 +1,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import Optional, TYPE_CHECKING if TYPE_CHECKING: from .workspace import WorkspaceManager - from ...lib import codemp + import codemp import sublime import os @@ -16,10 +16,10 @@ from ..utils import bidict logger = logging.getLogger(__name__) -def bind_buffer_manager(buff: BufferManager): - def text_callback(bufctl: codemp.BufferController): +def bind_callback(v: sublime.View): + def _callback(bufctl: codemp.BufferController): def _(): - change_id = buff.view.change_id() + change_id = v.change_id() while change := bufctl.try_recv().wait(): logger.debug("received remote buffer change!") if change is None: @@ -32,13 +32,13 @@ def bind_buffer_manager(buff: BufferManager): # In case a change arrives to a background buffer, just apply it. # We are not listening on it. Otherwise, interrupt the listening # to avoid echoing back the change just received. - if buff.view.id() == g.ACTIVE_CODEMP_VIEW: - buff.view.settings()[g.CODEMP_IGNORE_NEXT_TEXT_CHANGE] = True + if v.id() == g.ACTIVE_CODEMP_VIEW: + v.settings()[g.CODEMP_IGNORE_NEXT_TEXT_CHANGE] = True # we need to go through a sublime text command, since the method, # view.replace needs an edit token, that is obtained only when calling # a textcommand associated with a view. - buff.view.run_command( + v.run_command( "codemp_replace_text", { "start": change.start, @@ -48,7 +48,7 @@ def bind_buffer_manager(buff: BufferManager): }, # pyright: ignore ) sublime.set_timeout(_) - return text_callback + return _callback class BufferManager(): def __init__(self, handle: codemp.BufferController, v: sublime.View, filename: str): @@ -56,6 +56,7 @@ class BufferManager(): self.view: sublime.View = v self.id = self.handle.path() self.filename = filename + self.handle.callback(bind_callback(self.view)) def __del__(self): logger.debug(f"dropping buffer {self.id}") @@ -80,7 +81,6 @@ class BufferManager(): def sync(self, text_listener): promise = self.handle.content() - def _(): content = promise.wait() safe_listener_detach(text_listener) @@ -92,13 +92,13 @@ class BufferRegistry(): def __init__(self): self._buffers: bidict[BufferManager, WorkspaceManager] = bidict() - def lookup(self, ws: WorkspaceManager | None = None) -> list[BufferManager]: + def lookup(self, ws: Optional[WorkspaceManager] = None) -> list[BufferManager]: if not ws: return list(self._buffers.keys()) bf = self._buffers.inverse.get(ws) return bf if bf else [] - def lookupId(self, bid: str) -> BufferManager | None: + def lookupId(self, bid: str) -> Optional[BufferManager]: return next((bf for bf in self._buffers if bf.id == bid), None) def add(self, bhandle: codemp.BufferController, wsm: WorkspaceManager): @@ -115,17 +115,17 @@ class BufferRegistry(): view.set_status(g.SUBLIME_STATUS_ID, "[Codemp]") bfm = BufferManager(bhandle, view, tmpfile) + self._buffers[bfm] = wsm - def remove(self, bf: BufferManager | str | None): + def remove(self, bf: Optional[BufferManager | str]): if isinstance(bf, str): bf = self.lookupId(bf) - if not bf: return del self._buffers[bf] bf.view.close() - +buffers = BufferRegistry() diff --git a/plugin/core/client.py b/plugin/core/client.py deleted file mode 100644 index d40523e..0000000 --- a/plugin/core/client.py +++ /dev/null @@ -1,96 +0,0 @@ -from __future__ import annotations -from typing import Optional -from typing import TYPE_CHECKING - -if TYPE_CHECKING: - from ..workspace.workspace import VirtualWorkspace - -import sublime -import logging - -from ..utils import bidict - -logger = logging.getLogger(__name__) - - -class VirtualClient: - def __init__(self): - self.codemp: Optional[codemp.Client] = None - self.driver: Optional[codemp.Driver] = None - - # bookkeeping corner - self._id2buffer: dict[str, VirtualBuffer] = {} - self._id2workspace: dict[str, VirtualWorkspace] = {} - - self._view2buff: dict[sublime.View, VirtualBuffer] = {} - self._buff2workspace: bidict[VirtualBuffer, VirtualWorkspace] = bidict() - self._workspace2window: dict[VirtualWorkspace, sublime.Window] = {} - - def disconnect(self): - if self.codemp is None: - return - logger.info("disconnecting from the current client") - # for each workspace tell it to clean up after itself. - for vws in self.all_workspaces(): - self.uninstall_workspace(vws) - self.codemp.leave_workspace(vws.id) - - self._id2workspace.clear() - self._id2buffer.clear() - self._buff2workspace.clear() - self._view2buff.clear() - self._workspace2window.clear() - - if self.driver is not None: - self.driver.stop() - self.driver = None - self.codemp = None - - def connect(self, host: str, user: str, password: str): - if self.codemp is not None: - logger.info("Disconnecting from previous client.") - return self.disconnect() - - if self.driver is None: - self.driver = codemp.init() - logger.debug("registering logger callback...") - if not codemp.set_logger(lambda msg: logger.debug(msg), False): - logger.debug( - "could not register the logger... If reconnecting it's ok, the previous logger is still registered" - ) - - config = codemp.get_default_config() - config.username = user - config.host = host - config.password = password - - self.codemp = codemp.connect(config).wait() - id = self.codemp.user_id() - logger.debug(f"Connected to '{host}' as user {user} (id: {id})") - - def install_workspace(self, workspace: codemp.Workspace, window: sublime.Window): - vws = VirtualWorkspace(workspace, window) - self._workspace2window[vws] = window - self._id2workspace[vws.id] = vws - - def uninstall_workspace(self, vws: VirtualWorkspace): - # we aim at dropping all references to the workspace - # as well as all the buffers associated with it. - # if we did a good job the dunder del method will kick - # and continue with the cleanup. - logger.info(f"Uninstalling workspace '{vws.id}'...") - del self._workspace2window[vws] - del self._id2workspace[vws.id] - for vbuff in self.all_buffers(vws): - self.unregister_buffer(vbuff) - - vws.uninstall() - - def workspaces_in_server(self): - return self.codemp.active_workspaces() if self.codemp else [] - - def user_id(self): - return self.codemp.user_id() if self.codemp else None - - -client = VirtualClient() diff --git a/plugin/core/registry.py b/plugin/core/registry.py deleted file mode 100644 index 443c62d..0000000 --- a/plugin/core/registry.py +++ /dev/null @@ -1,5 +0,0 @@ -from .workspace import WorkspaceRegistry -from .buffers import BufferRegistry - -workspaces = WorkspaceRegistry() -buffers = BufferRegistry() diff --git a/plugin/core/session.py b/plugin/core/session.py index 5c6d290..82f5f33 100644 --- a/plugin/core/session.py +++ b/plugin/core/session.py @@ -1,5 +1,5 @@ import logging -from ...lib import codemp +import codemp logger = logging.getLogger(__name__) @@ -54,5 +54,4 @@ class SessionManager(): def drop_client(self): self._client = None - session = SessionManager() \ No newline at end of file diff --git a/plugin/core/workspace.py b/plugin/core/workspace.py index a3edc78..7c907b1 100644 --- a/plugin/core/workspace.py +++ b/plugin/core/workspace.py @@ -3,7 +3,7 @@ from typing import Optional, Tuple from typing import TYPE_CHECKING if TYPE_CHECKING: from ...main import CodempClientTextChangeListener - from ...lib import codemp + import codemp import sublime import shutil @@ -13,7 +13,7 @@ import logging from .. import globals as g from ..utils import draw_cursor_region from ..utils import bidict -from ..core.registry import buffers +from .buffers import buffers logger = logging.getLogger(__name__) @@ -64,11 +64,11 @@ class WorkspaceManager(): self.curctl: codemp.CursorController = self.handle.cursor() self.rootdir: str = rootdir self.id: str = self.handle.id() + self.curctl.callback(cursor_callback) def __del__(self): logger.debug(f"dropping workspace {self.id}") self.curctl.clear_callback() - self.curctl.stop() for buff in self.handle.buffer_list(): if not self.handle.detach(buff): @@ -76,9 +76,8 @@ class WorkspaceManager(): f"could not detach from '{buff}' for workspace '{self.id}'." ) - bfm = buffers.lookupId(buff) - if bfm: - buffers.remove(bfm) + for bfm in buffers.lookup(self): + buffers.remove(bfm) def send_cursor(self, id: str, start: Tuple[int, int], end: Tuple[int, int]): # we can safely ignore the promise, we don't really care if everything @@ -89,13 +88,13 @@ class WorkspaceRegistry(): def __init__(self) -> None: self._workspaces: bidict[WorkspaceManager, sublime.Window] = bidict() - def lookup(self, w: sublime.Window | None = None) -> list[WorkspaceManager]: + def lookup(self, w: Optional[sublime.Window] = None) -> list[WorkspaceManager]: if not w: return list(self._workspaces.keys()) ws = self._workspaces.inverse.get(w) return ws if ws else [] - def lookupId(self, wid: str) -> WorkspaceManager | None: + def lookupId(self, wid: str) -> Optional[WorkspaceManager]: return next((ws for ws in self._workspaces if ws.id == wid), None) def add(self, wshandle: codemp.Workspace) -> WorkspaceManager: @@ -109,7 +108,7 @@ class WorkspaceRegistry(): self._workspaces[wm] = win return wm - def remove(self, ws: WorkspaceManager | str | None): + def remove(self, ws: Optional[WorkspaceManager | str]): if isinstance(ws, str): ws = self.lookupId(ws) @@ -120,7 +119,7 @@ class WorkspaceRegistry(): del self._workspaces[ws] - +workspaces = WorkspaceRegistry() diff --git a/src/workspace.py b/src/workspace.py deleted file mode 100644 index e69de29..0000000