From d409148404d987c38337704a5a5447ce920ce0df Mon Sep 17 00:00:00 2001 From: David Vazgenovich Shakaryan Date: Tue, 6 Feb 2024 02:53:03 -0800 Subject: split tags and window title into separate modules This is done using a shared herbstclient idler to which the separate modules can add listeners for specific hooks. --- panel.py | 127 ++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 90 insertions(+), 37 deletions(-) (limited to 'panel.py') diff --git a/panel.py b/panel.py index 9efef29..5ef9cbb 100755 --- a/panel.py +++ b/panel.py @@ -4,6 +4,7 @@ import glob import os +import queue import subprocess import threading import time @@ -79,14 +80,74 @@ class ModDate(Mod): self.tz = (self.tz + int(cmd[3:] or 1)) % len(self.tzs) self.e.set() -class ModHLWM(Mod): +class HLWMClient(): + def __init__(self): + self.t = None + self.lock = threading.Lock() + self.listeners = {} + + def run(self): + with self.lock: + if self.t is None: + self.t = threading.Thread(target=self.work, daemon=True) + self.t.start() + + def work(self): + p = subprocess.Popen( + ('herbstclient', '--idle'), + stdout=subprocess.PIPE, text=True) + + for line in iter(p.stdout.readline, ''): + for hook, arr in self.listeners.items(): + if line.startswith(hook): + for q, cb_index in arr: + q.put((cb_index, line)) + + def listen(self, hook, q, cb_index): + d = (q, cb_index) + if hook in self.listeners: + self.listeners[hook].append(d) + else: + self.listeners[hook] = [d] + + def exec(self, *args): + res = subprocess.run( + ('herbstclient', *args), + stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True) + return res.stdout.rstrip() + +class ModHLWMBase(Mod): + client = HLWMClient() + def __init__(self): super().__init__() - self.out_tags = None - self.out_title = None + self.q = queue.Queue() + self.cbs = [] + + def post_start(self): + pass + + def listen(self, hook, cb): + self.client.listen(hook, self.q, len(self.cbs)) + self.cbs.append(cb) - def flush(self): - self.out = f'{self.out_tags}{spacing()}{self.out_title}' + def work(self): + self.client.run() + self.post_start() + while True: + cb_index, line = self.q.get() + self.cbs[cb_index]() + + def hc(self, *args): + return self.client.exec(*args); + +class ModHLWMTags(ModHLWMBase): + def __init__(self): + super().__init__() + self.listen('tag_', self.refresh) + + def post_start(self): + self.refresh() def fmt_tag(self, sym, tag, tagstr): buf = f'%{{A:{id(self)} use {tag}:}}' @@ -108,49 +169,39 @@ class ModHLWM(Mod): buf += '%{A}' return buf - def refresh_tags(self): - res = subprocess.run( - ('herbstclient', 'tag_status'), - stdout=subprocess.PIPE, text=True) - tagstr = res.stdout.strip() - tags = tagstr.split('\t') + def refresh(self): + tagstr = self.hc('tag_status') + tags = tagstr.lstrip('\t').split('\t') buf = (f'%{{A4:{id(self)} use_index +1:}}' f'%{{A5:{id(self)} use_index -1:}}') for tag in tags: buf += self.fmt_tag(tag[0], tag[1:], tagstr) buf += '%{A}%{A}' - with self.cv: - self.out_tags = buf - self.flush() - self.cv.notify() - def refresh_title(self): - res = subprocess.run( - ('herbstclient', 'attr', 'clients.focus.title'), - stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, text=True) - title = res.stdout.strip() - buf = title if len(title) < 65 else title[0:63] + '…' with self.cv: - self.out_title = buf - self.flush() + self.out = buf self.cv.notify() - def work(self): - p = subprocess.Popen( - ('herbstclient', '--idle'), - stdout=subprocess.PIPE, text=True) - self.refresh_tags() - self.refresh_title() - for line in iter(p.stdout.readline, ''): - if line.startswith('tag_'): - self.refresh_tags() - elif (line.startswith('focus_changed') or - line.startswith('window_title_changed')): - self.refresh_title() - def process_cmd(self, cmd): subprocess.run(('herbstclient', *cmd.split())) +class ModHLWMTitle(ModHLWMBase): + def __init__(self): + super().__init__() + self.listen('focus_changed', self.refresh) + self.listen('window_title_changed', self.refresh) + + def post_start(self): + self.refresh() + + def refresh(self): + title = self.hc('attr', 'clients.focus.title') + buf = title if len(title) < 65 else title[0:63] + '…' + + with self.cv: + self.out = buf + self.cv.notify() + class ModInputUnavail(Mod): def __init__(self, path, label=''): super().__init__() @@ -241,7 +292,9 @@ class Bar: file=self.bar.stdin, flush=True) Bar( - ModHLWM(), + ModHLWMTags(), + ModSpacer(), + ModHLWMTitle(), ModRight(), ModInputUnavail( '/dev/input/by-id/usb-HID_Keyboard_HID_Keyboard-event-kbd', -- cgit v1.2.3-70-g09d2