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
|
|
|
|
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-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
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
|
|
|
|
|
|
|
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-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):
|
|
|
|
assert client.codemp is not None
|
|
|
|
|
|
|
|
for vws in client.all_workspaces(window):
|
|
|
|
client.codemp.leave_workspace(vws.id)
|
|
|
|
client.uninstall_workspace(vws)
|
|
|
|
|
|
|
|
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):
|
|
|
|
return settings.get(g.CODEMP_BUFFER_TAG) is not None
|
|
|
|
|
|
|
|
@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())
|
|
|
|
|
|
|
|
vws = client.workspace_from_view(self.view)
|
|
|
|
vbuff = client.buffer_from_view(self.view)
|
|
|
|
if vws is None or vbuff is None:
|
|
|
|
logger.error("we couldn't find the matching buffer or workspace!")
|
|
|
|
return
|
|
|
|
|
|
|
|
logger.debug(f"selection modified! {vws.id}, {vbuff.id} - {start}, {end}")
|
|
|
|
vws.send_cursor(vbuff.id, start, end)
|
|
|
|
|
|
|
|
def on_activated(self):
|
|
|
|
global TEXT_LISTENER
|
|
|
|
logger.debug(f"'{self.view}' view activated!")
|
|
|
|
safe_listener_attach(TEXT_LISTENER, self.view.buffer()) # pyright: ignore
|
|
|
|
|
|
|
|
def on_deactivated(self):
|
|
|
|
global TEXT_LISTENER
|
|
|
|
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")
|
|
|
|
global TEXT_LISTENER
|
|
|
|
safe_listener_detach(TEXT_LISTENER) # pyright: ignore
|
|
|
|
|
|
|
|
vws = client.workspace_from_view(self.view)
|
|
|
|
vbuff = client.buffer_from_view(self.view)
|
|
|
|
if vws is None or vbuff is None:
|
|
|
|
logger.debug("no matching workspace or buffer.")
|
|
|
|
return
|
|
|
|
|
|
|
|
client.unregister_buffer(vbuff)
|
|
|
|
vws.uninstall_buffer(vbuff)
|
|
|
|
|
|
|
|
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")
|
|
|
|
|
|
|
|
|
|
|
|
class CodempClientTextChangeListener(sublime_plugin.TextChangeListener):
|
|
|
|
@classmethod
|
|
|
|
def is_applicable(cls, buffer): # pyright: ignore
|
|
|
|
# don't attach this event listener automatically
|
|
|
|
# we'll do it by hand with .attach(buffer).
|
|
|
|
return False
|
|
|
|
|
|
|
|
def on_text_changed(self, changes):
|
|
|
|
s = self.buffer.primary_view().settings()
|
|
|
|
if s.get(g.CODEMP_IGNORE_NEXT_TEXT_CHANGE, False):
|
|
|
|
logger.debug("Ignoring echoing back the change.")
|
|
|
|
s[g.CODEMP_IGNORE_NEXT_TEXT_CHANGE] = False
|
|
|
|
return
|
|
|
|
|
|
|
|
vbuff = client.buffer_from_view(self.buffer.primary_view())
|
|
|
|
if vbuff is not None:
|
|
|
|
logger.debug(f"local buffer change! {vbuff.id}")
|
|
|
|
vbuff.send_buffer_change(changes)
|
|
|
|
|
|
|
|
TEXT_LISTENER = CodempClientTextChangeListener()
|
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:'
|