{ lib , writeShellScriptBin , coreutils , gnugrep , jq , systemd }: # Smart suspend (#115): on battery, with hibernate available and the # in-flake toggle on, enter suspend-then-hibernate (1h → hibernate via # systemd.sleep HibernateDelaySec). Otherwise plain suspend. # # Reads the *live* state.json (menu may have flipped before rebuild); # logind lid policy still needs a system rebuild to match (power.nix). writeShellScriptBin "nomarchy-suspend" '' set -euo pipefail PATH=${lib.makeBinPath [ coreutils gnugrep jq systemd ]}:$PATH on_ac() { local f for f in /sys/class/power_supply/*/online; do [ -r "$f" ] && [ "$(cat "$f")" = "1" ] && return 0 done return 1 } can_hibernate() { # Prefer logind's live answer (swap + resume wiring). local v v=$(busctl get-property org.freedesktop.login1 \ /org/freedesktop/login1 org.freedesktop.login1.Manager \ CanHibernate 2>/dev/null || true) case "$v" in "s \"yes\"") return 0 ;; esac # Offline / early-boot fallback: resume= on the kernel cmdline. grep -q '[[:space:]]resume=' /proc/cmdline 2>/dev/null \ || grep -q '^resume=' /proc/cmdline 2>/dev/null } want_s2h() { # Default on (absent key / no state file) — bag-carry drains less without # a Preferences trip; menu writes false to opt out. local st v="" found=0 for st in \ "''${NOMARCHY_PATH:-$HOME/.nomarchy}/state.json" \ /home/*/.nomarchy/state.json do [ -r "$st" ] || continue found=1 v=$(jq -r '.settings.power.suspendThenHibernate // true' "$st" 2>/dev/null || true) break done [ "$found" -eq 0 ] && return 0 case "$v" in false|False|0) return 1 ;; *) return 0 ;; esac } if want_s2h && ! on_ac && can_hibernate; then exec systemctl suspend-then-hibernate fi exec systemctl suspend ''