diff options
author | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2024-02-18 22:01:58 -0800 |
---|---|---|
committer | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2024-02-18 22:01:58 -0800 |
commit | 61263de56df6872bf85346f05d425bf640da6571 (patch) | |
tree | f9f020894eaf7d2a4d232277f40b156003511626 | |
parent | d409148404d987c38337704a5a5447ce920ce0df (diff) | |
download | panel-61263de56df6872bf85346f05d425bf640da6571.tar.gz panel-61263de56df6872bf85346f05d425bf640da6571.tar.xz |
abstract out formatting and other cleanup
-rwxr-xr-x | panel.py | 141 |
1 files changed, 81 insertions, 60 deletions
@@ -2,32 +2,62 @@ # # Copyright 2024 David Vazgenovich Shakaryan -import glob import os import queue import subprocess import threading -import time -from datetime import datetime, timezone +from datetime import datetime from zoneinfo import ZoneInfo -def fmt_label(s): - return f'%{{F#7b51ca}}{s}%{{F-}}' +class Fmt: + @classmethod + def fg(cls, col, s): + return f'%{{F{col}}}{s}%{{F-}}' -def spacing(n = 1): - return f'%{{O{n * 7}}}' + @classmethod + def bg(cls, col, s): + return f'%{{B{col}}}{s}%{{B-}}' + + @classmethod + def ul(cls, col, s): + return f'%{{U{col}}}%{{+u}}{s}%{{-u}}%{{U-}}' + + @classmethod + def bold(cls, s): + return f'%{{T2}}{s}%{{T-}}' + + @classmethod + def label(cls, s): + return cls.fg('#7b51ca', s) + + @classmethod + def spacer(cls, n=1): + return f'%{{O{n * 7}}}' + + @classmethod + def pad(cls, s, n=1): + sp = cls.spacer(n) + return f'{sp}{s}{sp}' + + @classmethod + def clickable(cls, btn, cmd, s): + return f'%{{A{btn}:{cmd}:}}{s}%{{A}}' class Mod: def __init__(self): - self.cv = None - self.t = None + self.e_repaint = None + + # changes should be applied atomically, as the main thread may read + # this at any time. self.out = None + def repaint(self): + self.e_repaint.set() + def run(self): if callable(getattr(self, 'work', None)): - self.t = threading.Thread(target=self.work, daemon=True) - self.t.start() + threading.Thread(target=self.work, daemon=True).start() def process_cmd(self, cmd): pass @@ -38,7 +68,7 @@ class ModRight(Mod): class ModSpacer(Mod): def __init__(self, n=1): - self.out = spacing(n) + self.out = Fmt.spacer(n) class ModDate(Mod): def __init__(self, fmts=None, tzs=None): @@ -60,14 +90,15 @@ class ModDate(Mod): dt = datetime.now().astimezone(ZoneInfo(tz_id) if tz_id else None) label = tz_label or dt.strftime('%Z') - buf = (f'%{{A4:{id(self)} tz +1:}}%{{A5:{id(self)} tz -1:}}' - f'%{{A:{id(self)} tz:}}{fmt_label(label)}%{{A}}{spacing()}' - f'%{{A:{id(self)} fmt:}}{dt.strftime(fmt)}%{{A}}' - '%{A}%{A}') - - with self.cv: - self.out = buf - self.cv.notify() + self.out = Fmt.clickable( + 4, f'{id(self)} tz +1', + Fmt.clickable( + 5, f'{id(self)} tz -1', + Fmt.clickable('', f'{id(self)} tz', Fmt.label(label)) + + Fmt.spacer() + + Fmt.clickable( + '', f'{id(self)} fmt', dt.strftime(fmt)))) + self.repaint() self.e.wait(1 - (dt.microsecond / 1000000)) self.e.clear() @@ -150,37 +181,33 @@ class ModHLWMTags(ModHLWMBase): self.refresh() def fmt_tag(self, sym, tag, tagstr): - buf = f'%{{A:{id(self)} use {tag}:}}' + disp = Fmt.pad(tag) match sym: case '.': - buf += f'%{{F#777777}}%{{O7}}{tag}%{{O7}}%{{F-}}' + buf = Fmt.fg('#777777', disp) case '#': - buf += (f'%{{B#333333}}%{{U#7b51ca}}%{{+u}}%{{O7}}%{{T2}}' - f'{tag}%{{T-}}%{{O7}}%{{-u}}%{{U-}}%{{B-}}') + buf = Fmt.bg('#333333', Fmt.ul('#7b51ca', Fmt.bold(disp))) case '!': if '#' in tagstr: - buf += (f'%{{B#a03000}}%{{U#000000}}%{{+u}}%{{O7}}' - f'{tag}%{{O7}}%{{-u}}%{{U-}}%{{B-}}') + buf = Fmt.bg('#a03000', Fmt.ul('#000000', disp)) else: - buf += (f'%{{B#a03000}}%{{U#7b51ca}}%{{+u}}%{{O7}}%{{T2}}' - f'{tag}%{{T-}}%{{O7}}%{{-u}}%{{U-}}%{{B-}}') + buf = Fmt.bg('#a03000', Fmt.ul('#7b51ca', Fmt.bold(disp))) case ':': - buf += f'%{{O7}}{tag}%{{O7}}' - buf += '%{A}' - return buf + buf = disp + + return Fmt.clickable('', f'{id(self)} use {tag}', buf) 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 = buf - self.cv.notify() + self.out = Fmt.clickable( + 4, f'{id(self)} use_index +1', + Fmt.clickable( + 5, f'{id(self)} use_index -1', + ''.join( + self.fmt_tag(tag[0], tag[1:], tagstr) for tag in tags))) + self.repaint() def process_cmd(self, cmd): subprocess.run(('herbstclient', *cmd.split())) @@ -196,11 +223,8 @@ class ModHLWMTitle(ModHLWMBase): 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() + self.out = title if len(title) < 65 else title[0:63] + '…' + self.repaint() class ModInputUnavail(Mod): def __init__(self, path, label=''): @@ -241,20 +265,17 @@ class ModInputUnavail(Mod): def _update_state(self, avail): if avail: - buf = None + self.out = None else: - buf = f'%{{B#a03000}}{spacing()}{self.label}{spacing()}%{{B-}}' - - with self.cv: - self.out = buf - self.cv.notify() + self.out = Fmt.bg('#a03000', Fmt.pad(self.label)) + self.repaint() -class Bar: +class Panel: def __init__(self, *mods): - self.cv = threading.Condition() + self.e_repaint = threading.Event() self.mods = mods for m in self.mods: - m.cv = self.cv + m.e_repaint = self.e_repaint self.mod_by_id = {id(m): m for m in self.mods} def process_cmds(self, pipe): @@ -270,7 +291,7 @@ class Bar: for mod in self.mods: mod.run() - self.bar = subprocess.Popen( + self.panel = subprocess.Popen( ('/home/david/lemonbar-xft/lemonbar', '-bf', 'Monospace:size=10:dpi=96', '-f', 'Monospace:size=10:dpi=96:bold', @@ -281,17 +302,17 @@ class Bar: threading.Thread( target=self.process_cmds, - args=(self.bar.stdout,), + args=(self.panel.stdout,), daemon=True ).start() while True: - with self.cv: - self.cv.wait() + self.e_repaint.wait() + self.e_repaint.clear() print(''.join([m.out for m in self.mods if m.out]), - file=self.bar.stdin, flush=True) + file=self.panel.stdin, flush=True) -Bar( +Panel( ModHLWMTags(), ModSpacer(), ModHLWMTitle(), @@ -299,7 +320,7 @@ Bar( ModInputUnavail( '/dev/input/by-id/usb-HID_Keyboard_HID_Keyboard-event-kbd', label='NO KEYBOARD'), - ModSpacer(n=2), + ModSpacer(2), ModDate( fmts=('%Y-%m-%d %H:%M:%S', '%H:%M'), tzs=({'id': None}, {'id': 'UTC'}, |