mirror of
https://github.com/hexedtech/codemp-sublime.git
synced 2024-11-22 14:54:48 +01:00
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:
parent
89df99b850
commit
74f386e819
8 changed files with 39 additions and 148 deletions
6
main.py
6
main.py
|
@ -3,11 +3,11 @@ import sublime
|
||||||
import sublime_plugin
|
import sublime_plugin
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from lib import codemp
|
import codemp
|
||||||
from .plugin.utils import safe_listener_detach
|
from .plugin.utils import safe_listener_detach
|
||||||
from .plugin.core.session import session
|
from .plugin.core.session import session
|
||||||
from .plugin.core.registry import workspaces
|
from .plugin.core.workspace import workspaces
|
||||||
from .plugin.core.registry import buffers
|
from .plugin.core.buffers import buffers
|
||||||
|
|
||||||
from .plugin.commands.client import CodempConnectCommand
|
from .plugin.commands.client import CodempConnectCommand
|
||||||
from .plugin.commands.client import CodempDisconnectCommand
|
from .plugin.commands.client import CodempDisconnectCommand
|
||||||
|
|
|
@ -3,10 +3,10 @@ import sublime_plugin
|
||||||
import logging
|
import logging
|
||||||
import random
|
import random
|
||||||
|
|
||||||
from ...lib import codemp
|
import codemp
|
||||||
from ..core.session import session
|
from ..core.session import session
|
||||||
from ..core.registry import workspaces
|
from ..core.workspace import workspaces
|
||||||
from ..core.registry import buffers
|
from ..core.buffers import buffers
|
||||||
|
|
||||||
from input_handlers import SimpleTextInput
|
from input_handlers import SimpleTextInput
|
||||||
from input_handlers import SimpleListInput
|
from input_handlers import SimpleListInput
|
||||||
|
@ -14,14 +14,13 @@ from input_handlers import SimpleListInput
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class CodempConnectCommand(sublime_plugin.WindowCommand):
|
class CodempConnectCommand(sublime_plugin.WindowCommand):
|
||||||
|
|
||||||
def run(self, server_host, user_name, password): # pyright: ignore[reportIncompatibleMethodOverride]
|
def run(self, server_host, user_name, password): # pyright: ignore[reportIncompatibleMethodOverride]
|
||||||
def _():
|
def _():
|
||||||
try:
|
try:
|
||||||
config = codemp.get_default_config()
|
config = codemp.Config(
|
||||||
config.host = server_host
|
username = user_name,
|
||||||
config.username = user_name
|
password = password,
|
||||||
config.password = password
|
host = server_host)
|
||||||
session.connect(config)
|
session.connect(config)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
sublime.error_message(
|
sublime.error_message(
|
||||||
|
@ -72,15 +71,14 @@ class CodempDisconnectCommand(sublime_plugin.WindowCommand):
|
||||||
# Join Workspace Command
|
# Join Workspace Command
|
||||||
class CodempJoinWorkspaceCommand(sublime_plugin.WindowCommand):
|
class CodempJoinWorkspaceCommand(sublime_plugin.WindowCommand):
|
||||||
def is_enabled(self) -> bool:
|
def is_enabled(self) -> bool:
|
||||||
return client.codemp is not None
|
return session.is_active()
|
||||||
|
|
||||||
def run(self, workspace_id): # pyright: ignore[reportIncompatibleMethodOverride]
|
def run(self, workspace_id): # pyright: ignore[reportIncompatibleMethodOverride]
|
||||||
assert client.codemp is not None
|
|
||||||
if workspace_id is None:
|
if workspace_id is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
logger.info(f"Joining workspace: '{workspace_id}'...")
|
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()
|
active_window = sublime.active_window()
|
||||||
|
|
||||||
def _():
|
def _():
|
||||||
|
@ -92,19 +90,15 @@ class CodempJoinWorkspaceCommand(sublime_plugin.WindowCommand):
|
||||||
)
|
)
|
||||||
sublime.error_message(f"Could not join workspace '{workspace_id}'")
|
sublime.error_message(f"Could not join workspace '{workspace_id}'")
|
||||||
return
|
return
|
||||||
client.install_workspace(workspace, active_window)
|
workspaces.add(workspace)
|
||||||
|
|
||||||
sublime.set_timeout_async(_)
|
sublime.set_timeout_async(_)
|
||||||
# the else shouldn't really happen, and if it does, it should already be instantiated.
|
|
||||||
# ignore.
|
|
||||||
|
|
||||||
def input_description(self):
|
def input_description(self):
|
||||||
return "Join:"
|
return "Join:"
|
||||||
|
|
||||||
def input(self, args):
|
def input(self, args):
|
||||||
assert client.codemp is not None
|
|
||||||
if "workspace_id" not in args:
|
if "workspace_id" not in args:
|
||||||
list = client.codemp.list_workspaces(True, True)
|
list = session.client.list_workspaces(True, True)
|
||||||
return SimpleListInput(
|
return SimpleListInput(
|
||||||
("workspace_id", list.wait()),
|
("workspace_id", list.wait()),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from typing import TYPE_CHECKING
|
from typing import Optional, TYPE_CHECKING
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .workspace import WorkspaceManager
|
from .workspace import WorkspaceManager
|
||||||
from ...lib import codemp
|
import codemp
|
||||||
|
|
||||||
import sublime
|
import sublime
|
||||||
import os
|
import os
|
||||||
|
@ -16,10 +16,10 @@ from ..utils import bidict
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
def bind_buffer_manager(buff: BufferManager):
|
def bind_callback(v: sublime.View):
|
||||||
def text_callback(bufctl: codemp.BufferController):
|
def _callback(bufctl: codemp.BufferController):
|
||||||
def _():
|
def _():
|
||||||
change_id = buff.view.change_id()
|
change_id = v.change_id()
|
||||||
while change := bufctl.try_recv().wait():
|
while change := bufctl.try_recv().wait():
|
||||||
logger.debug("received remote buffer change!")
|
logger.debug("received remote buffer change!")
|
||||||
if change is None:
|
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.
|
# In case a change arrives to a background buffer, just apply it.
|
||||||
# We are not listening on it. Otherwise, interrupt the listening
|
# We are not listening on it. Otherwise, interrupt the listening
|
||||||
# to avoid echoing back the change just received.
|
# to avoid echoing back the change just received.
|
||||||
if buff.view.id() == g.ACTIVE_CODEMP_VIEW:
|
if v.id() == g.ACTIVE_CODEMP_VIEW:
|
||||||
buff.view.settings()[g.CODEMP_IGNORE_NEXT_TEXT_CHANGE] = True
|
v.settings()[g.CODEMP_IGNORE_NEXT_TEXT_CHANGE] = True
|
||||||
|
|
||||||
# we need to go through a sublime text command, since the method,
|
# we need to go through a sublime text command, since the method,
|
||||||
# view.replace needs an edit token, that is obtained only when calling
|
# view.replace needs an edit token, that is obtained only when calling
|
||||||
# a textcommand associated with a view.
|
# a textcommand associated with a view.
|
||||||
buff.view.run_command(
|
v.run_command(
|
||||||
"codemp_replace_text",
|
"codemp_replace_text",
|
||||||
{
|
{
|
||||||
"start": change.start,
|
"start": change.start,
|
||||||
|
@ -48,7 +48,7 @@ def bind_buffer_manager(buff: BufferManager):
|
||||||
}, # pyright: ignore
|
}, # pyright: ignore
|
||||||
)
|
)
|
||||||
sublime.set_timeout(_)
|
sublime.set_timeout(_)
|
||||||
return text_callback
|
return _callback
|
||||||
|
|
||||||
class BufferManager():
|
class BufferManager():
|
||||||
def __init__(self, handle: codemp.BufferController, v: sublime.View, filename: str):
|
def __init__(self, handle: codemp.BufferController, v: sublime.View, filename: str):
|
||||||
|
@ -56,6 +56,7 @@ class BufferManager():
|
||||||
self.view: sublime.View = v
|
self.view: sublime.View = v
|
||||||
self.id = self.handle.path()
|
self.id = self.handle.path()
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
|
self.handle.callback(bind_callback(self.view))
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
logger.debug(f"dropping buffer {self.id}")
|
logger.debug(f"dropping buffer {self.id}")
|
||||||
|
@ -80,7 +81,6 @@ class BufferManager():
|
||||||
|
|
||||||
def sync(self, text_listener):
|
def sync(self, text_listener):
|
||||||
promise = self.handle.content()
|
promise = self.handle.content()
|
||||||
|
|
||||||
def _():
|
def _():
|
||||||
content = promise.wait()
|
content = promise.wait()
|
||||||
safe_listener_detach(text_listener)
|
safe_listener_detach(text_listener)
|
||||||
|
@ -92,13 +92,13 @@ class BufferRegistry():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._buffers: bidict[BufferManager, WorkspaceManager] = bidict()
|
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:
|
if not ws:
|
||||||
return list(self._buffers.keys())
|
return list(self._buffers.keys())
|
||||||
bf = self._buffers.inverse.get(ws)
|
bf = self._buffers.inverse.get(ws)
|
||||||
return bf if bf else []
|
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)
|
return next((bf for bf in self._buffers if bf.id == bid), None)
|
||||||
|
|
||||||
def add(self, bhandle: codemp.BufferController, wsm: WorkspaceManager):
|
def add(self, bhandle: codemp.BufferController, wsm: WorkspaceManager):
|
||||||
|
@ -115,17 +115,17 @@ class BufferRegistry():
|
||||||
view.set_status(g.SUBLIME_STATUS_ID, "[Codemp]")
|
view.set_status(g.SUBLIME_STATUS_ID, "[Codemp]")
|
||||||
|
|
||||||
bfm = BufferManager(bhandle, view, tmpfile)
|
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):
|
if isinstance(bf, str):
|
||||||
bf = self.lookupId(bf)
|
bf = self.lookupId(bf)
|
||||||
|
|
||||||
if not bf: return
|
if not bf: return
|
||||||
|
|
||||||
del self._buffers[bf]
|
del self._buffers[bf]
|
||||||
bf.view.close()
|
bf.view.close()
|
||||||
|
|
||||||
|
buffers = BufferRegistry()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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()
|
|
|
@ -1,5 +0,0 @@
|
||||||
from .workspace import WorkspaceRegistry
|
|
||||||
from .buffers import BufferRegistry
|
|
||||||
|
|
||||||
workspaces = WorkspaceRegistry()
|
|
||||||
buffers = BufferRegistry()
|
|
|
@ -1,5 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
from ...lib import codemp
|
import codemp
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -54,5 +54,4 @@ class SessionManager():
|
||||||
def drop_client(self):
|
def drop_client(self):
|
||||||
self._client = None
|
self._client = None
|
||||||
|
|
||||||
|
|
||||||
session = SessionManager()
|
session = SessionManager()
|
|
@ -3,7 +3,7 @@ from typing import Optional, Tuple
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ...main import CodempClientTextChangeListener
|
from ...main import CodempClientTextChangeListener
|
||||||
from ...lib import codemp
|
import codemp
|
||||||
|
|
||||||
import sublime
|
import sublime
|
||||||
import shutil
|
import shutil
|
||||||
|
@ -13,7 +13,7 @@ import logging
|
||||||
from .. import globals as g
|
from .. import globals as g
|
||||||
from ..utils import draw_cursor_region
|
from ..utils import draw_cursor_region
|
||||||
from ..utils import bidict
|
from ..utils import bidict
|
||||||
from ..core.registry import buffers
|
from .buffers import buffers
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -64,11 +64,11 @@ class WorkspaceManager():
|
||||||
self.curctl: codemp.CursorController = self.handle.cursor()
|
self.curctl: codemp.CursorController = self.handle.cursor()
|
||||||
self.rootdir: str = rootdir
|
self.rootdir: str = rootdir
|
||||||
self.id: str = self.handle.id()
|
self.id: str = self.handle.id()
|
||||||
|
self.curctl.callback(cursor_callback)
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
logger.debug(f"dropping workspace {self.id}")
|
logger.debug(f"dropping workspace {self.id}")
|
||||||
self.curctl.clear_callback()
|
self.curctl.clear_callback()
|
||||||
self.curctl.stop()
|
|
||||||
|
|
||||||
for buff in self.handle.buffer_list():
|
for buff in self.handle.buffer_list():
|
||||||
if not self.handle.detach(buff):
|
if not self.handle.detach(buff):
|
||||||
|
@ -76,9 +76,8 @@ class WorkspaceManager():
|
||||||
f"could not detach from '{buff}' for workspace '{self.id}'."
|
f"could not detach from '{buff}' for workspace '{self.id}'."
|
||||||
)
|
)
|
||||||
|
|
||||||
bfm = buffers.lookupId(buff)
|
for bfm in buffers.lookup(self):
|
||||||
if bfm:
|
buffers.remove(bfm)
|
||||||
buffers.remove(bfm)
|
|
||||||
|
|
||||||
def send_cursor(self, id: str, start: Tuple[int, int], end: Tuple[int, int]):
|
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
|
# we can safely ignore the promise, we don't really care if everything
|
||||||
|
@ -89,13 +88,13 @@ class WorkspaceRegistry():
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self._workspaces: bidict[WorkspaceManager, sublime.Window] = bidict()
|
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:
|
if not w:
|
||||||
return list(self._workspaces.keys())
|
return list(self._workspaces.keys())
|
||||||
ws = self._workspaces.inverse.get(w)
|
ws = self._workspaces.inverse.get(w)
|
||||||
return ws if ws else []
|
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)
|
return next((ws for ws in self._workspaces if ws.id == wid), None)
|
||||||
|
|
||||||
def add(self, wshandle: codemp.Workspace) -> WorkspaceManager:
|
def add(self, wshandle: codemp.Workspace) -> WorkspaceManager:
|
||||||
|
@ -109,7 +108,7 @@ class WorkspaceRegistry():
|
||||||
self._workspaces[wm] = win
|
self._workspaces[wm] = win
|
||||||
return wm
|
return wm
|
||||||
|
|
||||||
def remove(self, ws: WorkspaceManager | str | None):
|
def remove(self, ws: Optional[WorkspaceManager | str]):
|
||||||
if isinstance(ws, str):
|
if isinstance(ws, str):
|
||||||
ws = self.lookupId(ws)
|
ws = self.lookupId(ws)
|
||||||
|
|
||||||
|
@ -120,7 +119,7 @@ class WorkspaceRegistry():
|
||||||
del self._workspaces[ws]
|
del self._workspaces[ws]
|
||||||
|
|
||||||
|
|
||||||
|
workspaces = WorkspaceRegistry()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue