feat: implement hybrid declarative state with automatic Nix sync
Some checks failed
Check / eval-and-lint (push) Has been cancelled

This commit is contained in:
Bernardo Magri
2026-05-31 20:09:12 +01:00
parent 624023c1d5
commit dc3346bc55
18 changed files with 182 additions and 48 deletions

View File

@@ -22,4 +22,8 @@ esac
hyprctl keyword misc:disable_scale_notification true
hyprctl keyword monitor "$ACTIVE_MONITOR,${WIDTH}x${HEIGHT}@${REFRESH_RATE},auto,$NEW_SCALE"
hyprctl keyword misc:disable_scale_notification false
# Persist the choice declaratively
nomarchy-state-write "hyprland.scale" "$NEW_SCALE"
notify-send -u low "󰍹 Display scaling set to ${NEW_SCALE}x"

View File

@@ -25,7 +25,6 @@ else
hyprctl keyword general:border_size 0
fi
TMP_JSON=$(mktemp)
jq --argjson state "$NEW_STATE" '.hyprland = $state' "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE"
nomarchy-state-write hyprland "$NEW_STATE" --type json
echo "Toggled gaps to $NEW_STATE declaratively."

View File

@@ -99,3 +99,11 @@ LOCK_FILE="${STATE_FILE}.lock"
# Clean up lock file
rm -f "$LOCK_FILE"
# If we just updated the main home state file, sync it to the Nix configuration.
# This bridges the gap between runtime UI changes and declarative Nix.
if [[ "$STATE_FILE" == "$HOME/.config/nomarchy/state.json" ]]; then
if command -v nomarchy-sync-nix-state >/dev/null 2>&1; then
nomarchy-sync-nix-state
fi
fi

View File

@@ -0,0 +1,67 @@
#!/usr/bin/env bash
set -e
# Nomarchy Nix State Sync
# Bridges the gap between runtime UI changes (state.json) and declarative
# Nix configuration (nomarchy-state.nix).
STATE_JSON="$HOME/.config/nomarchy/state.json"
NIX_STATE_FILE="/etc/nixos/nomarchy-state.nix"
# If state.json is missing, nothing to sync
if [ ! -f "$STATE_JSON" ]; then
exit 0
fi
# Determine destination.
# If we are in the repo, we sync to ./nomarchy-state.nix (dev mode).
# Otherwise, we sync to /etc/nixos/nomarchy-state.nix (real install).
if [ -f "flake.nix" ] || [ -d ".git" ]; then
DEST="./nomarchy-state.nix"
elif [ -w "/etc/nixos" ]; then
DEST="$NIX_STATE_FILE"
else
# Nowhere to sync to
exit 0
fi
# Generate the Nix attribute set from JSON.
# We use jq to extract the keys and format them as Nix assignments.
# Note: font in state.json maps to fonts.monospace in Nix.
{
echo "# DO NOT EDIT MANUALLY - Managed by Nomarchy scripts."
echo "# This file mirrors your UI choices (theme, font, etc.) into the declarative"
echo "# Nix configuration. It is imported by your home.nix."
echo "{"
echo " nomarchy = {"
# Core UI strings
echo " theme = \"$(jq -r '.theme // empty' "$STATE_JSON")\";"
echo " fonts.monospace = \"$(jq -r '.font // empty' "$STATE_JSON")\";"
echo " panelPosition = \"$(jq -r '.panelPosition // empty' "$STATE_JSON")\";"
echo " wallpaper = \"$(jq -r '.wallpaper // empty' "$STATE_JSON")\";"
# Hyprland layout (numbers)
echo " hyprland = {"
echo " scale = \"$(jq -r '.hyprland.scale // "auto"' "$STATE_JSON")\";"
echo " gaps_in = $(jq -r '.hyprland.gaps_in // 5' "$STATE_JSON");"
echo " gaps_out = $(jq -r '.hyprland.gaps_out // 10' "$STATE_JSON");"
echo " border_size = $(jq -r '.hyprland.border_size // 2' "$STATE_JSON");"
echo " };"
# Toggles (booleans)
echo " toggles = {"
echo " suspend = $(jq -r '.suspend // true' "$STATE_JSON");"
echo " screensaver = $(jq -r '.screensaver // true' "$STATE_JSON");"
echo " idle = $(jq -r '.idle // true' "$STATE_JSON");"
echo " nightlight = $(jq -r '.nightlight // false' "$STATE_JSON");"
echo " waybar = $(jq -r '.waybar // true' "$STATE_JSON");"
echo " };"
echo " };"
echo "}"
} > "$DEST.tmp"
# Final atomic move
mv "$DEST.tmp" "$DEST"

View File

@@ -19,8 +19,7 @@ else
notify-send -u low " Screensaver disabled"
fi
TMP_JSON=$(mktemp)
jq --argjson val "$NEW_VALUE" '.screensaver = $val' "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE"
nomarchy-state-write screensaver "$NEW_VALUE" --type bool
echo "Screensaver state set to $NEW_VALUE. Updating environment..."

View File

@@ -22,7 +22,6 @@ else
notify-send -u low " Top bar disabled"
fi
TMP_JSON=$(mktemp)
jq --argjson val "$NEW_VALUE" '.waybar = $val' "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE"
nomarchy-state-write waybar "$NEW_VALUE" --type bool
echo "Waybar state set to $NEW_VALUE."

View File

@@ -61,13 +61,10 @@ echo "Step 4: Choose your monitor scaling"
echo "Recommended: 'auto' for most screens, '2' for 4K/HiDPI."
SCALE=$(gum choose "auto" "1" "1.25" "1.5" "2")
if [[ -n "$SCALE" ]]; then
# Write to nested hyprland.scale key
STATE_DIR="$HOME/.config/nomarchy"
mkdir -p "$STATE_DIR"
TMP_FILE=\$(mktemp)
jq ".hyprland.scale = \"$SCALE\"" "\$STATE_FILE" > "\$TMP_FILE" && mv "\$TMP_FILE" "\$STATE_FILE"
nomarchy-state-write "hyprland.scale" "$SCALE"
fi
# Skip system-modifying steps in the Live ISO environment
if [[ "$USER" == "nixos" ]]; then
echo ""