# pyright: reportIncompatibleMethodOverride=false import sublime import sublime_plugin import logging import codemp from .plugin.utils import is_codemp_buffer, safe_listener_detach from .plugin.utils import safe_listener_attach from .plugin.utils import some from .plugin.utils import is_codemp_buffer from .plugin.core.session import session from .plugin.core.workspace import workspaces from .plugin.core.buffers import buffers from .plugin.text_listener import TEXT_LISTENER from .plugin.input_handlers import SimpleListInput from .plugin import globals as g from .plugin.commands.client import * from .plugin.commands.workspace import * from .plugin.quickpanel.qpbrowser import QPServerBrowser from .plugin.quickpanel.qpbrowser import QPWorkspaceBrowser 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) version = codemp.version() logger.debug("plugin loaded - library version: {}".format(version)) 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() def buffid_from_view(view): if not is_codemp_buffer(view): raise ValueError("The view is not a Codemp Buffer.") buffid = str(view.settings().get(g.CODEMP_BUFFER_ID)) return buffid def vbuff_form_view(view): buffid = buffid_from_view(view) vbuff = buffers.lookupId(buffid) return vbuff def objects_from_view(view): vbuff = vbuff_form_view(view) vws = buffers.lookupParent(vbuff) win = workspaces.lookupParent(vws) return win, vws, vbuff class CodempBrowseWorkspaceCommand(sublime_plugin.WindowCommand): def is_enabled(self) -> bool: return len(workspaces.lookup(self.window)) > 0 def run(self, workspace_id): wks = workspaces.lookupId(workspace_id) buffers = wks.handle.fetch_buffers() QPWorkspaceBrowser(self.window, workspace_id, buffers.wait()).run() def input(self, args): if "workspace_id" not in args: wslist = session.client.active_workspaces() return SimpleListInput( ("workspace_id", wslist), ) class CodempBrowseServerCommand(sublime_plugin.WindowCommand): def is_enabled(self) -> bool: return session.is_active() def run(self): wks = session.get_workspaces() QPServerBrowser(self.window, session.config.host, wks).run() class CodempReplaceTextCommand(sublime_plugin.TextCommand): def run(self, edit, start, end, content, change_id = None): # we modify the region to account for any change that happened in the mean time region = sublime.Region(start, end) if change_id: region = self.view.transform_region_from(sublime.Region(start, end), change_id) self.view.replace(edit, region, content) class CodempSyncBuffer(sublime_plugin.TextCommand): def is_enabled(self) -> bool: return is_codemp_buffer(self.view) def run(self, edit): buff = vbuff_form_view(self.view) buff.sync(TEXT_LISTENER) class EventListener(sublime_plugin.EventListener): def is_enabled(self): return session.is_active() def on_exit(self): kill_all() def on_pre_close_window(self, window): for vws in workspaces.lookup(window): sublime.run_command("codemp_leave_workspace", { "workspace_id": vws.id }) 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_VIEW_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()) try: _, vws, vbuff = objects_from_view(self.view) except KeyError: logger.error(f"Could not find buffers associated with the view {self.view}.\ Removing the tag to disable event listener. Reattach.") # delete the tag so we disable this event listener on the view del self.view.settings()[g.CODEMP_VIEW_TAG] return vws.send_cursor(vbuff.id, start, end) # logger.debug(f"selection modified! {vws.id}, {vbuff.id} - {start}, {end}") def on_activated(self): logger.debug(f"'{self.view}' view activated!") safe_listener_detach(TEXT_LISTENER) 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 try: bid = buffid_from_view(self.view) some(self.view.window()).run_command( "codemp_leave_buffer", {"buffer_id": bid}) except KeyError: 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") # 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:'