refactor(#107): theme-state.json → state.json, theme-sync → state-sync
Some checks failed
Check / eval (push) Has been cancelled
Some checks failed
Check / eval (push) Has been cancelled
The machine flake's git-tracked settings file is system state, not "theme" only — rename it to state.json. CLI becomes nomarchy-state-sync with a nomarchy-theme-sync symlink for scripts and muscle memory. Eval (mkFlake, doctor, lifecycle) still accepts theme-state.json; the next write migrates to state.json and removes the legacy file. Documented in MIGRATION.md; drop the CLI alias after release notes.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# Auto time-of-day theme switch (BACKLOG #79, VISION § D). A user timer
|
||||
# periodically runs `nomarchy-theme-sync auto`, which reads
|
||||
# periodically runs `nomarchy-state-sync auto`, which reads
|
||||
# settings.autoTheme = { enable, day, night, sunrise, sunset } from the
|
||||
# state file and applies the day or night preset for the current clock —
|
||||
# through the SAME one engine as a manual `apply` (no second pipeline).
|
||||
@@ -20,7 +20,7 @@ lib.mkIf (config.nomarchy.settings.autoTheme.enable or false) {
|
||||
# The rebuild (`home-manager switch`) and its tools resolve from the
|
||||
# system + per-user profiles — same PATH shape nomarchy-updates uses.
|
||||
Environment = "PATH=/run/current-system/sw/bin:/etc/profiles/per-user/${config.home.username}/bin";
|
||||
ExecStart = "${pkgs.nomarchy-theme-sync}/bin/nomarchy-theme-sync auto";
|
||||
ExecStart = "${pkgs.nomarchy-state-sync}/bin/nomarchy-state-sync auto";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
{
|
||||
imports = [
|
||||
./options.nix # the nomarchy.* option surface
|
||||
./theme.nix # ingests theme-state.json, owns the live-sync hooks
|
||||
./theme.nix # ingests state.json, owns the live-sync hooks
|
||||
./stylix.nix # GTK/Qt/cursor/fonts from the same JSON
|
||||
./hyprland.nix
|
||||
./waybar.nix
|
||||
@@ -106,8 +106,8 @@
|
||||
# (system nixpkgs.config alone does not cover those entry points).
|
||||
NIXPKGS_ALLOW_UNFREE = "1";
|
||||
|
||||
# Where the Nomarchy flake (and therefore theme-state.json) lives on
|
||||
# disk. nomarchy-theme-sync writes its state here; rebuilds read from
|
||||
# Where the Nomarchy flake (and therefore state.json) lives on
|
||||
# disk. nomarchy-state-sync writes its state here; rebuilds read from
|
||||
# here. Clone/symlink your flake to this path.
|
||||
NOMARCHY_PATH = "$HOME/.nomarchy";
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
Environment = [
|
||||
"PATH=${lib.makeBinPath [
|
||||
pkgs.libnotify
|
||||
pkgs.nomarchy-theme-sync
|
||||
pkgs.nomarchy-state-sync
|
||||
pkgs.coreutils
|
||||
]}"
|
||||
"NOMARCHY_PATH=%h/.nomarchy"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Hyprland — fully driven by config.nomarchy.theme (theme-state.json).
|
||||
# Hyprland — fully driven by config.nomarchy.theme (state.json).
|
||||
# Gaps, borders and colors are baked from the JSON at eval time; theme
|
||||
# changes arrive via `home-manager switch`.
|
||||
{ config, lib, pkgs, ... }:
|
||||
@@ -8,7 +8,7 @@ let
|
||||
c = t.colors;
|
||||
inherit (config.nomarchy.lib) rgb rgba;
|
||||
|
||||
# nomarchy-theme-sync — the in-flake state writer the keyboard watcher uses
|
||||
# nomarchy-state-sync — the in-flake state writer the keyboard watcher uses
|
||||
# to remember per-device layouts (same path night-light's toggle takes).
|
||||
sync = lib.getExe config.nomarchy.package;
|
||||
|
||||
@@ -883,7 +883,7 @@ in
|
||||
"awww-daemon"
|
||||
# Paint the wallpaper as soon as the session is up (waits for
|
||||
# the daemon internally).
|
||||
"nomarchy-theme-sync wallpaper"
|
||||
"nomarchy-state-sync wallpaper"
|
||||
# Polkit authentication agent — without one, EVERY pkexec/polkit
|
||||
# prompt in the session fails silently (btrfs-assistant-launcher
|
||||
# was the discovery case). hyprpolkitagent is Hyprland's own Qt
|
||||
@@ -903,8 +903,8 @@ in
|
||||
];
|
||||
|
||||
# ── Theme-driven look ──────────────────────────────────────────
|
||||
# These flow from theme-state.json and stay at NORMAL priority:
|
||||
# change them with `nomarchy-theme-sync set ui.<key>` (the intended
|
||||
# These flow from state.json and stay at NORMAL priority:
|
||||
# change them with `nomarchy-state-sync set ui.<key>` (the intended
|
||||
# path), or lib.mkForce in home.nix to hardcode against the theme.
|
||||
# The non-theme knobs around them are lib.mkDefault — override
|
||||
# those with a plain home.nix assignment. See docs/OVERRIDES.md.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# hyprlock + hypridle — screen locking and idle management, themed from
|
||||
# theme-state.json. One concern, one file: hypridle drives WHEN (idle
|
||||
# state.json. One concern, one file: hypridle drives WHEN (idle
|
||||
# lock, display off, suspend, lock-before-sleep), hyprlock is the
|
||||
# themed lock screen itself (also behind the power menu's Lock entry).
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
# home-manager switch (progress via notify-send).
|
||||
{ mods = "$mod"; key = "T"; action = "exec, nomarchy-menu theme"; desc = "Theme picker"; group = "Menu"; }
|
||||
# Cycle the current theme's wallpapers (instant, no rebuild).
|
||||
{ mods = "$mod SHIFT"; key = "T"; action = "exec, nomarchy-theme-sync bg next"; desc = "Next wallpaper"; group = "Menu"; }
|
||||
{ mods = "$mod SHIFT"; key = "T"; action = "exec, nomarchy-state-sync bg next"; desc = "Next wallpaper"; group = "Menu"; }
|
||||
|
||||
# Power menu via the dispatcher. Not Escape: Super+Escape gets
|
||||
# swallowed before reaching the dispatcher on some setups.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Kitty — Nomarchy's only terminal, themed from theme-state.json.
|
||||
# Kitty — Nomarchy's only terminal, themed from state.json.
|
||||
# Colors, fonts and the full 16-color ANSI palette are baked from the
|
||||
# JSON at eval time (same contract Ghostty used to have). Always
|
||||
# installed: SUPER+Return, SUPER+E, doctor, calendar, and $TERMINAL
|
||||
|
||||
@@ -88,11 +88,11 @@ in
|
||||
# ── Required ───────────────────────────────────────────────────
|
||||
stateFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
example = lib.literalExpression "./theme-state.json";
|
||||
example = lib.literalExpression "./state.json";
|
||||
description = ''
|
||||
Path to theme-state.json, the single source of truth for all UI
|
||||
Path to state.json, the single source of truth for all UI
|
||||
configuration. Must live inside your flake (so evaluation stays
|
||||
pure) and be git-tracked. nomarchy-theme-sync writes to the
|
||||
pure) and be git-tracked. nomarchy-state-sync writes to the
|
||||
on-disk copy; rebuilds bake it into the generation.
|
||||
'';
|
||||
};
|
||||
@@ -182,9 +182,9 @@ in
|
||||
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.nomarchy-theme-sync;
|
||||
defaultText = lib.literalExpression "pkgs.nomarchy-theme-sync";
|
||||
description = "The nomarchy-theme-sync package (provided by overlays.default).";
|
||||
default = pkgs.nomarchy-state-sync;
|
||||
defaultText = lib.literalExpression "pkgs.nomarchy-state-sync";
|
||||
description = "The nomarchy-state-sync package (provided by overlays.default).";
|
||||
};
|
||||
|
||||
themesDir = lib.mkOption {
|
||||
@@ -379,7 +379,7 @@ in
|
||||
type = lib.types.bool;
|
||||
default = config.nomarchy.settings.fingerprint.pam or false;
|
||||
defaultText = lib.literalExpression
|
||||
"(settings.fingerprint.pam from theme-state.json) or false";
|
||||
"(settings.fingerprint.pam from state.json) or false";
|
||||
description = ''
|
||||
Unlock the lock screen with a fingerprint as well as the password, and
|
||||
say so on the input field.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# lock). The media keys drive it via swayosd-client (it performs the
|
||||
# action AND shows the OSD), so changing volume or brightness gives the
|
||||
# visual feedback that bare wpctl/brightnessctl didn't. Themed from
|
||||
# theme-state.json. Brightness needs the backlight udev rule shipped
|
||||
# state.json. Brightness needs the backlight udev rule shipped
|
||||
# system-side (modules/nixos/default.nix → services.udev.packages).
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# rofi (2.0, native Wayland on 26.05) — launcher + dmenu renderer for
|
||||
# the menu system, themed from theme-state.json. rofi's .rasi is far more
|
||||
# the menu system, themed from state.json. rofi's .rasi is far more
|
||||
# expressive than a flat scheme, so the generated theme styles each
|
||||
# element (accent border, highlighted selection, rounded inputbar); a
|
||||
# themes/<slug>/rofi.rasi whole-swap replaces it entirely.
|
||||
@@ -71,7 +71,7 @@ let
|
||||
|
||||
# One grid row per theme (square thumb + name, ✓ on the active one), and a
|
||||
# Name→slug map so the picked label resolves back to the preset that
|
||||
# nomarchy-theme-sync applies (pretty names ≠ slugs, hence the map). Themes
|
||||
# nomarchy-state-sync applies (pretty names ≠ slugs, hence the map). Themes
|
||||
# with no preview degrade to a plain-name row.
|
||||
themeRows = lib.concatMapStringsSep "\n" (th:
|
||||
let label = th.name + lib.optionalString (th.slug == t.slug) " ✓";
|
||||
@@ -190,7 +190,7 @@ let
|
||||
nomarchy-menu = pkgs.writeShellScriptBin "nomarchy-menu" ''
|
||||
# Nomarchy menu dispatcher — thin presentation layer over
|
||||
# `rofi -dmenu` (via rofi_menu helper); actions delegate to
|
||||
# nomarchy-theme-sync, systemctl, hyprctl and friends. Menu entries
|
||||
# nomarchy-state-sync, systemctl, hyprctl and friends. Menu entries
|
||||
# carry real icons from the theme's icon set (Papirus) via rofi's
|
||||
# per-row icon protocol — see row() below. `nomarchy-menu` with no
|
||||
# argument shows the module picker.
|
||||
@@ -350,7 +350,7 @@ let
|
||||
# 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
|
||||
# rows drive the same state-sync writer as batterylimit. Each half
|
||||
# self-gates on its hardware, so a desktop with neither just toasts.
|
||||
haveppd=false; command -v powerprofilesctl >/dev/null 2>&1 && haveppd=true
|
||||
havecharge=false; has_charge_threshold && havecharge=true
|
||||
@@ -359,7 +359,7 @@ let
|
||||
exit 0
|
||||
fi
|
||||
curp=""; $haveppd && curp=$(powerprofilesctl get 2>/dev/null)
|
||||
curc=$(nomarchy-theme-sync get settings.power.batteryChargeLimit 2>/dev/null)
|
||||
curc=$(nomarchy-state-sync get settings.power.batteryChargeLimit 2>/dev/null)
|
||||
choice=$( {
|
||||
if $haveppd; then
|
||||
powerprofilesctl list 2>/dev/null | sed -nE 's/^[* ] ([a-z-]+):$/\1/p' \
|
||||
@@ -384,7 +384,7 @@ let
|
||||
# allows users to restart it) so a non-writable sysfs node still
|
||||
# updates. Fallback: direct echo if the node is group-writable.
|
||||
set_limit() {
|
||||
nomarchy-theme-sync --quiet set settings.power.batteryChargeLimit "$1" --no-switch
|
||||
nomarchy-state-sync --quiet set settings.power.batteryChargeLimit "$1" --no-switch
|
||||
n="$1"; [ "$n" = null ] && n=100
|
||||
# Root oneshot sets Custom charge type (Dell) + thresholds.
|
||||
applied=
|
||||
@@ -452,7 +452,7 @@ ${themeRows}
|
||||
[ "$choice" = "$BACK" ] && exec "$0"
|
||||
choice="''${choice% ✓}" # drop the active marker if present
|
||||
slug="''${THEME_SLUG[$choice]:-}"
|
||||
[ -n "$slug" ] && exec nomarchy-theme-sync apply "$slug" ;;
|
||||
[ -n "$slug" ] && exec nomarchy-state-sync apply "$slug" ;;
|
||||
|
||||
clipboard)
|
||||
sel=$( { cliphist list; printf '%s\n' "$BACK"; } | rofi_menu -p clip) || exit 0
|
||||
@@ -691,7 +691,7 @@ ${themeRows}
|
||||
pos=$(printf '%s' "$mons" | jq -r --arg n "$name" '.[]|select(.name==$n)|"\(.x)x\(.y)"')
|
||||
scale=$(printf '%s' "$mons" | jq -r --arg n "$name" '.[]|select(.name==$n)|.scale')
|
||||
if hyprctl keyword monitor "$name,$mode,$pos,$scale" >/dev/null 2>&1; then
|
||||
nomarchy-theme-sync --quiet set "settings.monitors.$name" "$mode" --no-switch
|
||||
nomarchy-state-sync --quiet set "settings.monitors.$name" "$mode" --no-switch
|
||||
got=$(hyprctl monitors -j | jq -r --arg n "$name" \
|
||||
'.[]|select(.name==$n)|"\(.width)x\(.height)@\(.refreshRate|round)"')
|
||||
notify-send "Display" "$name → $mode (now ${got:-?})"
|
||||
@@ -759,7 +759,7 @@ ${themeRows}
|
||||
# Power / Keybindings). SUPER+T / SUPER+SHIFT+T still hit leaves.
|
||||
choice=$( {
|
||||
row "Theme${menuHint "theme"}" preferences-desktop-theme
|
||||
row "Next wallpaper${hintForAction "exec, nomarchy-theme-sync bg next"}" preferences-desktop-wallpaper
|
||||
row "Next wallpaper${hintForAction "exec, nomarchy-state-sync bg next"}" preferences-desktop-wallpaper
|
||||
row "Reset wallpaper (auto)" preferences-desktop-wallpaper
|
||||
# Use the toggle script (knows hyprsunset vs wlsunset); a hard-coded
|
||||
# hyprsunset-only check always showed (off) in geo mode and when
|
||||
@@ -768,7 +768,7 @@ ${themeRows}
|
||||
then row "Night light (on)" weather-clear-night
|
||||
else row "Night light (off)" weather-clear-night
|
||||
fi
|
||||
if [ "$(nomarchy-theme-sync get settings.autoTheme.enable 2>/dev/null)" = true ]
|
||||
if [ "$(nomarchy-state-sync get settings.autoTheme.enable 2>/dev/null)" = true ]
|
||||
then row "Auto theme (on)" preferences-desktop-theme
|
||||
else row "Auto theme (off)" preferences-desktop-theme
|
||||
fi
|
||||
@@ -778,8 +778,8 @@ ${themeRows}
|
||||
"$BACK") exec "$0" ;;
|
||||
*"Auto theme"*) exec "$0" autotheme ;;
|
||||
*Theme*) exec "$0" theme ;;
|
||||
*"Next wallpaper"*) exec nomarchy-theme-sync bg next ;;
|
||||
*"Reset wallpaper"*) exec nomarchy-theme-sync bg auto ;;
|
||||
*"Next wallpaper"*) exec nomarchy-state-sync bg next ;;
|
||||
*"Reset wallpaper"*) exec nomarchy-state-sync bg auto ;;
|
||||
*"Night light"*) exec "$0" nightlight ;;
|
||||
esac ;;
|
||||
|
||||
@@ -796,7 +796,7 @@ ${themeRows}
|
||||
if [ "$p" = "$active" ]; then printf '● %s\n' "$p"; else printf '○ %s\n' "$p"; fi
|
||||
done
|
||||
printf 'Base layout\n'
|
||||
if [ "$(nomarchy-theme-sync get settings.displayProfileAuto 2>/dev/null)" = true ]
|
||||
if [ "$(nomarchy-state-sync get settings.displayProfileAuto 2>/dev/null)" = true ]
|
||||
then printf 'Auto-switch (on)\n'
|
||||
else printf 'Auto-switch (off)\n'
|
||||
fi
|
||||
@@ -808,11 +808,11 @@ ${themeRows}
|
||||
*"Auto-switch"*)
|
||||
# Instant in-flake flag; the watcher reads it live on the next
|
||||
# output change — no rebuild, no unit juggling.
|
||||
if [ "$(nomarchy-theme-sync get settings.displayProfileAuto 2>/dev/null)" = true ]; then
|
||||
nomarchy-theme-sync --quiet set settings.displayProfileAuto false --no-switch
|
||||
if [ "$(nomarchy-state-sync get settings.displayProfileAuto 2>/dev/null)" = true ]; then
|
||||
nomarchy-state-sync --quiet set settings.displayProfileAuto false --no-switch
|
||||
notify-send "Display profiles" "Auto-switch off — profiles change only from this menu."
|
||||
else
|
||||
nomarchy-theme-sync --quiet set settings.displayProfileAuto true --no-switch
|
||||
nomarchy-state-sync --quiet set settings.displayProfileAuto true --no-switch
|
||||
notify-send "Display profiles" "Auto-switch on — plugging/unplugging outputs picks the matching profile."
|
||||
fi
|
||||
exec "$0" display-profile ;;
|
||||
@@ -869,12 +869,12 @@ ${themeRows}
|
||||
# (settings.autoTheme, applied by the nomarchy-auto-theme timer from
|
||||
# autotheme.nix). The enable flag GATES the timer's install, so
|
||||
# turning it *on* must rebuild; day/night/times are read live by
|
||||
# `nomarchy-theme-sync auto`, so those writes are instant
|
||||
# `nomarchy-state-sync auto`, so those writes are instant
|
||||
# (--no-switch). Enabling writes the flag then `auto --force`, so a
|
||||
# single rebuild both installs the timer and applies the right theme
|
||||
# now. Disabling is instant: the flag flips and `auto` self-gates to
|
||||
# a no-op, so the lingering timer does nothing until the next rebuild.
|
||||
at_get() { nomarchy-theme-sync get "settings.autoTheme.$1" 2>/dev/null; }
|
||||
at_get() { nomarchy-state-sync get "settings.autoTheme.$1" 2>/dev/null; }
|
||||
en=$(at_get enable); day=$(at_get day); night=$(at_get night)
|
||||
sunrise=$(at_get sunrise); sunset=$(at_get sunset)
|
||||
choice=$( {
|
||||
@@ -892,25 +892,25 @@ ${themeRows}
|
||||
"$BACK") exec "$0" lookfeel ;;
|
||||
*"Auto theme"*)
|
||||
if [ "$en" = true ]; then
|
||||
nomarchy-theme-sync --quiet set settings.autoTheme.enable false --no-switch
|
||||
nomarchy-state-sync --quiet set settings.autoTheme.enable false --no-switch
|
||||
notify-send "Auto theme" "Off — current theme stays."
|
||||
exec "$0" autotheme
|
||||
fi
|
||||
# Need a day + night pair before enabling; default the summer pair.
|
||||
[ -n "$day" ] || nomarchy-theme-sync --quiet set settings.autoTheme.day summer-day --no-switch
|
||||
[ -n "$night" ] || nomarchy-theme-sync --quiet set settings.autoTheme.night summer-night --no-switch
|
||||
nomarchy-theme-sync --quiet set settings.autoTheme.enable true --no-switch
|
||||
[ -n "$day" ] || nomarchy-state-sync --quiet set settings.autoTheme.day summer-day --no-switch
|
||||
[ -n "$night" ] || nomarchy-state-sync --quiet set settings.autoTheme.night summer-night --no-switch
|
||||
nomarchy-state-sync --quiet set settings.autoTheme.enable true --no-switch
|
||||
notify-send "Auto theme" "On — applying the theme for now…"
|
||||
exec nomarchy-theme-sync auto --force ;; # one rebuild: install timer + apply
|
||||
exec nomarchy-state-sync auto --force ;; # one rebuild: install timer + apply
|
||||
"Day theme"*)
|
||||
slug=$( { nomarchy-theme-sync list; printf '%s\n' "$BACK"; } | rofi_menu -p "Day theme") || exec "$0" autotheme
|
||||
slug=$( { nomarchy-state-sync list; printf '%s\n' "$BACK"; } | rofi_menu -p "Day theme") || exec "$0" autotheme
|
||||
[ "$slug" != "$BACK" ] && [ -n "$slug" ] \
|
||||
&& nomarchy-theme-sync --quiet set settings.autoTheme.day "$slug" --no-switch
|
||||
&& nomarchy-state-sync --quiet set settings.autoTheme.day "$slug" --no-switch
|
||||
exec "$0" autotheme ;;
|
||||
"Night theme"*)
|
||||
slug=$( { nomarchy-theme-sync list; printf '%s\n' "$BACK"; } | rofi_menu -p "Night theme") || exec "$0" autotheme
|
||||
slug=$( { nomarchy-state-sync list; printf '%s\n' "$BACK"; } | rofi_menu -p "Night theme") || exec "$0" autotheme
|
||||
[ "$slug" != "$BACK" ] && [ -n "$slug" ] \
|
||||
&& nomarchy-theme-sync --quiet set settings.autoTheme.night "$slug" --no-switch
|
||||
&& nomarchy-state-sync --quiet set settings.autoTheme.night "$slug" --no-switch
|
||||
exec "$0" autotheme ;;
|
||||
"Sunrise"*|"Sunset"*)
|
||||
key=sunrise; label=Sunrise; cur="''${sunrise:-07:00}"
|
||||
@@ -919,7 +919,7 @@ ${themeRows}
|
||||
case "$t" in
|
||||
""|"$BACK") : ;;
|
||||
[01][0-9]:[0-5][0-9]|2[0-3]:[0-5][0-9])
|
||||
nomarchy-theme-sync --quiet set "settings.autoTheme.$key" "$t" --no-switch ;;
|
||||
nomarchy-state-sync --quiet set "settings.autoTheme.$key" "$t" --no-switch ;;
|
||||
*) notify-send "Auto theme" "Ignored '$t' — use HH:MM (24-hour)." ;;
|
||||
esac
|
||||
exec "$0" autotheme ;;
|
||||
@@ -945,18 +945,18 @@ ${themeRows}
|
||||
|
||||
autocommit)
|
||||
# Toggle opt-in auto-commit: every menu/theme mutation also commits
|
||||
# theme-state.json (that file only) in the downstream flake, so
|
||||
# state.json (that file only) in the downstream flake, so
|
||||
# settings history is `git log`; nomarchy-pull/-rebuild/-home
|
||||
# additionally sweep everything else dirty (hand edits, lock bumps)
|
||||
# into a commit first. Nothing in Nix consumes the flag —
|
||||
# the tool reads the live state on each write — so the toggle is
|
||||
# instant, no rebuild. The off-write commits too (the tool fires
|
||||
# when the flag was on before OR after), keeping history consistent.
|
||||
if [ "$(nomarchy-theme-sync get settings.autoCommit 2>/dev/null)" = true ]; then
|
||||
nomarchy-theme-sync --quiet set settings.autoCommit false --no-switch
|
||||
if [ "$(nomarchy-state-sync get settings.autoCommit 2>/dev/null)" = true ]; then
|
||||
nomarchy-state-sync --quiet set settings.autoCommit false --no-switch
|
||||
notify-send "Auto-commit" "Off — menu changes stay uncommitted in your flake."
|
||||
else
|
||||
nomarchy-theme-sync --quiet set settings.autoCommit true --no-switch
|
||||
nomarchy-state-sync --quiet set settings.autoCommit true --no-switch
|
||||
notify-send "Auto-commit" "On — menu changes commit; rebuilds sweep pending edits in too."
|
||||
fi
|
||||
exit 0 ;;
|
||||
@@ -1017,7 +1017,7 @@ ${themeRows}
|
||||
# CLI (services.fprintd). Enroll is interactive → terminal.
|
||||
command -v fprintd-list >/dev/null 2>&1 \
|
||||
|| { notify-send "Fingerprint" "fprintd not available (nomarchy.hardware.fingerprint.enable?)."; exit 0; }
|
||||
pam=$(nomarchy-theme-sync get settings.fingerprint.pam 2>/dev/null || echo false)
|
||||
pam=$(nomarchy-state-sync get settings.fingerprint.pam 2>/dev/null || echo false)
|
||||
case "$pam" in true|True) pam_label="Fingerprint (on)" ;; *) pam_label="Fingerprint (off)" ;; esac
|
||||
choice=$( {
|
||||
# The switch leads: it is the decision this menu exists for, and
|
||||
@@ -1178,7 +1178,7 @@ ${themeRows}
|
||||
&& row "Keyboard${menuHint "keyboard"}" preferences-desktop-keyboard
|
||||
command -v system-config-printer >/dev/null 2>&1 && row "Printers" printer
|
||||
row "Do Not Disturb${menuHint "dnd"}" notification-disabled
|
||||
if [ "$(nomarchy-theme-sync get settings.autoTimezone 2>/dev/null)" = true ]
|
||||
if [ "$(nomarchy-state-sync get settings.autoTimezone 2>/dev/null)" = true ]
|
||||
then row "Auto timezone (on)" preferences-system-time
|
||||
else row "Auto timezone (off)" preferences-system-time
|
||||
fi
|
||||
@@ -1186,15 +1186,15 @@ ${themeRows}
|
||||
# greeter asks; that's the prompt the Fingerprint switch feeds.
|
||||
if command -v nomarchy-autologin >/dev/null 2>&1; then
|
||||
# Unset (get exits 1, empty) and null both read as off. "None" is
|
||||
# what an older theme-sync printed for null — accepted so a menu
|
||||
# what an older state-sync printed for null — accepted so a menu
|
||||
# from a newer generation can't misreport against an older tool.
|
||||
case "$(nomarchy-theme-sync get settings.greeter.autoLogin 2>/dev/null)" in
|
||||
case "$(nomarchy-state-sync get settings.greeter.autoLogin 2>/dev/null)" in
|
||||
null|""|None) row "Auto-login (off)" system-users ;;
|
||||
*) row "Auto-login (on)" system-users ;;
|
||||
esac
|
||||
fi
|
||||
if [ -e "''${NOMARCHY_PATH:-$HOME/.nomarchy}/.git" ]; then
|
||||
if [ "$(nomarchy-theme-sync get settings.autoCommit 2>/dev/null)" = true ]
|
||||
if [ "$(nomarchy-state-sync get settings.autoCommit 2>/dev/null)" = true ]
|
||||
then row "Auto-commit (on)" git
|
||||
else row "Auto-commit (off)" git
|
||||
fi
|
||||
@@ -1255,7 +1255,7 @@ ${themeRows}
|
||||
|| { notify-send "Battery limit" \
|
||||
"This machine's firmware does not expose a charge-stop control (no charge_control_end_threshold in /sys), so a charge limit cannot be set here. The battery still works normally — this is a hardware capability, not a Nomarchy problem."
|
||||
exit 0; }
|
||||
cur=$(nomarchy-theme-sync get settings.power.batteryChargeLimit 2>/dev/null)
|
||||
cur=$(nomarchy-state-sync get settings.power.batteryChargeLimit 2>/dev/null)
|
||||
sel=$( {
|
||||
row "80% (recommended)" battery-080
|
||||
row "90%" battery-090
|
||||
@@ -1265,7 +1265,7 @@ ${themeRows}
|
||||
back
|
||||
} | rofi_menu -show-icons -p "Battery limit (now: ''${cur:-default})") || exit 0
|
||||
set_limit() {
|
||||
nomarchy-theme-sync --quiet set settings.power.batteryChargeLimit "$1" --no-switch
|
||||
nomarchy-state-sync --quiet set settings.power.batteryChargeLimit "$1" --no-switch
|
||||
n="$1"; [ "$n" = null ] && n=100
|
||||
applied=
|
||||
if systemctl restart nomarchy-battery-charge-limit.service 2>/dev/null; then
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Stylix — themes the long tail of applications (GTK, Qt, cursors,
|
||||
# fonts) from the same theme-state.json that drives the live engine.
|
||||
# fonts) from the same state.json that drives the live engine.
|
||||
#
|
||||
# Division of labour: the hot-reload trio (Hyprland, Waybar, Kitty)
|
||||
# is owned by the Nomarchy engine and updates instantly; everything
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# swaync — notification daemon + control centre, themed from
|
||||
# theme-state.json. Until this shipped, nothing rendered notify-send at
|
||||
# state.json. Until this shipped, nothing rendered notify-send at
|
||||
# all: the theme-switch progress toasts, the CLI's font warnings and the
|
||||
# live ISO's welcome message were all invisible.
|
||||
{ config, lib, ... }:
|
||||
@@ -29,7 +29,7 @@ in
|
||||
};
|
||||
|
||||
style = ''
|
||||
/* Palette baked from theme-state.json. Only roles guaranteed to
|
||||
/* Palette baked from state.json. Only roles guaranteed to
|
||||
contrast @base in EVERY palette are used: subtext/surface mean
|
||||
"on-surface" in some light themes (summer-day: subtext==base,
|
||||
surface==text — body text was invisible on hardware, item 25).
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Nomarchy theming engine.
|
||||
#
|
||||
# nomarchy.stateFile (theme-state.json, inside the consuming flake) is
|
||||
# nomarchy.stateFile (state.json, inside the consuming flake) is
|
||||
# ingested at evaluation time — pure, because flake files are store
|
||||
# paths — and exposed to every other module as `config.nomarchy.theme`.
|
||||
#
|
||||
# Theme changes are fully Home Manager managed: `nomarchy-theme-sync
|
||||
# Theme changes are fully Home Manager managed: `nomarchy-state-sync
|
||||
# apply <theme>` writes the JSON and runs `home-manager switch`, baking
|
||||
# everything (Hyprland, Waybar, Kitty, btop, Stylix) into one
|
||||
# read-only generation. No runtime patching, no partial states; theme
|
||||
@@ -13,17 +13,17 @@
|
||||
# The one runtime exception is the wallpaper (swww is imperative by
|
||||
# nature): applied at session start, after every switch (hook below), and
|
||||
# after output hotplug (hyprland.nix); cycled instantly with
|
||||
# `nomarchy-theme-sync bg next`.
|
||||
# `nomarchy-state-sync bg next`.
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.nomarchy;
|
||||
|
||||
# Fail-closed load: missing / empty / non-object get a short pointer at
|
||||
# the template + `nomarchy-theme-sync validate`, not a raw readFile stack
|
||||
# the template + `nomarchy-state-sync validate`, not a raw readFile stack
|
||||
# from deep inside a consumer (nightlight, hyprland, …). Field-level
|
||||
# checks below still run on the merged result.
|
||||
themeState = import ../theme-state-read.nix { inherit lib; } cfg.stateFile;
|
||||
themeState = import ../state-read.nix { inherit lib; } cfg.stateFile;
|
||||
|
||||
# Defaults guarantee evaluation succeeds on a sparse or older state
|
||||
# file (e.g. one written before a schema field was added). The shipped
|
||||
@@ -92,7 +92,7 @@ let
|
||||
parsed = lib.recursiveUpdate defaults themeState;
|
||||
|
||||
# ── Friendly eval-time validation ───────────────────────────────────
|
||||
# The same schema nomarchy-theme-sync enforces before every write. A
|
||||
# The same schema nomarchy-state-sync enforces before every write. A
|
||||
# HAND-edited state file (the one path that bypasses the tool) must
|
||||
# fail with the field, the problem, and the fix — not a Nix stack
|
||||
# trace deep in some consumer. Checks run on `parsed` (after the
|
||||
@@ -137,14 +137,14 @@ let
|
||||
if problems == [ ] then parsed
|
||||
else throw ''
|
||||
|
||||
Nomarchy: your theme-state.json is invalid:
|
||||
Nomarchy: your state.json is invalid:
|
||||
${lib.concatMapStrings (p: " ✖ ${p}\n") problems}
|
||||
Fix the named field(s) in the theme-state.json of your flake
|
||||
checkout (usually ~/.nomarchy/theme-state.json — the store copy at
|
||||
Fix the named field(s) in the state.json of your flake
|
||||
checkout (usually ~/.nomarchy/state.json — the store copy at
|
||||
${toString cfg.stateFile} is a snapshot of it). The tool prints
|
||||
the same report with per-field fixes: `nomarchy-theme-sync
|
||||
the same report with per-field fixes: `nomarchy-state-sync
|
||||
validate`. Re-applying any preset resets all appearance fields:
|
||||
`nomarchy-theme-sync apply boreal`.'';
|
||||
`nomarchy-state-sync apply boreal`.'';
|
||||
|
||||
# A border value is a palette key (look it up in colors) unless it's
|
||||
# already a literal hex. Unknown roles are rejected by the field checks
|
||||
@@ -155,7 +155,7 @@ let
|
||||
|
||||
Nomarchy: border role "${v}" is not in the palette (colors.*).
|
||||
Use one of: ${lib.concatStringsSep ", " colorRoles}
|
||||
or a literal "#RRGGBB". Validate with: nomarchy-theme-sync validate'');
|
||||
or a literal "#RRGGBB". Validate with: nomarchy-state-sync validate'');
|
||||
border = {
|
||||
active = resolveColor checked.border.active;
|
||||
inactive = resolveColor checked.border.inactive;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# timezone. Waybar's clock module captures the zone once at construction, so a
|
||||
# runtime timezone change (automatic-timezoned, nomarchy.system.autoTimezone)
|
||||
# would NOT show until a relogin. A tiny watcher subscribes to timedate1's
|
||||
# change signal and reloads Waybar (SIGUSR2 = the same reload theme-sync uses),
|
||||
# change signal and reloads Waybar (SIGUSR2 = the same reload state-sync uses),
|
||||
# so the clock follows your location live. Also catches a manual
|
||||
# `timedatectl set-timezone`.
|
||||
#
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Waybar — two-tier theming:
|
||||
#
|
||||
# 1. Default: structure, fonts, geometry AND palette baked from
|
||||
# theme-state.json (colors as GTK named colors, @define-color).
|
||||
# state.json (colors as GTK named colors, @define-color).
|
||||
#
|
||||
# 2. Whole-swap: themes with their own visual identity ship
|
||||
# <themesDir>/<slug>/waybar.css (and optionally waybar.jsonc) which
|
||||
@@ -35,7 +35,7 @@ let
|
||||
# Waybar supervisor — exec-once has no restart, so a crashed bar used to
|
||||
# leave the session bar-less until relogin (seen on hardware: a theme
|
||||
# switch crashed waybar mid-reload). Respawns on ANY exit — a plain
|
||||
# `pkill -x waybar` is now a clean restart, which nomarchy-theme-sync
|
||||
# `pkill -x waybar` is now a clean restart, which nomarchy-state-sync
|
||||
# uses instead of the crash-prone in-place SIGUSR2 reload when it sees
|
||||
# this supervisor running. Crash-loop guard: 5 exits within 10s of
|
||||
# their start → give up with a critical notification instead of
|
||||
@@ -377,7 +377,7 @@ let
|
||||
};
|
||||
|
||||
generatedStyle = ''
|
||||
/* Palette baked from theme-state.json */
|
||||
/* Palette baked from state.json */
|
||||
${colorDefs}
|
||||
|
||||
/* NB: this `*` reset reaches the SNI tray menus Waybar hosts too
|
||||
@@ -522,7 +522,7 @@ in
|
||||
# on a warm relogin — it started before the socket was up, exited, landed
|
||||
# in `failed`, and was never retried, so the bar vanished. exec-once only
|
||||
# fires once Hyprland is up, dodging the race; theme switches reload the
|
||||
# running bar via SIGUSR2 (nomarchy-theme-sync). No uwsm here to manage the
|
||||
# running bar via SIGUSR2 (nomarchy-state-sync). No uwsm here to manage the
|
||||
# session target, so we don't depend on its lifecycle.
|
||||
systemd.enable = false;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# yazi — the flagship file manager: a fast, keyboard-driven TUI that
|
||||
# fits the distro's identity (Kitty graphics previews, rofi
|
||||
# menus, everything from one JSON). Themed from theme-state.json and
|
||||
# menus, everything from one JSON). Themed from state.json and
|
||||
# shipped with a curated plugin set. The GUI half (Thunar, "open folder"
|
||||
# handler) is nomarchy.system.fileManager on the system side.
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user