codemp-sublime/main.py
cschen 539a4e4e5e wip: huge refactor with smarter and simpler struture
Former-commit-id: fbd0bca8094642dd8d2cf6c3f154af3b10dff95b
2024-09-18 17:42:56 +02:00

186 lines
6.5 KiB
Python

# pyright: reportIncompatibleMethodOverride=false
import sublime
import sublime_plugin
import logging
from lib 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.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
logger = logging.getLogger(__name__)
# Initialisation and Deinitialisation
##############################################################################
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)
class EventListener(sublime_plugin.EventListener):
def is_enabled(self):
return session.is_active()
def on_exit(self):
kill_all()
# client.disconnect()
# if client.driver is not None:
# client.driver.stop()
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()
# 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:'