diff --git a/bin/nomarchy-font-set b/bin/nomarchy-font-set index 53c6a45..7dd2385 100755 --- a/bin/nomarchy-font-set +++ b/bin/nomarchy-font-set @@ -11,12 +11,14 @@ if [[ -z $font_name ]]; then fi STATE_DIR="$HOME/.config/home-manager" -STATE_FILE="$STATE_DIR/font-state.nix" +STATE_FILE="$STATE_DIR/state.json" mkdir -p "$STATE_DIR" +[[ ! -f $STATE_FILE ]] && echo "{}" > "$STATE_FILE" if fc-list | grep -iq "$font_name"; then - echo "$font_name" > "$STATE_FILE" + TMP_JSON=$(mktemp) + jq ".font = \"$font_name\"" "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE" echo "Font set to $font_name declaratively. Applying changes..." env-update diff --git a/bin/nomarchy-hyprland-window-gaps-toggle b/bin/nomarchy-hyprland-window-gaps-toggle index 7f51aaa..d4b575d 100755 --- a/bin/nomarchy-hyprland-window-gaps-toggle +++ b/bin/nomarchy-hyprland-window-gaps-toggle @@ -2,14 +2,14 @@ # Toggles the window gaps globally between no gaps and the default 10/5/2, declaratively and instantly. -STATE_FILE="$HOME/.config/home-manager/hyprland-state.json" +STATE_FILE="$HOME/.config/home-manager/state.json" mkdir -p "$(dirname "$STATE_FILE")" if [ ! -f "$STATE_FILE" ]; then - echo '{"gaps_out": 10, "gaps_in": 5, "border_size": 2}' > "$STATE_FILE" + echo "{}" > "$STATE_FILE" fi -gaps=$(jq -r '.gaps_out' "$STATE_FILE") +gaps=$(jq -r '.hyprland.gaps_out // 10' "$STATE_FILE") if [[ $gaps == "0" ]]; then NEW_STATE='{"gaps_out": 10, "gaps_in": 5, "border_size": 2}' @@ -23,5 +23,7 @@ else hyprctl keyword general:border_size 0 fi -echo "$NEW_STATE" > "$STATE_FILE" +TMP_JSON=$(mktemp) +jq ".hyprland = $NEW_STATE" "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE" + echo "Toggled gaps to $NEW_STATE declaratively." diff --git a/bin/nomarchy-launch-screensaver b/bin/nomarchy-launch-screensaver index 1ccf302..16eff8e 100755 --- a/bin/nomarchy-launch-screensaver +++ b/bin/nomarchy-launch-screensaver @@ -11,10 +11,12 @@ fi pgrep -f org.nomarchy.screensaver && exit 0 # Allow screensaver to be turned off but also force started -if [[ -f ~/.local/state/nomarchy/toggles/screensaver-off ]] && [[ $1 != "force" ]]; then - exit 1 +# Skip if screensaver is disabled in configuration +if [[ $NOMARCHY_TOGGLE_SCREENSAVER == "false" ]] && [[ $1 != "force" ]]; then + exit 0 fi + # Silently quit Walker on overlay walker -q diff --git a/bin/nomarchy-state b/bin/nomarchy-state index 7cfcc87..855676f 100755 --- a/bin/nomarchy-state +++ b/bin/nomarchy-state @@ -1,8 +1,10 @@ #!/bin/bash -# Manage persistent state files for Nomarchy toggles and settings. +# Manage persistent runtime state files for Nomarchy indicators. # Usage: nomarchy-state -# Used to track whether features like suspend, idle lock, etc are enabled or disabled. +# Used to track whether things like reboot, restart, etc are required. +# DO NOT use this for configuration toggles (suspend, screensaver, etc). +# Use declarative Nomarchy NixOS home-manager options for those instead. STATE_DIR="$HOME/.local/state/nomarchy" mkdir -p "$STATE_DIR" diff --git a/bin/nomarchy-theme-bg-next b/bin/nomarchy-theme-bg-next index d5576e0..0b9c9fd 100755 --- a/bin/nomarchy-theme-bg-next +++ b/bin/nomarchy-theme-bg-next @@ -4,10 +4,11 @@ # Declarative + Hybrid (instant swww) for Nomarchy NixOS. STATE_DIR="$HOME/.config/home-manager" -THEME_STATE_FILE="$STATE_DIR/theme-state.nix" -WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix" +STATE_FILE="$STATE_DIR/state.json" +mkdir -p "$STATE_DIR" +[[ ! -f $STATE_FILE ]] && echo "{}" > "$STATE_FILE" -THEME_NAME=$(cat "$THEME_STATE_FILE" 2>/dev/null || echo "nord") +THEME_NAME=$(jq -r '.theme // "nord"' "$STATE_FILE") if [ -d "/etc/nixos/nomarchy/themes" ]; then THEMES_DIR="/etc/nixos/nomarchy/themes" @@ -32,7 +33,7 @@ if (( TOTAL == 0 )); then exit 1 fi -CURRENT_BG=$(cat "$WALLPAPER_STATE_FILE" 2>/dev/null) +CURRENT_BG=$(jq -r '.wallpaper' "$STATE_FILE") INDEX=-1 for i in "${!BACKGROUNDS[@]}"; do if [[ "$BG_DIR/${BACKGROUNDS[$i]}" == "$CURRENT_BG" ]]; then @@ -44,7 +45,8 @@ done NEXT_INDEX=$(((INDEX + 1) % TOTAL)) NEW_BG="$BG_DIR/${BACKGROUNDS[$NEXT_INDEX]}" -echo "$NEW_BG" > "$WALLPAPER_STATE_FILE" +TMP_JSON=$(mktemp) +jq ".wallpaper = \"$NEW_BG\"" "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE" # Instant feedback via swww if pgrep -x swww-daemon >/dev/null; then diff --git a/bin/nomarchy-theme-set b/bin/nomarchy-theme-set index 856ada8..aaea1b4 100755 --- a/bin/nomarchy-theme-set +++ b/bin/nomarchy-theme-set @@ -11,8 +11,7 @@ if [[ -z $THEME_NAME ]]; then fi STATE_DIR="$HOME/.config/home-manager" -THEME_STATE_FILE="$STATE_DIR/theme-state.nix" -WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix" +STATE_FILE="$STATE_DIR/state.json" # Logic for finding themes if [ -d "/etc/nixos/nomarchy/themes" ]; then @@ -24,6 +23,7 @@ else fi mkdir -p "$STATE_DIR" +[[ ! -f $STATE_FILE ]] && echo "{}" > "$STATE_FILE" if [ ! -d "$THEMES_DIR/$THEME_NAME" ] && ! [[ "$THEME_NAME" == "nord" ]]; then echo "Theme '$THEME_NAME' not found in $THEMES_DIR" @@ -31,18 +31,23 @@ if [ ! -d "$THEMES_DIR/$THEME_NAME" ] && ! [[ "$THEME_NAME" == "nord" ]]; then # (Assuming nomarchy-palettes.nix is imported in Nix) fi -echo "$THEME_NAME" > "$THEME_STATE_FILE" +TMP_JSON=$(mktemp) +jq ".theme = \"$THEME_NAME\"" "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE" # Try to find a background for this theme BG_DIR="$THEMES_DIR/$THEME_NAME/backgrounds" if [ -d "$BG_DIR" ]; then BG=$(ls "$BG_DIR" | head -n 1) if [ -n "$BG" ]; then - echo "$BG_DIR/$BG" > "$WALLPAPER_STATE_FILE" + TMP_JSON=$(mktemp) + jq ".wallpaper = \"$BG_DIR/$BG\"" "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE" fi fi echo "Theme set to $THEME_NAME. Applying changes with env-update..." +rm -rf "$HOME/.config/nomarchy/current/theme" env-update +nomarchy-theme-set-templates + nomarchy-hook theme-set "$THEME_NAME" diff --git a/bin/nomarchy-theme-set-vscode b/bin/nomarchy-theme-set-vscode index 8d06f5d..621d8a4 100755 --- a/bin/nomarchy-theme-set-vscode +++ b/bin/nomarchy-theme-set-vscode @@ -7,9 +7,8 @@ VS_CODE_THEME="$HOME/.config/nomarchy/current/theme/vscode.json" set_theme() { local editor_cmd="$1" local settings_path="$2" - local skip_flag="$3" - nomarchy-cmd-present "$editor_cmd" && [[ ! -f $skip_flag ]] || return 0 + nomarchy-cmd-present "$editor_cmd" && [[ $NOMARCHY_TOGGLE_SKIP_VSCODE_THEME != "true" ]] || return 0 if [[ -f $VS_CODE_THEME ]]; then theme_name=$(jq -r '.name' "$VS_CODE_THEME") @@ -34,7 +33,7 @@ set_theme() { fi } -set_theme "code" "$HOME/.config/Code/User/settings.json" "$HOME/.local/state/nomarchy/toggles/skip-vscode-theme-changes" -set_theme "code-insiders" "$HOME/.config/Code - Insiders/User/settings.json" "$HOME/.local/state/nomarchy/toggles/skip-vscode-insiders-theme-changes" -set_theme "codium" "$HOME/.config/VSCodium/User/settings.json" "$HOME/.local/state/nomarchy/toggles/skip-codium-theme-changes" -set_theme "cursor" "$HOME/.config/Cursor/User/settings.json" "$HOME/.local/state/nomarchy/toggles/skip-cursor-theme-changes" +set_theme "code" "$HOME/.config/Code/User/settings.json" +set_theme "code-insiders" "$HOME/.config/Code - Insiders/User/settings.json" +set_theme "codium" "$HOME/.config/VSCodium/User/settings.json" +set_theme "cursor" "$HOME/.config/Cursor/User/settings.json" diff --git a/bin/nomarchy-toggle-idle b/bin/nomarchy-toggle-idle index 8fd8a1e..699737d 100755 --- a/bin/nomarchy-toggle-idle +++ b/bin/nomarchy-toggle-idle @@ -1,28 +1,27 @@ #!/usr/bin/env bash # Toggles the idle daemon (hypridle) between enabled and disabled. -# Declarative + Hybrid (instant IPC/kill) for Nomarchy NixOS. +# Hybrid: updates state.json and provides instant feedback. -STATE_FILE="$HOME/.config/home-manager/idle-state.json" +STATE_FILE="$HOME/.config/home-manager/state.json" mkdir -p "$(dirname "$STATE_FILE")" -if [ ! -f "$STATE_FILE" ]; then - echo '{"enabled": true}' > "$STATE_FILE" -fi +# Initialize if doesn't exist +[[ ! -f $STATE_FILE ]] && echo "{}" > "$STATE_FILE" -enabled=$(jq -r '.enabled' "$STATE_FILE") - -if [[ $enabled == "true" ]]; then - NEW_ENABLED="false" - pkill -x hypridle - notify-send -u low "󱫖 Stop locking computer when idle" -else - NEW_ENABLED="true" +if [[ $NOMARCHY_TOGGLE_IDLE == "false" ]]; then + NEW_VALUE="true" setsid hypridle >/dev/null 2>&1 & notify-send -u low "󱫖 Now locking computer when idle" +else + NEW_VALUE="false" + pkill -x hypridle + notify-send -u low "󱫖 Stop locking computer when idle" fi -echo "{\"enabled\": $NEW_ENABLED}" > "$STATE_FILE" -echo "Idle daemon set to $NEW_ENABLED declaratively." +TMP_JSON=$(mktemp) +jq ".idle = $NEW_VALUE" "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE" + +echo "Idle state set to $NEW_VALUE. Environment will be fully updated on next rebuild." pkill -RTMIN+9 waybar # Signal waybar if needed diff --git a/bin/nomarchy-toggle-nightlight b/bin/nomarchy-toggle-nightlight index 73073e2..6cde7ac 100755 --- a/bin/nomarchy-toggle-nightlight +++ b/bin/nomarchy-toggle-nightlight @@ -1,36 +1,25 @@ #!/usr/bin/env bash -# Toggles the nightlight (hyprsunset) between enabled (4000) and disabled (6500) -# Declarative + Hybrid (instant IPC) for Nomarchy NixOS. +# Toggles the nightlight (hyprsunset). +# Hybrid: updates state.json and provides instant feedback. -STATE_FILE="$HOME/.config/home-manager/hyprsunset-state.json" +STATE_FILE="$HOME/.config/home-manager/state.json" mkdir -p "$(dirname "$STATE_FILE")" -if [ ! -f "$STATE_FILE" ]; then - echo '{"enabled": false, "temperature": 4000}' > "$STATE_FILE" -fi +# Initialize if doesn't exist +[[ ! -f $STATE_FILE ]] && echo "{}" > "$STATE_FILE" -enabled=$(jq -r '.enabled' "$STATE_FILE") - -if [[ $enabled == "true" ]]; then - NEW_ENABLED="false" - TEMP=6500 - notify-send -u low " Nightlight DISABLED" +if [[ $NOMARCHY_TOGGLE_NIGHTLIGHT == "false" ]]; then + NEW_VALUE="true" + hyprctl dispatch exec hyprsunset --temperature 4000 + notify-send -u low "󰔎 Nightlight enabled" else - NEW_ENABLED="true" - TEMP=4000 - notify-send -u low " Nightlight ENABLED" + NEW_VALUE="false" + pkill hyprsunset + notify-send -u low "󰔎 Nightlight disabled" fi -# Instant feedback via IPC -if pgrep -x hyprsunset >/dev/null; then - hyprctl hyprsunset temperature $TEMP -else - # Should be started by systemd, but just in case - setsid hyprsunset -t $TEMP & -fi +TMP_JSON=$(mktemp) +jq ".nightlight = $NEW_VALUE" "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE" -echo "{\"enabled\": $NEW_ENABLED, \"temperature\": 4000}" > "$STATE_FILE" -echo "Nightlight set to $NEW_ENABLED ($TEMP) declaratively." -# No need to run env-update if we don't want the delay, -# as next HM switch will pick it up and apply it. +echo "Nightlight state set to $NEW_VALUE. Environment will be fully updated on next rebuild." diff --git a/bin/nomarchy-toggle-screensaver b/bin/nomarchy-toggle-screensaver index b9f90fb..ad3839e 100755 --- a/bin/nomarchy-toggle-screensaver +++ b/bin/nomarchy-toggle-screensaver @@ -1,12 +1,25 @@ -#!/bin/bash +#!/usr/bin/env bash -STATE_FILE=~/.local/state/nomarchy/toggles/screensaver-off +# Toggles the screensaver availability. +# Hybrid: updates state.json and runs env-update for persistence. -if [[ -f $STATE_FILE ]]; then - rm -f $STATE_FILE - notify-send -u low "󱄄 Screensaver enabled" +STATE_FILE="$HOME/.config/home-manager/state.json" +mkdir -p "$(dirname "$STATE_FILE")" + +# Initialize if doesn't exist +[[ ! -f $STATE_FILE ]] && echo "{}" > "$STATE_FILE" + +if [[ $NOMARCHY_TOGGLE_SCREENSAVER == "false" ]]; then + NEW_VALUE="true" + notify-send -u low "󱄄 Screensaver enabled" else - mkdir -p "$(dirname $STATE_FILE)" - touch $STATE_FILE - notify-send -u low "󱄄 Screensaver disabled" + NEW_VALUE="false" + notify-send -u low "󱄄 Screensaver disabled" fi + +TMP_JSON=$(mktemp) +jq ".screensaver = $NEW_VALUE" "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE" + +echo "Screensaver state set to $NEW_VALUE. Updating environment..." + +env-update diff --git a/bin/nomarchy-toggle-suspend b/bin/nomarchy-toggle-suspend index 871e1ea..c5888b9 100755 --- a/bin/nomarchy-toggle-suspend +++ b/bin/nomarchy-toggle-suspend @@ -1,12 +1,29 @@ -#!/bin/bash +#!/usr/bin/env bash -STATE_FILE=~/.local/state/nomarchy/toggles/suspend-off +# Toggles the suspend menu option availability. +# Hybrid: updates state.json and runs env-update for persistence. -if [[ -f $STATE_FILE ]]; then - rm -f $STATE_FILE - notify-send -u low "󰒲 Suspend now available in system menu" +STATE_FILE="$HOME/.config/home-manager/state.json" +mkdir -p "$(dirname "$STATE_FILE")" + +# Initialize if doesn't exist +[[ ! -f $STATE_FILE ]] && echo "{}" > "$STATE_FILE" + +# Get current state from env or state file +if [[ $NOMARCHY_TOGGLE_SUSPEND == "false" ]]; then + NEW_VALUE="true" + notify-send -u low "󰒲 Suspend now available in system menu" else - mkdir -p "$(dirname $STATE_FILE)" - touch $STATE_FILE - notify-send -u low "󰒲 Suspend removed from system menu" + NEW_VALUE="false" + notify-send -u low "󰒲 Suspend removed from system menu" fi + +# Update JSON using jq +# We use a temporary file to avoid corruption if the shell is interrupted +TMP_JSON=$(mktemp) +jq ".suspend = $NEW_VALUE" "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE" + +echo "Suspend availability set to $NEW_VALUE. Updating environment..." + +# Run env-update to apply changes to the menu +env-update diff --git a/bin/nomarchy-toggle-waybar b/bin/nomarchy-toggle-waybar index 7138782..bf21573 100755 --- a/bin/nomarchy-toggle-waybar +++ b/bin/nomarchy-toggle-waybar @@ -1,7 +1,25 @@ -#!/bin/bash +#!/usr/bin/env bash -if pgrep -x waybar >/dev/null; then - pkill -x waybar +# Toggles the waybar top bar. +# Hybrid: updates state.json and provides instant feedback. + +STATE_FILE="$HOME/.config/home-manager/state.json" +mkdir -p "$(dirname "$STATE_FILE")" + +# Initialize if doesn't exist +[[ ! -f $STATE_FILE ]] && echo "{}" > "$STATE_FILE" + +if [[ $NOMARCHY_TOGGLE_WAYBAR == "false" ]]; then + NEW_VALUE="true" + uwsm-app -- waybar >/dev/null 2>&1 & + notify-send -u low "󰍜 Top bar enabled" else - uwsm-app -- waybar >/dev/null 2>&1 & + NEW_VALUE="false" + pkill -x waybar + notify-send -u low "󰍜 Top bar disabled" fi + +TMP_JSON=$(mktemp) +jq ".waybar = $NEW_VALUE" "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE" + +echo "Waybar state set to $NEW_VALUE. Environment will be fully updated on next rebuild." diff --git a/migrations/20260404_migrate_state_to_json.sh b/migrations/20260404_migrate_state_to_json.sh new file mode 100644 index 0000000..812ad08 --- /dev/null +++ b/migrations/20260404_migrate_state_to_json.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash + +# Migration: Migrate individual state files to unified state.json +# Version: 20260404 + +OLD_TOGGLES_DIR="$HOME/.local/state/nomarchy/toggles" +IDLE_STATE_FILE="$HOME/.config/home-manager/idle-state.json" +NIGHTLIGHT_STATE_FILE="$HOME/.config/home-manager/hyprsunset-state.json" +HYPRLAND_STATE_FILE="$HOME/.config/home-manager/hyprland-state.json" +THEME_STATE_FILE="$HOME/.config/home-manager/theme-state.nix" +WALLPAPER_STATE_FILE="$HOME/.config/home-manager/wallpaper-state.nix" +FONT_STATE_FILE="$HOME/.config/home-manager/font-state.nix" +NEW_STATE_FILE="$HOME/.config/home-manager/state.json" + +mkdir -p "$(dirname "$NEW_STATE_FILE")" +[[ ! -f $NEW_STATE_FILE ]] && echo "{}" > "$NEW_STATE_FILE" + +# 1. Migrate .local/state/nomarchy/toggles (these were empty 'off' flag files) +if [[ -d $OLD_TOGGLES_DIR ]]; then + for file in "$OLD_TOGGLES_DIR"/*; do + [[ -e "$file" ]] || continue + filename=$(basename "$file") + case "$filename" in + suspend-off) + echo "Migrating suspend-off -> suspend: false" + jq '.suspend = false' "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE" + ;; + screensaver-off) + echo "Migrating screensaver-off -> screensaver: false" + jq '.screensaver = false' "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE" + ;; + skip-vscode-theme-changes) + echo "Migrating skip-vscode-theme-changes -> skipVsCodeTheme: true" + jq '.skipVsCodeTheme = true' "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE" + ;; + esac + rm "$file" + done + rmdir "$OLD_TOGGLES_DIR" 2>/dev/null || true +fi + +# 2. Migrate existing JSON state files +if [[ -f $IDLE_STATE_FILE ]]; then + echo "Migrating idle-state.json -> state.json" + ENABLED=$(jq '.enabled' "$IDLE_STATE_FILE") + jq ".idle = $ENABLED" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE" + rm "$IDLE_STATE_FILE" +fi + +if [[ -f $NIGHTLIGHT_STATE_FILE ]]; then + echo "Migrating hyprsunset-state.json -> state.json" + ENABLED=$(jq '.enabled' "$NIGHTLIGHT_STATE_FILE") + TEMP=$(jq '.temperature' "$NIGHTLIGHT_STATE_FILE") + jq ".nightlight = $ENABLED | .nightlightTemperature = $TEMP" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE" + rm "$NIGHTLIGHT_STATE_FILE" +fi + +if [[ -f $HYPRLAND_STATE_FILE ]]; then + echo "Migrating hyprland-state.json -> state.json" + GAPS_OUT=$(jq '.gaps_out' "$HYPRLAND_STATE_FILE") + GAPS_IN=$(jq '.gaps_in' "$HYPRLAND_STATE_FILE") + BORDER_SIZE=$(jq '.border_size' "$HYPRLAND_STATE_FILE") + jq ".hyprland = {\"gaps_out\": $GAPS_OUT, \"gaps_in\": $GAPS_IN, \"border_size\": $BORDER_SIZE}" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE" + rm "$HYPRLAND_STATE_FILE" +fi + +# 3. Migrate plaintext string state files +if [[ -f $THEME_STATE_FILE ]]; then + echo "Migrating theme-state.nix -> state.json" + THEME=$(cat "$THEME_STATE_FILE" | tr -d '\n') + jq ".theme = \"$THEME\"" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE" + rm "$THEME_STATE_FILE" +fi + +if [[ -f $WALLPAPER_STATE_FILE ]]; then + echo "Migrating wallpaper-state.nix -> state.json" + WALLPAPER=$(cat "$WALLPAPER_STATE_FILE" | tr -d '\n') + jq ".wallpaper = \"$WALLPAPER\"" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE" + rm "$WALLPAPER_STATE_FILE" +fi + +if [[ -f $FONT_STATE_FILE ]]; then + echo "Migrating font-state.nix -> state.json" + FONT=$(cat "$FONT_STATE_FILE" | tr -d '\n') + jq ".font = \"$FONT\"" "$NEW_STATE_FILE" > "$NEW_STATE_FILE.tmp" && mv "$NEW_STATE_FILE.tmp" "$NEW_STATE_FILE" + rm "$FONT_STATE_FILE" +fi + +echo "State migration complete." diff --git a/modules/home/default.nix b/modules/home/default.nix index 685d5bc..6a50454 100644 --- a/modules/home/default.nix +++ b/modules/home/default.nix @@ -2,11 +2,6 @@ let palettes = import ../../themes/nomarchy-palettes.nix; - # Reads the state file. If it doesn't exist, defaults to nord. - stateFile = "${config.home.homeDirectory}/.config/home-manager/theme-state.nix"; - activeThemeName = if builtins.pathExists stateFile then - lib.removeSuffix "\n" (builtins.readFile stateFile) - else "nord"; userPackagesFile = "${config.home.homeDirectory}/.config/home-manager/user-packages.json"; userPackages = if builtins.pathExists userPackagesFile then let @@ -20,6 +15,9 @@ in imports = [ inputs.nix-colors.homeManagerModules.default inputs.walker.homeManagerModules.default + ./options.nix + ./state.nix + ./theme-files.nix ./fonts.nix ./alacritty.nix ./nightlight.nix @@ -34,7 +32,7 @@ in ./swayosd.nix ]; - colorScheme = palettes.${activeThemeName} or palettes.nord; + colorScheme = palettes.${config.nomarchy.theme} or palettes.nord; home.packages = with pkgs; [ firefox diff --git a/modules/home/fonts.nix b/modules/home/fonts.nix index 40e856a..4cec7d5 100644 --- a/modules/home/fonts.nix +++ b/modules/home/fonts.nix @@ -1,22 +1,6 @@ -{ config, pkgs, lib, ... }: +{ ... }: -let - # Standardize state files to a common directory - stateDir = "${config.home.homeDirectory}/.config/home-manager"; - fontStateFile = "${stateDir}/font-state.nix"; - activeFont = if builtins.pathExists fontStateFile then - lib.removeSuffix "\n" (builtins.readFile fontStateFile) - else "JetBrainsMono Nerd Font"; -in { - options.nomarchy.fonts = { - monospace = lib.mkOption { - type = lib.types.str; - default = activeFont; - description = "Monospace font for the system"; - }; - }; - config = { fonts.fontconfig.enable = true; xdg.dataFile."fonts/nomarchy.ttf".source = ../../config/nomarchy.ttf; diff --git a/modules/home/hyprland.nix b/modules/home/hyprland.nix index 50bb754..39dbe28 100644 --- a/modules/home/hyprland.nix +++ b/modules/home/hyprland.nix @@ -1,14 +1,8 @@ { config, pkgs, lib, ... }: let - wallpaperStateFile = "${config.home.homeDirectory}/.config/home-manager/wallpaper-state.nix"; - activeWallpaper = if builtins.pathExists wallpaperStateFile then - lib.removeSuffix "\n" (builtins.readFile wallpaperStateFile) - else ""; - hyprlandStateFile = "${config.home.homeDirectory}/.config/home-manager/hyprland-state.json"; - hyprlandState = if builtins.pathExists hyprlandStateFile then - builtins.fromJSON (builtins.readFile hyprlandStateFile) - else { gaps_out = 10; gaps_in = 5; border_size = 2; }; + activeWallpaper = config.nomarchy.wallpaper; + hyprlandState = config.nomarchy.hyprland; in { wayland.windowManager.hyprland = { @@ -23,10 +17,9 @@ in }; "exec-once" = [ "swww-daemon & sleep 0.5 && swww img ${activeWallpaper} --transition-type none" - "waybar" "nomarchy-on-boot" "nomarchy-welcome" - ]; + ] ++ (lib.optional config.nomarchy.toggles.waybar "waybar"); "bind" = [ "SUPER, Space, exec, walker" "SUPER ALT, Space, exec, nomarchy-theme-selector" diff --git a/modules/home/idle.nix b/modules/home/idle.nix index 8ae3846..0fcbffd 100644 --- a/modules/home/idle.nix +++ b/modules/home/idle.nix @@ -1,13 +1,7 @@ -{ config, pkgs, ... }: +{ config, ... }: -let - stateFile = "${config.home.homeDirectory}/.config/home-manager/idle-state.json"; - idleState = if builtins.pathExists stateFile then - builtins.fromJSON (builtins.readFile stateFile) - else { enabled = true; }; -in { services.hypridle = { - enable = idleState.enabled; + enable = config.nomarchy.toggles.idle; }; } diff --git a/modules/home/nightlight.nix b/modules/home/nightlight.nix index 5e19202..142dbd0 100644 --- a/modules/home/nightlight.nix +++ b/modules/home/nightlight.nix @@ -1,11 +1,7 @@ -{ config, pkgs, ... }: +{ config, ... }: let - stateFile = "${config.home.homeDirectory}/.config/home-manager/hyprsunset-state.json"; - hyprsunsetState = if builtins.pathExists stateFile then - builtins.fromJSON (builtins.readFile stateFile) - else { enabled = false; temperature = 4000; }; - temp = toString (if hyprsunsetState.enabled then hyprsunsetState.temperature else 6500); + temp = toString (if config.nomarchy.toggles.nightlight then config.nomarchy.nightlightTemperature else 6500); in { services.hyprsunset = { diff --git a/modules/home/options.nix b/modules/home/options.nix new file mode 100644 index 0000000..bff1e9b --- /dev/null +++ b/modules/home/options.nix @@ -0,0 +1,77 @@ +{ lib, ... }: + +{ + options.nomarchy = { + toggles = { + suspend = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Whether to show suspend in system menu."; + }; + screensaver = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Whether the screensaver is enabled."; + }; + idle = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Whether the idle lock is enabled."; + }; + nightlight = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Whether the nightlight is enabled."; + }; + waybar = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Whether the top bar is enabled."; + }; + skipVsCodeTheme = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Whether to skip theme changes in VSCode."; + }; + }; + nightlightTemperature = lib.mkOption { + type = lib.types.int; + default = 4000; + description = "Temperature for the nightlight."; + }; + theme = lib.mkOption { + type = lib.types.str; + default = "nord"; + description = "System theme name."; + }; + wallpaper = lib.mkOption { + type = lib.types.str; + default = ""; + description = "System wallpaper path."; + }; + hyprland = { + gaps_in = lib.mkOption { + type = lib.types.int; + default = 5; + description = "Inner gaps for Hyprland."; + }; + gaps_out = lib.mkOption { + type = lib.types.int; + default = 10; + description = "Outer gaps for Hyprland."; + }; + border_size = lib.mkOption { + type = lib.types.int; + default = 2; + description = "Border size for Hyprland."; + }; + }; + fonts = { + monospace = lib.mkOption { + type = lib.types.str; + default = "JetBrainsMono Nerd Font"; + description = "System monospace font."; + }; + }; + }; +} diff --git a/modules/home/scripts.nix b/modules/home/scripts.nix index a3de21a..8c2b2a1 100644 --- a/modules/home/scripts.nix +++ b/modules/home/scripts.nix @@ -42,11 +42,18 @@ let cp -r * $out/bin/ chmod +x $out/bin/* - # Wrap every script to ensure dependencies are in PATH + # Wrap every script to ensure dependencies are in PATH and inject configuration for file in $out/bin/*; do if [ -f "$file" ]; then wrapProgram "$file" \ - --prefix PATH : ${lib.makeBinPath nomarchy-deps} + --prefix PATH : ${lib.makeBinPath nomarchy-deps} \ + --set NOMARCHY_TOGGLE_SUSPEND "${if config.nomarchy.toggles.suspend then "true" else "false"}" \ + --set NOMARCHY_TOGGLE_SCREENSAVER "${if config.nomarchy.toggles.screensaver then "true" else "false"}" \ + --set NOMARCHY_TOGGLE_IDLE "${if config.nomarchy.toggles.idle then "true" else "false"}" \ + --set NOMARCHY_TOGGLE_NIGHTLIGHT "${if config.nomarchy.toggles.nightlight then "true" else "false"}" \ + --set NOMARCHY_TOGGLE_WAYBAR "${if config.nomarchy.toggles.waybar then "true" else "false"}" \ + --set NOMARCHY_TOGGLE_SKIP_VSCODE_THEME "${if config.nomarchy.toggles.skipVsCodeTheme then "true" else "false"}" \ + --set NOMARCHY_MONOSPACE_FONT "${config.nomarchy.fonts.monospace}" fi done ''; diff --git a/modules/home/state.nix b/modules/home/state.nix new file mode 100644 index 0000000..3d788e8 --- /dev/null +++ b/modules/home/state.nix @@ -0,0 +1,43 @@ +{ config, lib, ... }: + +let + stateDir = "${config.home.homeDirectory}/.config/home-manager"; + + # Helper to read state from a file, with a default + readState = file: default: + if builtins.pathExists "${stateDir}/${file}" then + let + content = builtins.readFile "${stateDir}/${file}"; + cleanContent = lib.removeSuffix "\n" content; + in + if lib.hasSuffix ".json" file then + builtins.fromJSON cleanContent + else + cleanContent + else + default; + + # Unified state reading + togglesState = readState "state.json" {}; +in +{ + config.nomarchy = { + toggles = { + suspend = togglesState.suspend or true; + screensaver = togglesState.screensaver or true; + idle = togglesState.idle or true; + nightlight = togglesState.nightlight or false; + waybar = togglesState.waybar or true; + skipVsCodeTheme = togglesState.skipVsCodeTheme or false; + }; + nightlightTemperature = togglesState.nightlightTemperature or 4000; + theme = togglesState.theme or "nord"; + wallpaper = togglesState.wallpaper or ""; + hyprland = { + gaps_in = togglesState.hyprland.gaps_in or 5; + gaps_out = togglesState.hyprland.gaps_out or 10; + border_size = togglesState.hyprland.border_size or 2; + }; + fonts.monospace = togglesState.font or "JetBrainsMono Nerd Font"; + }; +} diff --git a/modules/home/stylix.nix b/modules/home/stylix.nix index 70926da..f8f1acc 100644 --- a/modules/home/stylix.nix +++ b/modules/home/stylix.nix @@ -4,14 +4,9 @@ let # Re-use our state-based logic palettes = import ../../themes/nomarchy-palettes.nix; - themeStateFile = "${config.home.homeDirectory}/.config/home-manager/theme-state.nix"; - activeThemeName = if builtins.pathExists themeStateFile then - lib.removeSuffix "\n" (builtins.readFile themeStateFile) - else "nord"; - - wallpaperStateFile = "${config.home.homeDirectory}/.config/home-manager/wallpaper-state.nix"; - activeWallpaper = if builtins.pathExists wallpaperStateFile then - lib.removeSuffix "\n" (builtins.readFile wallpaperStateFile) + activeThemeName = config.nomarchy.theme; + activeWallpaper = if config.nomarchy.wallpaper != "" then + config.nomarchy.wallpaper else "${../../themes/catppuccin/backgrounds/1-totoro.png}"; # Fallback # Map nix-colors palette to a format Stylix expects (attrset of hex strings) diff --git a/modules/home/theme-switcher.nix b/modules/home/theme-switcher.nix index f1cc1b6..a35ea23 100644 --- a/modules/home/theme-switcher.nix +++ b/modules/home/theme-switcher.nix @@ -6,55 +6,32 @@ let themeList = builtins.concatStringsSep "\\n" themeNames; nomarchy-theme-selector = pkgs.writeShellScriptBin "nomarchy-theme-selector" '' - STATE_DIR="$HOME/.config/home-manager" - THEME_STATE_FILE="$STATE_DIR/theme-state.nix" - WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix" - if [ -d "/etc/nixos/nomarchy/themes" ]; then - THEMES_DIR="/etc/nixos/nomarchy/themes" - elif [ -d "/etc/nomarchy/themes" ]; then - THEMES_DIR="/etc/nomarchy/themes" - else - THEMES_DIR="/etc/nixos/themes" - fi # This depends on where the repo is cloned - - mkdir -p "$STATE_DIR" - SELECTED_THEME=$(echo -e "${themeList}" | walker --dmenu) if [ -n "$SELECTED_THEME" ]; then - echo "$SELECTED_THEME" > "$THEME_STATE_FILE" - - # Try to find a background for this theme - BG_DIR="$THEMES_DIR/$SELECTED_THEME/backgrounds" - if [ -d "$BG_DIR" ]; then - BG=$(ls "$BG_DIR" | head -n 1) - if [ -n "$BG" ]; then - echo "$BG_DIR/$BG" > "$WALLPAPER_STATE_FILE" - swww img "$BG_DIR/$BG" --transition-type outer --transition-pos 0.85,0.97 --transition-step 90 & - fi - fi - - env-update + nomarchy-theme-set "$SELECTED_THEME" fi ''; nomarchy-font-selector = pkgs.writeShellScriptBin "nomarchy-font-selector" '' STATE_DIR="$HOME/.config/home-manager" - STATE_FILE="$STATE_DIR/font-state.nix" + STATE_FILE="$STATE_DIR/state.json" mkdir -p "$STATE_DIR" + [[ ! -f $STATE_FILE ]] && echo "{}" > "$STATE_FILE" # Simple list of common nerd fonts, could be expanded FONTS="JetBrainsMono Nerd Font\nRobotoMono Nerd Font\nFiraCode Nerd Font\nUbuntuMono Nerd Font" SELECTED_FONT=$(echo -e "$FONTS" | walker --dmenu) if [ -n "$SELECTED_FONT" ]; then - echo "$SELECTED_FONT" > "$STATE_FILE" + TMP_JSON=$(mktemp) + jq ".font = \"$SELECTED_FONT\"" "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE" env-update fi ''; nomarchy-wallpaper-selector = pkgs.writeShellScriptBin "nomarchy-wallpaper-selector" '' STATE_DIR="$HOME/.config/home-manager" - WALLPAPER_STATE_FILE="$STATE_DIR/wallpaper-state.nix" + STATE_FILE="$STATE_DIR/state.json" if [ -d "/etc/nixos/nomarchy/themes" ]; then THEMES_DIR="/etc/nixos/nomarchy/themes" elif [ -d "/etc/nomarchy/themes" ]; then @@ -64,13 +41,15 @@ let fi mkdir -p "$STATE_DIR" + [[ ! -f $STATE_FILE ]] && echo "{}" > "$STATE_FILE" # List all images in all themes backgrounds WALLPAPERS=$(find "$THEMES_DIR" -type f \( -name "*.jpg" -o -name "*.png" \)) SELECTED_WP=$(echo -e "$WALLPAPERS" | walker --dmenu) if [ -n "$SELECTED_WP" ]; then - echo "$SELECTED_WP" > "$WALLPAPER_STATE_FILE" + TMP_JSON=$(mktemp) + jq ".wallpaper = \"$SELECTED_WP\"" "$STATE_FILE" > "$TMP_JSON" && mv "$TMP_JSON" "$STATE_FILE" swww img "$SELECTED_WP" --transition-type outer --transition-pos 0.85,0.97 --transition-step 90 & env-update fi