feat(waybar): combined power menu on the battery + profile icons
All checks were successful
Check / eval (push) Successful in 3m5s

Item 36(b). Adds `nomarchy-menu powermgmt` — one flat rofi menu of power
Profile rows (→ powerprofilesctl set) + Charge limit rows (→ the same
theme-sync writer batterylimit uses), each half self-gating on its
hardware. No backend duplication; Custom charge stays in the dedicated
batterylimit picker.

Opened two ways (Bernardo's call): the Waybar battery icon AND the
power-profile icon — the profile icon's click flips from cycle → menu.
Wired in waybar.nix and all four whole-swaps (parity). Named `powermgmt`
to avoid the whole-swaps' existing `custom/powermenu` shutdown button
(→ nomarchy-menu power), which is left untouched. The granular System ▸
Power profile / Battery limit rows stay ("keep both").
nomarchy-powerprofile-cycle kept as a standalone bin, now unbound by
default.

Verified: V0 green; V1 HM built (bash -n) — powermgmt case ships, the
generated waybar-config.json wires both icons (2 hits), all four jsoncs
re-wired and still parse, shutdown buttons intact. Click→menu→apply is
V3 (queued).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Bernardo Magri
2026-07-08 14:40:40 +01:00
parent 714fbd1daf
commit 1143e67f95
9 changed files with 101 additions and 33 deletions

View File

@@ -256,6 +256,56 @@ let
[ "$choice" = "$BACK" ] && exec "$0" system
[ -n "$choice" ] && powerprofilesctl set "$choice" ;;
powermgmt)
# Combined power menu (item 36b) power PROFILE + battery CHARGE cap
# in one flat list, opened from BOTH the Waybar battery and
# power-profile icons (the two granular System Power profile /
# Battery limit rows stay for direct access). No new backend: profile
# rows drive powerprofilesctl like the power-profile picker, charge
# rows drive the same theme-sync writer as batterylimit. Each half
# self-gates on its hardware, so a desktop with neither just toasts.
bats=(/sys/class/power_supply/BAT*)
haveppd=false; command -v powerprofilesctl >/dev/null 2>&1 && haveppd=true
havecharge=false; [ -e "''${bats[0]}/charge_control_end_threshold" ] && havecharge=true
if ! $haveppd && ! $havecharge; then
notify-send "Power" "No power-profile or charge-limit control on this machine."
exit 0
fi
curp=""; $haveppd && curp=$(powerprofilesctl get 2>/dev/null)
curc=$(nomarchy-theme-sync get settings.power.batteryChargeLimit 2>/dev/null)
choice=$( {
if $haveppd; then
powerprofilesctl list 2>/dev/null | sed -nE 's/^[* ] ([a-z-]+):$/\1/p' \
| while IFS= read -r p; do
case "$p" in
performance) row "Profile: $p" battery-profile-performance ;;
balanced) row "Profile: $p" battery-profile-balanced ;;
power-saver) row "Profile: $p" battery-profile-powersave ;;
*) row "Profile: $p" preferences-system-power ;;
esac
done
fi
if $havecharge; then
row "Charge limit: 80% (recommended)" battery-080
row "Charge limit: 90%" battery-090
row "Charge limit: 60%" battery-060
row "Charge limit: Off (100%)" battery-100
fi
back
} | rofi -dmenu -show-icons -p "Power profile: ''${curp:-n/a}, limit: ''${curc:-default}") || exit 0
set_limit() {
nomarchy-theme-sync --quiet set settings.power.batteryChargeLimit "$1" --no-switch
notify-send "Battery limit" "$2 applies on the next rebuild."
}
case "$choice" in
"$BACK") exec "$0" ;;
"Profile: "*) powerprofilesctl set "''${choice#Profile: }" ;;
"Charge limit: 80%"*) set_limit 80 "Set to 80%" ;;
"Charge limit: 90%"*) set_limit 90 "Set to 90%" ;;
"Charge limit: 60%"*) set_limit 60 "Set to 60%" ;;
"Charge limit: Off"*) set_limit null "Off charges to 100%" ;;
esac ;;
theme)
# Visual picker: a grid of real desktop previews (rows + Nameslug
# map generated from the presets at build time). Pick a card apply
@@ -790,7 +840,7 @@ ${themeRows}
esac ;;
*)
echo "usage: nomarchy-menu [lookfeel|tools|system|power|power-profile|batterylimit|theme|clipboard|calc|files|emoji|web|network|bluetooth|audio|display|display-profile|printers|capture|colorpicker|keybinds|ask|dnd|nightlight|autotimezone|autocommit|vpn|snapshot]" >&2
echo "usage: nomarchy-menu [lookfeel|tools|system|power|power-profile|powermgmt|batterylimit|theme|clipboard|calc|files|emoji|web|network|bluetooth|audio|display|display-profile|printers|capture|colorpicker|keybinds|ask|dnd|nightlight|autotimezone|autocommit|vpn|snapshot]" >&2
exit 64 ;;
esac
'';

View File

@@ -199,13 +199,19 @@ let
format = "<span size='${toString (t.fonts.size + 2)}pt'>{icon}</span> {capacity}%";
format-charging = "<span size='${toString (t.fonts.size + 2)}pt'>󰂄</span> {capacity}%";
format-icons = [ "󰁺" "󰁼" "󰁾" "󰂀" "󰁹" ];
# Click either the battery or the power-profile icon → the combined
# power menu (profile + charge cap). The granular System rows stay.
on-click = "nomarchy-menu powermgmt";
};
"custom/powerprofile" = {
exec = "nomarchy-powerprofile-status";
return-type = "json";
interval = 5;
on-click = "nomarchy-powerprofile-cycle";
# Opens the same combined power menu as the battery icon (item 36b).
# nomarchy-powerprofile-cycle stays a standalone bin for downstream
# rebinding — it's just no longer the default click.
on-click = "nomarchy-menu powermgmt";
};
# VPN shield — self-hides unless a NM VPN/WireGuard tunnel or Tailscale is