2024-02-21 23:59:49 +01:00
|
|
|
from __future__ import annotations
|
2024-08-24 18:45:42 +02:00
|
|
|
from typing import Optional
|
2024-08-23 20:59:06 +02:00
|
|
|
|
2023-08-17 18:39:47 +02:00
|
|
|
|
2024-02-23 13:25:01 +01:00
|
|
|
import sublime
|
2024-08-09 19:20:58 +02:00
|
|
|
import logging
|
2023-08-25 14:29:11 +02:00
|
|
|
|
2024-08-21 21:35:57 +02:00
|
|
|
import codemp
|
2024-08-09 15:54:12 +02:00
|
|
|
from Codemp.src import globals as g
|
|
|
|
from Codemp.src.workspace import VirtualWorkspace
|
2024-08-23 20:59:06 +02:00
|
|
|
from Codemp.src.buffers import VirtualBuffer
|
|
|
|
from Codemp.src.utils import bidict
|
2024-08-09 19:20:58 +02:00
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
2024-02-21 23:59:49 +01:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
# the client will be responsible to keep track of everything!
|
|
|
|
# it will need 3 bidirectional dictionaries and 2 normal ones
|
|
|
|
# normal: workspace_id -> VirtualWorkspaces
|
|
|
|
# normal: buffer_id -> VirtualBuffer
|
|
|
|
# bidir: VirtualBuffer <-> VirtualWorkspace
|
|
|
|
# bidir: VirtualBuffer <-> Sublime.View
|
|
|
|
# bidir: VirtualWorkspace <-> Sublime.Window
|
2024-02-21 23:59:49 +01:00
|
|
|
|
2024-08-21 21:35:57 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
class VirtualClient:
|
2024-08-04 19:57:59 +02:00
|
|
|
def __init__(self):
|
2024-08-23 20:59:06 +02:00
|
|
|
self.codemp: Optional[codemp.Client] = None
|
2024-08-21 21:35:57 +02:00
|
|
|
self.driver = codemp.init(lambda msg: logger.log(logger.level, msg), False)
|
2024-02-21 23:59:49 +01:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
# bookkeeping corner
|
2024-08-29 08:17:52 +02:00
|
|
|
self._id2buffer: dict[str, VirtualBuffer] = {}
|
|
|
|
self._id2workspace: dict[str, VirtualWorkspace] = {}
|
|
|
|
self._view2buff: dict[sublime.View, VirtualBuffer] = {}
|
|
|
|
|
|
|
|
self._buff2workspace: bidict[VirtualBuffer, VirtualWorkspace] = bidict()
|
|
|
|
self._workspace2window: bidict[VirtualWorkspace, sublime.Window] = bidict()
|
|
|
|
|
|
|
|
def dump(self):
|
|
|
|
logger.debug("CLIENT STATUS:")
|
|
|
|
logger.debug("WORKSPACES:")
|
|
|
|
logger.debug(f"{self._id2workspace}")
|
|
|
|
logger.debug(f"{self._workspace2window}")
|
|
|
|
logger.debug(f"{self._workspace2window.inverse}")
|
|
|
|
logger.debug(f"{self._buff2workspace}")
|
|
|
|
logger.debug(f"{self._buff2workspace.inverse}")
|
|
|
|
logger.debug("VIEWS")
|
|
|
|
logger.debug(f"{self._view2buff}")
|
|
|
|
logger.debug(f"{self._id2buffer}")
|
2024-08-21 21:35:57 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def valid_window(self, window: sublime.Window):
|
2024-08-29 08:17:52 +02:00
|
|
|
return window in self._workspace2window.inverse
|
2024-08-21 21:35:57 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def valid_workspace(self, workspace: VirtualWorkspace | str):
|
|
|
|
if isinstance(workspace, str):
|
2024-08-29 08:17:52 +02:00
|
|
|
return client._id2workspace.get(workspace) is not None
|
2024-08-21 21:35:57 +02:00
|
|
|
|
2024-08-29 08:17:52 +02:00
|
|
|
return workspace in self._workspace2window
|
2024-08-21 21:35:57 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def all_workspaces(
|
|
|
|
self, window: Optional[sublime.Window] = None
|
|
|
|
) -> list[VirtualWorkspace]:
|
|
|
|
if window is None:
|
2024-08-29 08:17:52 +02:00
|
|
|
return list(self._workspace2window.keys())
|
2024-08-23 20:59:06 +02:00
|
|
|
else:
|
2024-08-29 08:17:52 +02:00
|
|
|
return self._workspace2window.inverse.get(window, [])
|
2024-08-21 21:35:57 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def workspace_from_view(self, view: sublime.View) -> Optional[VirtualWorkspace]:
|
2024-08-29 08:17:52 +02:00
|
|
|
buff = self._view2buff.get(view, None)
|
|
|
|
return self._buff2workspace.get(buff, None)
|
2024-08-09 09:17:38 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def workspace_from_buffer(self, buff: VirtualBuffer) -> Optional[VirtualWorkspace]:
|
2024-08-29 08:17:52 +02:00
|
|
|
return self._buff2workspace.get(buff)
|
2024-08-09 09:17:38 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def workspace_from_id(self, id: str) -> Optional[VirtualWorkspace]:
|
2024-08-29 08:17:52 +02:00
|
|
|
return self._id2workspace.get(id)
|
2024-08-09 09:17:38 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def all_buffers(
|
|
|
|
self, workspace: Optional[VirtualWorkspace | str] = None
|
|
|
|
) -> list[VirtualBuffer]:
|
|
|
|
if workspace is None:
|
2024-08-29 08:17:52 +02:00
|
|
|
return list(self._buff2workspace.keys())
|
2024-08-23 20:59:06 +02:00
|
|
|
else:
|
|
|
|
if isinstance(workspace, str):
|
2024-08-29 08:17:52 +02:00
|
|
|
workspace = client._id2workspace[workspace]
|
|
|
|
return self._buff2workspace.inverse.get(workspace, [])
|
2024-08-09 09:17:38 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def buffer_from_view(self, view: sublime.View) -> Optional[VirtualBuffer]:
|
2024-08-29 08:17:52 +02:00
|
|
|
return self._view2buff.get(view)
|
2024-08-09 09:17:38 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def buffer_from_id(self, id: str) -> Optional[VirtualBuffer]:
|
2024-08-29 08:17:52 +02:00
|
|
|
return self._id2buffer.get(id)
|
2024-08-21 21:35:57 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def view_from_buffer(self, buff: VirtualBuffer) -> sublime.View:
|
|
|
|
return buff.view
|
2024-08-09 09:17:38 +02:00
|
|
|
|
2024-08-29 08:17:52 +02:00
|
|
|
def register_buffer(self, workspace: VirtualWorkspace, buffer: VirtualBuffer):
|
|
|
|
self._buff2workspace[buffer] = workspace
|
|
|
|
self._id2buffer[buffer.id] = buffer
|
|
|
|
self._view2buff[buffer.view] = buffer
|
|
|
|
|
|
|
|
def unregister_buffer(self, buffer: VirtualBuffer):
|
|
|
|
del self._buff2workspace[buffer]
|
|
|
|
del self._id2buffer[buffer.id]
|
|
|
|
del self._view2buff[buffer.view]
|
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def disconnect(self):
|
|
|
|
if self.codemp is None:
|
2024-08-04 19:57:59 +02:00
|
|
|
return
|
2024-08-23 20:59:06 +02:00
|
|
|
logger.info("disconnecting from the current client")
|
|
|
|
# for each workspace tell it to clean up after itself.
|
|
|
|
for vws in self.all_workspaces():
|
|
|
|
vws.cleanup()
|
|
|
|
self.codemp.leave_workspace(vws.id)
|
2024-08-04 19:57:59 +02:00
|
|
|
|
2024-08-29 08:17:52 +02:00
|
|
|
self._id2workspace.clear()
|
|
|
|
self._id2buffer.clear()
|
|
|
|
self._buff2workspace.clear()
|
|
|
|
self._view2buff.clear()
|
|
|
|
self._workspace2window.clear()
|
2024-08-23 20:59:06 +02:00
|
|
|
self.codemp = None
|
2024-08-04 19:57:59 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def connect(self, host: str, user: str, password: str):
|
|
|
|
if self.codemp is not None:
|
|
|
|
logger.info("Disconnecting from previous client.")
|
|
|
|
return self.disconnect()
|
2024-08-04 19:57:59 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
self.codemp = codemp.Client(host, user, password)
|
|
|
|
id = self.codemp.user_id()
|
|
|
|
logger.debug(f"Connected to '{host}' as user {user} (id: {id})")
|
2024-08-09 09:17:38 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def install_workspace(
|
|
|
|
self, workspace: codemp.Workspace, window: sublime.Window
|
|
|
|
) -> VirtualWorkspace:
|
|
|
|
# we pass the window as well so if the window changes in the mean
|
|
|
|
# time we have the correct one!
|
|
|
|
vws = VirtualWorkspace(workspace, window)
|
2024-08-29 08:17:52 +02:00
|
|
|
self._workspace2window[vws] = window
|
|
|
|
self._id2workspace[vws.id] = vws
|
2024-08-09 09:17:38 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
vws.install()
|
|
|
|
return vws
|
2024-08-04 19:57:59 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def uninstall_workspace(self, vws: VirtualWorkspace):
|
2024-08-29 08:17:52 +02:00
|
|
|
if vws not in self._workspace2window:
|
2024-08-23 20:59:06 +02:00
|
|
|
raise
|
|
|
|
|
|
|
|
logger.info(f"Uninstalling workspace '{vws.id}'...")
|
|
|
|
vws.cleanup()
|
2024-08-29 08:17:52 +02:00
|
|
|
del self._workspace2window[vws]
|
|
|
|
del self._id2workspace[vws.id]
|
|
|
|
buffers = self._buff2workspace.inverse[vws]
|
|
|
|
for vbuff in buffers:
|
|
|
|
self.unregister_buffer(vbuff)
|
|
|
|
# self._buff2workspace.inverse_del(vws) - if we delete all straight
|
|
|
|
# keys the last delete will remove also the empty key.
|
2024-08-04 19:57:59 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def workspaces_in_server(self):
|
|
|
|
return self.codemp.active_workspaces() if self.codemp else []
|
2024-08-04 19:57:59 +02:00
|
|
|
|
2024-08-23 20:59:06 +02:00
|
|
|
def user_id(self):
|
|
|
|
return self.codemp.user_id() if self.codemp else None
|
2024-02-21 23:59:49 +01:00
|
|
|
|
|
|
|
|
2024-08-04 19:57:59 +02:00
|
|
|
client = VirtualClient()
|