2024-09-17 22:20:00 +02:00
|
|
|
# pyright: reportIncompatibleMethodOverride=false
|
2024-09-17 16:23:19 +02:00
|
|
|
import sublime
|
|
|
|
import sublime_plugin
|
|
|
|
import logging
|
|
|
|
|
2024-09-28 19:55:20 +02:00
|
|
|
import codemp
|
2024-09-17 22:20:00 +02:00
|
|
|
from .plugin.utils import safe_listener_detach
|
2024-11-03 17:57:31 +01:00
|
|
|
from .plugin.utils import safe_listener_attach
|
2024-11-03 17:59:17 +01:00
|
|
|
from .plugin.utils import some
|
2024-09-17 22:20:00 +02:00
|
|
|
from .plugin.core.session import session
|
2024-09-28 19:55:20 +02:00
|
|
|
from .plugin.core.workspace import workspaces
|
|
|
|
from .plugin.core.buffers import buffers
|
2024-11-03 17:57:31 +01:00
|
|
|
from .plugin.text_listener import TEXT_LISTENER
|
|
|
|
from .plugin import globals as g
|
2024-09-17 22:20:00 +02:00
|
|
|
|
2024-11-03 17:57:31 +01:00
|
|
|
# We import these just to showcase the commands available.
|
2024-09-17 22:20:00 +02:00
|
|
|
from .plugin.commands.client import CodempConnectCommand
|
|
|
|
from .plugin.commands.client import CodempDisconnectCommand
|
|
|
|
from .plugin.commands.client import CodempCreateWorkspaceCommand
|
|
|
|
from .plugin.commands.client import CodempDeleteWorkspaceCommand
|
|
|
|
from .plugin.commands.client import CodempJoinWorkspaceCommand
|
|
|
|
from .plugin.commands.client import CodempLeaveWorkspaceCommand
|
|
|
|
from .plugin.commands.client import CodempInviteToWorkspaceCommand
|
|
|
|
|
|
|
|
from .plugin.commands.workspace import CodempCreateBufferCommand
|
|
|
|
from .plugin.commands.workspace import CodempDeleteBufferCommand
|
|
|
|
from .plugin.commands.workspace import CodempJoinBufferCommand
|
|
|
|
from .plugin.commands.workspace import CodempLeaveBufferCommand
|
|
|
|
|
2024-11-03 17:57:31 +01:00
|
|
|
from .plugin.quickpanel.qpbrowser import QPServerBrowser
|
|
|
|
from .plugin.quickpanel.qpbrowser import QPWorkspaceBrowser
|
|
|
|
|
|
|
|
|
2024-09-17 22:20:00 +02:00
|
|
|
LOG_LEVEL = logging.DEBUG
|
|
|
|
handler = logging.StreamHandler()
|
|
|
|
handler.setFormatter(
|
|
|
|
logging.Formatter(
|
|
|
|
fmt="<{thread}/{threadName}> {levelname} [{name} :: {funcName}] {message}",
|
|
|
|
style="{",
|
|
|
|
)
|
|
|
|
)
|
|
|
|
package_logger = logging.getLogger(__package__)
|
|
|
|
package_logger.setLevel(LOG_LEVEL)
|
|
|
|
package_logger.propagate = False
|
2024-09-17 16:23:19 +02:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2024-09-17 22:20:00 +02:00
|
|
|
# Initialisation and Deinitialisation
|
2024-09-17 16:23:19 +02:00
|
|
|
##############################################################################
|
2024-09-17 22:20:00 +02:00
|
|
|
def plugin_loaded():
|
|
|
|
package_logger.addHandler(handler)
|
|
|
|
logger.debug("plugin loaded")
|
|
|
|
|
|
|
|
def plugin_unloaded():
|
|
|
|
logger.debug("unloading")
|
|
|
|
safe_listener_detach(TEXT_LISTENER)
|
|
|
|
package_logger.removeHandler(handler)
|
|
|
|
|
|
|
|
|
|
|
|
def kill_all():
|
|
|
|
for ws in workspaces.lookup():
|
|
|
|
session.client.leave_workspace(ws.id)
|
|
|
|
workspaces.remove(ws)
|
|
|
|
|
|
|
|
session.stop()
|
|
|
|
|
2024-11-03 17:57:31 +01:00
|
|
|
def objects_from_view(view):
|
|
|
|
assert view.settings().get(g.CODEMP_VIEW_TAG, False)
|
|
|
|
buffid = str(view.settings().get(g.CODEMP_BUFFER_ID))
|
|
|
|
|
2024-11-03 17:59:17 +01:00
|
|
|
vbuff = buffers.lookupId(buffid)
|
2024-11-03 17:57:31 +01:00
|
|
|
|
|
|
|
vws = buffers.lookupParent(vbuff)
|
|
|
|
win = workspaces.lookupParent(vws)
|
|
|
|
|
|
|
|
return win, vws, vbuff
|
|
|
|
|
|
|
|
class CodempBrowseWorkspaceCommand(sublime_plugin.WindowCommand):
|
|
|
|
def is_enabled(self) -> bool:
|
|
|
|
return session.is_active()
|
|
|
|
|
|
|
|
def run(self, workspace_id):
|
|
|
|
wks = workspaces.lookupId(workspace_id)
|
|
|
|
buffers = wks.handle.fetch_buffers()
|
|
|
|
QPWorkspaceBrowser(self.window, workspace_id, buffers.wait()).run()
|
|
|
|
|
|
|
|
|
|
|
|
class CodempBrowseServerCommand(sublime_plugin.WindowCommand):
|
|
|
|
def is_enabled(self) -> bool:
|
|
|
|
return session.is_active()
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
wks = session.get_workspaces()
|
2024-11-03 17:59:17 +01:00
|
|
|
QPServerBrowser(self.window, session.config.host, wks).run()
|
2024-11-03 17:57:31 +01:00
|
|
|
|
2024-09-17 22:20:00 +02:00
|
|
|
|
|
|
|
class CodempReplaceTextCommand(sublime_plugin.TextCommand):
|
|
|
|
def run(self, edit, start, end, content, change_id):
|
|
|
|
# we modify the region to account for any change that happened in the mean time
|
|
|
|
region = self.view.transform_region_from(sublime.Region(start, end), change_id)
|
|
|
|
self.view.replace(edit, region, content)
|
|
|
|
|
|
|
|
|
2024-11-19 19:46:44 +01:00
|
|
|
class CodempSyncBuffer(sublime_plugin.TextCommand):
|
|
|
|
def run(self, edit):
|
|
|
|
buff = buffers.lookupId(self.view.settings().get(g.CODEMP_BUFFER_ID))
|
|
|
|
buff.sync(TEXT_LISTENER)
|
|
|
|
|
|
|
|
|
2024-09-17 16:23:19 +02:00
|
|
|
class EventListener(sublime_plugin.EventListener):
|
|
|
|
def is_enabled(self):
|
2024-09-17 22:20:00 +02:00
|
|
|
return session.is_active()
|
2024-09-17 16:23:19 +02:00
|
|
|
|
|
|
|
def on_exit(self):
|
2024-09-17 22:20:00 +02:00
|
|
|
kill_all()
|
|
|
|
# client.disconnect()
|
|
|
|
# if client.driver is not None:
|
|
|
|
# client.driver.stop()
|
2024-09-17 16:23:19 +02:00
|
|
|
|
|
|
|
def on_pre_close_window(self, window):
|
2024-11-02 18:26:37 +01:00
|
|
|
for vws in workspaces.lookup(window):
|
|
|
|
sublime.run_command("codemp_leave_workspace", {
|
|
|
|
"workspace_id": vws.id
|
|
|
|
})
|
2024-09-17 16:23:19 +02:00
|
|
|
|
|
|
|
def on_text_command(self, view, command_name, args):
|
|
|
|
if command_name == "codemp_replace_text":
|
|
|
|
logger.info("got a codemp_replace_text command!")
|
|
|
|
|
|
|
|
def on_post_text_command(self, view, command_name, args):
|
|
|
|
if command_name == "codemp_replace_text":
|
|
|
|
logger.info("got a codemp_replace_text command!")
|
|
|
|
|
|
|
|
|
|
|
|
class CodempClientViewEventListener(sublime_plugin.ViewEventListener):
|
|
|
|
@classmethod
|
|
|
|
def is_applicable(cls, settings):
|
2024-11-02 18:26:37 +01:00
|
|
|
return settings.get(g.CODEMP_VIEW_TAG) is not None
|
2024-09-17 16:23:19 +02:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def applies_to_primary_view_only(cls):
|
|
|
|
return False
|
|
|
|
|
|
|
|
def on_selection_modified_async(self):
|
|
|
|
region = self.view.sel()[0]
|
|
|
|
start = self.view.rowcol(region.begin())
|
|
|
|
end = self.view.rowcol(region.end())
|
|
|
|
|
2024-11-02 18:26:37 +01:00
|
|
|
try:
|
|
|
|
_, vws, vbuff = objects_from_view(self.view)
|
2024-11-03 17:59:17 +01:00
|
|
|
except KeyError:
|
2024-11-02 18:26:37 +01:00
|
|
|
logger.error(f"Could not find buffers associated with the view {self.view}.\
|
2024-11-03 17:59:17 +01:00
|
|
|
Removing the tag to disable event listener. Reattach.")
|
2024-11-02 18:26:37 +01:00
|
|
|
# delete the tag so we disable this event listener on the view
|
|
|
|
del self.view.settings()[g.CODEMP_VIEW_TAG]
|
2024-09-17 16:23:19 +02:00
|
|
|
return
|
|
|
|
|
|
|
|
vws.send_cursor(vbuff.id, start, end)
|
2024-11-02 18:26:37 +01:00
|
|
|
logger.debug(f"selection modified! {vws.id}, {vbuff.id} - {start}, {end}")
|
2024-09-17 16:23:19 +02:00
|
|
|
|
|
|
|
def on_activated(self):
|
|
|
|
logger.debug(f"'{self.view}' view activated!")
|
|
|
|
safe_listener_attach(TEXT_LISTENER, self.view.buffer()) # pyright: ignore
|
|
|
|
|
|
|
|
def on_deactivated(self):
|
|
|
|
logger.debug(f"'{self.view}' view deactivated!")
|
|
|
|
safe_listener_detach(TEXT_LISTENER) # pyright: ignore
|
|
|
|
|
|
|
|
def on_pre_close(self):
|
|
|
|
if self.view == sublime.active_window().active_view():
|
|
|
|
logger.debug("closing active view")
|
|
|
|
safe_listener_detach(TEXT_LISTENER) # pyright: ignore
|
2024-11-02 18:26:37 +01:00
|
|
|
try:
|
2024-11-03 17:59:17 +01:00
|
|
|
bid = str(self.view.settings().get(g.CODEMP_BUFFER_ID))
|
|
|
|
vws = buffers.lookupParent(bid)
|
|
|
|
some(self.view.window()).run_command(
|
|
|
|
"codemp_leave_buffer",
|
|
|
|
{"workspace_id": vws.id, "buffer_id": bid})
|
|
|
|
except KeyError:
|
2024-09-17 16:23:19 +02:00
|
|
|
return
|
|
|
|
|
|
|
|
def on_text_command(self, command_name, args):
|
|
|
|
if command_name == "codemp_replace_text":
|
|
|
|
logger.info("got a codemp_replace_text command! but in the view listener")
|
|
|
|
|
|
|
|
def on_post_text_command(self, command_name, args):
|
|
|
|
if command_name == "codemp_replace_text":
|
|
|
|
logger.info("got a codemp_replace_text command! but in the view listener")
|
|
|
|
|
|
|
|
|
2024-11-02 18:26:37 +01:00
|
|
|
# Next TODO:
|
|
|
|
# Server configurations:
|
|
|
|
# - where do we store it?
|
|
|
|
# - TOML? yes probably toml
|
2024-09-17 22:20:00 +02:00
|
|
|
|
2024-11-02 18:26:37 +01:00
|
|
|
# * Quickpanel for connecting with stuff.
|
|
|
|
# * Quickpanel for browsing the servers
|
|
|
|
# * Move all "server actions" like, create, delete, rename etc. as quickpanel actions. (See SFTP plugin.)
|
|
|
|
# * make panel for notifications!
|
|
|
|
# * make panel for errors and logging!
|
2024-09-17 22:20:00 +02:00
|
|
|
|
|
|
|
# Proxy Commands ( NOT USED, left just in case we need it again. )
|
|
|
|
#############################################################################
|
|
|
|
# class ProxyCodempShareCommand(sublime_plugin.WindowCommand):
|
|
|
|
# # on_window_command, does not trigger when called from the command palette
|
|
|
|
# # See: https://github.com/sublimehq/sublime_text/issues/2234
|
|
|
|
# def run(self, **kwargs):
|
|
|
|
# self.window.run_command("codemp_share", kwargs)
|
|
|
|
#
|
|
|
|
# def input(self, args):
|
|
|
|
# if 'sublime_buffer' not in args:
|
|
|
|
# return SublimeBufferPathInputHandler()
|
|
|
|
#
|
|
|
|
# def input_description(self):
|
|
|
|
# return 'Share Buffer:'
|
2024-11-02 18:26:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|