Add text_command + refresh live-text keys

Introduce a per-key `text_command` + `refresh` feature: the service
periodically runs a shell command and renders its stdout as the key's
text overlay, compositing over the base icon (or a black background for
text-only keys) each tick. `text` acts as the static fallback shown
before the first run or when the command errors/outputs nothing. A
refresh goroutine owns the key's image and also handles an optional poll
block (choosing icon_true/icon_false per tick). Adds `$(...)` sugar in
`text` as shorthand for `text_command`.

- internal/config: add TextCommand/Refresh fields to KeyConfig
- cmd/streamdeck: refreshTextKey goroutine, runTextCommand, unwrapCmdSubst
- config.example.yaml: document the feature with a `flow` pomodoro
  live-countdown example (status --short, toggle/skip/stop/gui)
- modules.example.yaml: example config updates

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEoLyNbtbjbDq7aTWAymUG
This commit is contained in:
lwoodard
2026-08-07 13:23:43 -06:00
parent a542ad60cd
commit d1d5d88508
4 changed files with 235 additions and 6 deletions

View File

@@ -61,3 +61,48 @@ keys:
# command: pactl get-source-mute @DEFAULT_SOURCE@
# interval: 2s
# match: "yes"
# --- Dynamic text from command output ---
#
# text_command: a shell command whose stdout is rendered as the key's label,
# re-run every `refresh` interval (default 1s; floored to 250ms). Newlines
# in the output become label line breaks; trailing whitespace is trimmed.
# `text` (if set) is the static fallback shown before the first run or when
# the command errors / outputs nothing. Composited over `icon` each tick.
#
# NOTE: use the ABSOLUTE binary path — the service runs with a minimal PATH.
# Apple Silicon Homebrew installs may live at /opt/homebrew/bin/flow instead.
#
# Pomodoro (`flow`) live countdown — press toggles start/pause:
# 8:
# icon: pomodoro.png # base icon; text on top
# text_command: "/usr/local/bin/flow status --short" # prints e.g. WORK\n24:12 (real newline)
# refresh: 1s
# text_color: "#FFFFFF"
# command: "/usr/local/bin/flow toggle"
#
# Separate icon-swap indicator (running vs paused):
# 9:
# icon_true: running.png
# icon_false: paused.png
# command: "/usr/local/bin/flow toggle"
# poll:
# command: "/usr/local/bin/flow status" # prints: state=running phase=work remaining=24:12
# interval: 1s
# match: "state=running"
#
# Control keys:
# 10:
# icon: skip.png
# command: "/usr/local/bin/flow skip"
# 11:
# icon: stop.png
# command: "/usr/local/bin/flow stop"
# 12:
# icon: gui.png
# command: "/usr/local/bin/flow gui"
#
# A text-only live clock (no icon → white text on black), refreshed each second:
# 13:
# text_command: "date +%H:%M:%S"
# refresh: 1s