diff --git a/doc/source/plugins/index.rst b/doc/source/plugins/index.rst index 0b30a331..d1f021de 100644 --- a/doc/source/plugins/index.rst +++ b/doc/source/plugins/index.rst @@ -163,7 +163,7 @@ Plugin index Screen Detach :ref:`Documentation ` - Changes your status to **away** if the screen poezio is in is detached. + Changes your status to **away** if the screen (or tmux) poezio is in gets detached. Send Delayed :ref:`Documentation ` diff --git a/doc/stub/pyinotify.py b/doc/stub/pyinotify.py index 48721264..1f8fc574 100644 --- a/doc/stub/pyinotify.py +++ b/doc/stub/pyinotify.py @@ -1,3 +1,5 @@ +class Notifier: + pass class WatchManager: pass class EventsCodes: diff --git a/plugins/screen_detach.py b/plugins/screen_detach.py index 53827c11..96339e9b 100644 --- a/plugins/screen_detach.py +++ b/plugins/screen_detach.py @@ -1,35 +1,85 @@ """ This plugin will set your status to **away** if you detach your screen. +The default behaviour is to check for both tmux and screen (in that order). + +Configuration options +--------------------- + +.. glossary:: + + use_screen + **Default:** ``true`` + + Try to find an attached screen. + + use_tmux + **Default:** ``true`` + + Try to find and attached tmux. + """ + from plugin import BasePlugin import os import stat import pyinotify +import asyncio + +DEFAULT_CONFIG = { + 'screen_detach': { + 'use_tmux': True, + 'use_screen': True + } +} + + +# overload if this is not how your stuff +# is configured +try: + LOGIN = os.getlogin() + LOGIN_TMUX = LOGIN +except Exception: + LOGIN = os.getenv('USER') + LOGIN_TMUX = os.getuid() + +SCREEN_DIR = '/var/run/screen/S-%s' % LOGIN +TMUX_DIR = '/tmp/tmux-%s' % LOGIN_TMUX + +def find_screen(path): + for f in os.listdir(path): + path = os.path.join(path, f) + if screen_attached(path): + return path + +def screen_attached(socket): + return (os.stat(socket).st_mode & stat.S_IXUSR) != 0 + +class Plugin(BasePlugin, pyinotify.Notifier): + + default_config = DEFAULT_CONFIG -class Plugin(BasePlugin): def init(self): - screen_dir = '/var/run/screen/S-%s' % (os.getlogin(),) - self.timed_event = None sock_path = None - self.thread = None - for f in os.listdir(screen_dir): - path = os.path.join(screen_dir, f) - if screen_attached(path): - sock_path = path - self.attached = True - break + if self.config.get('use_tmux'): + sock_path = find_screen(TMUX_DIR) + if sock_path is None and config.get('use_screen'): + sock_path = find_screen(SCREEN_DIR) # Only actually do something if we found an attached screen (assuming only one) if sock_path: + self.attached = True wm = pyinotify.WatchManager() wm.add_watch(sock_path, pyinotify.EventsCodes.ALL_FLAGS['IN_ATTRIB']) - self.thread = pyinotify.ThreadedNotifier(wm, default_proc_fun=HandleScreen(plugin=self)) - self.thread.start() + pyinotify.Notifier.__init__(self, wm, default_proc_fun=HandleScreen(plugin=self)) + asyncio.get_event_loop().add_reader(self._fd, self.process) + + def process(self): + self.read_events() + self.process_events() def cleanup(self): - if self.thread: - self.thread.stop() + asyncio.get_event_loop().remove_reader(self._fd) def update_screen_state(self, socket): attached = screen_attached(socket) @@ -38,8 +88,6 @@ class Plugin(BasePlugin): status = 'available' if self.attached else 'away' self.core.command_status(status) -def screen_attached(socket): - return (os.stat(socket).st_mode & stat.S_IXUSR) != 0 class HandleScreen(pyinotify.ProcessEvent): def my_init(self, **kwargs):