#!/usr/bin/env bash set -euo pipefail kind="${1:-}" iface="${POLYBAR_NETWORK:-eth0}" profile="${WG_QUICK_PROFILE:-PC}" state_dir="${XDG_RUNTIME_DIR:-/tmp}" if [ ! -w "$state_dir" ]; then state_dir="${XDG_CACHE_HOME:-$HOME/.cache}" mkdir -p "$state_dir" 2>/dev/null || true fi if [ ! -w "$state_dir" ]; then state_dir="/tmp" fi human_bytes() { local bytes="$1" if [ "$bytes" -ge 1048576 ]; then awk -v v="$bytes" 'BEGIN { printf "%.1fM", v / 1048576 }' elif [ "$bytes" -ge 1024 ]; then awk -v v="$bytes" 'BEGIN { printf "%.0fK", v / 1024 }' else printf '%sB' "$bytes" fi } case "$kind" in awake) [ -f "$state_dir/polybar-awake.state" ] && echo on || echo off ;; cpu) state_file="$state_dir/quickshell-cpu.state" read -r cpu user nice system idle iowait irq softirq steal _ "$state_file" diff_total=$((total - old_total)) diff_idle=$((idle_all - old_idle)) if [ "$diff_total" -le 0 ]; then echo 0% else echo "$(((100 * (diff_total - diff_idle)) / diff_total))%" fi ;; date) date '+%a %d %b %H:%M' ;; disk) df -P / | awk 'NR == 2 { print $5 }' ;; display) [ -f "$state_dir/polybar-display-night.state" ] && echo night || echo day ;; dunst) if ! command -v dunstctl >/dev/null 2>&1; then echo off elif [ "$(dunstctl is-paused 2>/dev/null || echo false)" = true ]; then waiting="$(dunstctl count waiting 2>/dev/null || echo 0)" [ "$waiting" -gt 0 ] 2>/dev/null && echo "dnd $waiting" || echo dnd else echo on fi ;; keyboard) export DISPLAY="${DISPLAY:-:0}" if [ -z "${XAUTHORITY:-}" ] && [ -r "$HOME/.Xauthority" ]; then export XAUTHORITY="$HOME/.Xauthority" fi query="$(setxkbmap -query 2>/dev/null || true)" layout="$(printf '%s\n' "$query" | awk '/^layout:/ { print $2; exit }')" variant="$(printf '%s\n' "$query" | awk '/^variant:/ { print $2; exit }')" case "${layout:-unknown}:${variant:-}" in us:dvorak) echo "us dv" ;; cz:*|cz:) echo cz ;; *:) echo "${layout:-unknown}" ;; *) echo "${layout:-unknown} ${variant}" ;; esac ;; mem) awk ' /MemTotal:/ { total = $2 } /MemAvailable:/ { avail = $2 } END { if (total > 0) printf "%d%%\n", ((total - avail) * 100) / total; else print "n/a" } ' /proc/meminfo ;; mic) if ! command -v pactl >/dev/null 2>&1; then echo n/a else mute="$(pactl get-source-mute @DEFAULT_SOURCE@ 2>/dev/null | awk '{ print $2 }' || true)" [ "$mute" = yes ] && echo muted || echo on fi ;; music) if ! command -v playerctl >/dev/null 2>&1; then echo n/a exit 0 fi status="$(playerctl status 2>/dev/null || true)" [ -n "$status" ] || { echo off; exit 0; } artist="$(playerctl metadata artist 2>/dev/null || true)" title="$(playerctl metadata title 2>/dev/null || true)" if [ -n "$artist" ] && [ -n "$title" ]; then printf '%s - %s\n' "$artist" "$title" | cut -c 1-34 elif [ -n "$title" ]; then printf '%s\n' "$title" | cut -c 1-34 else echo "$status" fi ;; net) ip -o -4 addr show "$iface" 2>/dev/null | awk '{ split($4, ip, "/"); print ip[1]; found = 1; exit } END { if (!found) print "offline" }' ;; netspeed) rx_file="/sys/class/net/$iface/statistics/rx_bytes" tx_file="/sys/class/net/$iface/statistics/tx_bytes" state_file="$state_dir/quickshell-net-${iface}.state" if [ ! -r "$rx_file" ] || [ ! -r "$tx_file" ]; then echo n/a exit 0 fi now="$(date +%s)" rx="$(cat "$rx_file")" tx="$(cat "$tx_file")" if [ -r "$state_file" ]; then read -r old_now old_rx old_tx <"$state_file" || true else old_now="$now" old_rx="$rx" old_tx="$tx" fi printf '%s %s %s\n' "$now" "$rx" "$tx" >"$state_file" delta=$((now - old_now)) [ "$delta" -gt 0 ] || delta=1 down=$(((rx - old_rx) / delta)) up=$(((tx - old_tx) / delta)) [ "$down" -ge 0 ] || down=0 [ "$up" -ge 0 ] || up=0 printf '%s/%s\n' "$(human_bytes "$down")" "$(human_bytes "$up")" ;; scratch) if command -v i3-msg >/dev/null 2>&1 && command -v jq >/dev/null 2>&1; then i3-msg -t get_tree 2>/dev/null | jq '[.. | objects | select(.name == "__i3_scratch") | .floating_nodes[]?] | length' 2>/dev/null || echo 0 else echo n/a fi ;; temp) if command -v sensors >/dev/null 2>&1; then temp="$( sensors 2>/dev/null | awk ' /Package id 0:/ { gsub(/[^0-9.-]/, "", $4); print int($4); exit } /Tctl:/ { gsub(/[^0-9.-]/, "", $2); print int($2); exit } /temp1:/ && $2 ~ /^\+/ { gsub(/[^0-9.-]/, "", $2); print int($2); exit } ' )" else temp="" fi if [ -z "$temp" ]; then for zone in /sys/class/thermal/thermal_zone*/temp; do [ -r "$zone" ] || continue value="$(cat "$zone")" if [ "$value" -gt 0 ] 2>/dev/null; then temp=$((value / 1000)) break fi done fi [ -n "${temp:-}" ] && echo "${temp}C" || echo n/a ;; updates) if command -v checkupdates >/dev/null 2>&1; then (checkupdates 2>/dev/null || true) | wc -l elif command -v pacman >/dev/null 2>&1; then (pacman -Qu 2>/dev/null || true) | wc -l else echo n/a fi ;; volume) if ! command -v pactl >/dev/null 2>&1; then echo n/a exit 0 fi mute="$(pactl get-sink-mute @DEFAULT_SINK@ 2>/dev/null | awk '{ print $2 }' || true)" vol="$(pactl get-sink-volume @DEFAULT_SINK@ 2>/dev/null | awk 'NR == 1 { print $5; exit }' || true)" [ "$mute" = yes ] && echo muted || echo "${vol:-n/a}" ;; wg) if [ ! -d "/sys/class/net/$profile" ]; then echo down exit 0 fi if ! command -v wg >/dev/null 2>&1; then echo up exit 0 fi latest="$(wg show "$profile" latest-handshakes 2>/dev/null | awk 'NF { if ($2 > newest) newest = $2 } END { print newest + 0 }' || true)" if [ -z "$latest" ] || [ "$latest" -le 0 ] 2>/dev/null; then echo up exit 0 fi age=$(($(date +%s) - latest)) if [ "$age" -lt 60 ]; then suffix="${age}s"; elif [ "$age" -lt 3600 ]; then suffix="$((age / 60))m"; elif [ "$age" -lt 86400 ]; then suffix="$((age / 3600))h"; else suffix="$((age / 86400))d"; fi echo "up $suffix" ;; *) echo n/a exit 1 ;; esac