fix: switched to the proper config

chore: switched to bundled codemp library in sublime
fix: fixed circular dependency
contd: small step towards rewrite.
This commit is contained in:
cschen 2024-09-28 19:55:20 +02:00
parent 89df99b850
commit 74f386e819
8 changed files with 39 additions and 148 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -1,5 +0,0 @@
from .workspace import WorkspaceRegistry
from .buffers import BufferRegistry
workspaces = WorkspaceRegistry()
buffers = BufferRegistry()

View file

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

View file

@ -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,8 +76,7 @@ class WorkspaceManager():
f"could not detach from '{buff}' for workspace '{self.id}'."
)
bfm = buffers.lookupId(buff)
if bfm:
for bfm in buffers.lookup(self):
buffers.remove(bfm)
def send_cursor(self, id: str, start: Tuple[int, int], end: Tuple[int, int]):
@ -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()

View file