#! /bin/bash # One dot per defined VM, coloured by state. # Copyright (C) 2026 Danilo M. # Licensed under the GNU General Public License v2 only. # # dependencies: libvirt (virsh), jq # # The colours come from the palette, not from here: install.sh writes # ~/.config/waybar-udt/dots.colors from the selected udt scheme, and this # sources it. The defaults below are only what a missing file falls back to, # so the bar still draws if the theme has not been installed yet. set -euo pipefail JQ_BIN="${JQ:-jq}" # Palette. Sourced, with fallbacks, so this script works standalone. DOT_SUCCESS="#a6da95" DOT_WARNING="#eed49f" DOT_CRITICAL="#ed8796" DOT_INFO="#8bd5ca" DOT_ACCENT="#b7bdf8" DOT_FAINT="#6e738d" colors="$HOME/.config/waybar-udt/dots.colors" # shellcheck source=/dev/null [[ -r "$colors" ]] && . "$colors" # Require virsh if ! command -v virsh >/dev/null 2>&1; then $JQ_BIN -cn '{text: "", tooltip: "virsh not found", class: "vmdot"}' exit 0 fi # Collect all defined VMs and their states. # virsh list --all columns: Id Name State (state may be multi-word, e.g. "shut off") declare -A vm_states while IFS= read -r line; do # Skip header lines and separator lines [[ "$line" =~ ^[[:space:]]*Id[[:space:]] ]] && continue [[ "$line" =~ ^[-[:space:]]+$ ]] && continue [[ -z "${line// }" ]] && continue # Fields: id (may be "-"), name, state (rest of line) read -r _id name state_rest <<< "$line" vm_states["$name"]="$state_rest" done < <(virsh list --all 2>/dev/null) if [[ ${#vm_states[@]} -eq 0 ]]; then $JQ_BIN -cn '{text: "", tooltip: "No VMs defined", class: "vmdot"}' exit 0 fi # libvirt state → palette role. declare -A state_color=( ["running"]="$DOT_SUCCESS" ["idle"]="$DOT_WARNING" # running but idle ["paused"]="$DOT_WARNING" ["pmsuspended"]="$DOT_ACCENT" # PM sleep / ACPI S3 ["saved"]="$DOT_INFO" # managed save ["crashed"]="$DOT_CRITICAL" ["shut off"]="$DOT_FAINT" ) fallback_color="$DOT_FAINT" # any unknown future state dots=() tooltip_parts=() classes="vmdot" # Sort VM names for stable ordering mapfile -t sorted_names < <(printf '%s\n' "${!vm_states[@]}" | sort) for name in "${sorted_names[@]}"; do state="${vm_states[$name]}" color="${state_color[$state]:-$fallback_color}" # Derive a CSS-safe class token (spaces → hyphens) state_class="${state// /-}" dots+=("") classes="$classes vm-${state_class}" tooltip_parts+=("${name}: ${state}") done text="${dots[*]}" tooltip="$(IFS=' | '; echo "${tooltip_parts[*]}")" $JQ_BIN -cn \ --arg text "$text" \ --arg tooltip "$tooltip" \ --arg class "$classes" \ '{text: $text, tooltip: $tooltip, class: $class}'