frobar: Gracefully handle zelbar exists

Before it would just spam logs with "Unknown command: "
This commit is contained in:
Geoffrey Frogeye 2025-12-17 10:01:57 +01:00
parent 356186de7c
commit 465c2347cb
2 changed files with 48 additions and 36 deletions

View file

@ -1,7 +1,7 @@
{
zelbarnixpkgs ? builtins.getFlake "github:wlcx/nixpkgs/zelbar",
# nixpkgs ? <nixpkgs>,
nixpkgs ? builtins.getFlake "nixpkgs/nixos-25.11",
nixpkgs ? <nixpkgs>,
# nixpkgs ? builtins.getFlake "nixpkgs/nixos-25.11",
pkgs ? import nixpkgs {
overlays = [
(self: super: {

View file

@ -4,7 +4,6 @@ import datetime
import enum
import logging
import signal
import sys
import typing
import gi
@ -361,39 +360,51 @@ class Screen(ComposableText):
self.output,
]
print(" ".join(cmd))
proc = await asyncio.create_subprocess_exec(
*cmd,
stdout=asyncio.subprocess.PIPE,
stdin=asyncio.subprocess.PIPE,
)
loop = asyncio.get_running_loop()
while True:
last_start_time = loop.time()
proc = await asyncio.create_subprocess_exec(
*cmd,
stdout=asyncio.subprocess.PIPE,
stdin=asyncio.subprocess.PIPE,
)
async def refresher() -> None:
assert proc.stdin
while True:
await self.refresh.wait()
self.refresh.clear()
markup = self.get_markup()
# sys.stdout.write(markup) # DEBUG
proc.stdin.write(markup.encode())
async def refresher(proc: asyncio.subprocess.Process) -> None:
assert proc.stdin
while proc.returncode is None:
markup = self.get_markup()
# sys.stdout.write(markup) # DEBUG
proc.stdin.write(markup.encode())
await self.refresh.wait()
self.refresh.clear()
async def action_handler() -> None:
assert proc.stdout
while True:
line = await proc.stdout.readline()
try:
command = line.decode().strip()
except UnicodeDecodeError:
# FIXME zelbar seems to have some memory issues
log.exception("Not unicode: %s", str(line))
continue
callback = self.actions.get(command)
if callback is None:
log.error("Unknown command: %s", command)
continue
callback()
async def action_handler(proc: asyncio.subprocess.Process) -> None:
assert proc.stdout
while proc.returncode is None:
line = await proc.stdout.readline()
try:
command = line.decode().strip()
except UnicodeDecodeError:
# TODO zelbar seems to have some memory issues
log.exception("Not unicode: %s", str(line))
continue
callback = self.actions.get(command)
if callback is None:
log.error("Unknown command: %s", command)
continue
callback()
self.bar.add_long_running_task(refresher())
self.bar.add_long_running_task(action_handler())
refresher_task = self.bar.add_long_running_task(refresher(proc))
action_handler_task = self.bar.add_long_running_task(action_handler(proc))
await proc.wait()
log.error("zelbar exited with code %d", proc.returncode)
refresher_task.cancel()
action_handler_task.cancel()
# Delay restart if it's been less than 5 seconds to prevent infinite loops
time_since_start = loop.time() - last_start_time
await asyncio.sleep(max(0, 5 - time_since_start))
def add_action(self, callback: typing.Callable) -> str:
command = f"com{self.actionIndex:x}"
@ -434,14 +445,15 @@ class Bar(ComposableText):
continue
Screen(parent=self, output=output.name)
def add_long_running_task(self, coro: typing.Coroutine) -> None:
def add_long_running_task(self, coro: typing.Coroutine) -> asyncio.Task:
task = self.taskGroup.create_task(coro)
self.longRunningTasks.append(task)
return task
async def run(self) -> None:
async with self.taskGroup:
for screen in self.children:
await screen.run()
self.add_long_running_task(screen.run())
for provider in self.providers:
self.add_long_running_task(provider.run())
@ -630,7 +642,7 @@ class PeriodicProvider(Provider):
while True:
# TODO Block bar update during the periodic update of the loops
loops = [provider.loop() for provider in providers]
asyncio.gather(*loops)
await asyncio.gather(*loops)
now = datetime.datetime.now(datetime.UTC)
# Hardcoded to 1 second... not sure if we want some more than that,