feat(overrides): wire nomarchy.overrides.paths into xdg.configFile

The option surface (`enable`, `paths`) lived in core/home/overrides.nix
since 2026-05-18 but didn't do anything — paths was a reserved
attrset that never reached xdg.configFile.

Now wired: every entry in nomarchy.overrides.paths substitutes the
matching xdg.configFile.<key>.source at lib.mkForce priority, beating
Nomarchy's own lib.mkDefault writes. Other fields on the original
entry (recursive, etc.) survive via the standard module-system merge.

  nomarchy.overrides.paths = {
    "nomarchy/default/hypr/looknfeel.conf" = ./looknfeel.conf;
    "waybar/style.css"                     = ./waybar.css;
  };

Picked the attrset model from the row's two options rather than
runtime ~/.config/nomarchy/overrides/ directory discovery — Nix needs
every managed file declared at evaluation time, and the attrset
matches the explicit-config shape used everywhere else in the
Nomarchy surface.

docs/OPTIONS.md updated: both overrides.{enable,paths} entries get
real content + an example, the configOverrides row now contrasts
bulk-vs-per-file accurately, and the "Where these are defined" footer
drops the (reserved) tag.

`nix flake check --no-build` clean.
This commit is contained in:
Bernardo Magri
2026-05-22 18:49:19 +01:00
parent ce7010bb67
commit 38429a32df
2 changed files with 56 additions and 15 deletions

View File

@@ -2,33 +2,63 @@
# File-based override system for Nomarchy.
#
# STATUS: option surface only — the actual override mechanism is NOT yet
# implemented. The options are kept so configs that already set
# `nomarchy.overrides.enable = …;` continue to evaluate; setting them has
# no effect today. Tracked in docs/ROADMAP.md.
# When `nomarchy.overrides.enable = true` (default), every entry in
# `nomarchy.overrides.paths` substitutes the `xdg.configFile.<key>.source`
# Nomarchy ships by default. The substitution is done with `lib.mkForce`
# so it wins over Nomarchy's own `lib.mkDefault` writes. Other fields on
# the original entry (e.g. `recursive`) survive the merge.
#
# When implemented, this module should substitute sources in
# `xdg.configFile.<path>.source` based on the presence of matching files
# under ~/.config/nomarchy/overrides/.
# Usage in a downstream home.nix:
#
# nomarchy.overrides.paths = {
# "nomarchy/default/hypr/looknfeel.conf" = ./mine/looknfeel.conf;
# "waybar/style.css" = ./mine/waybar.css;
# };
#
# The keys are xdg.configFile paths (i.e. relative to ~/.config/). Drop-
# in-a-dir discovery is intentionally not supported — Nix needs every
# managed file declared at evaluation time, and the attrset is the
# explicit-config shape the rest of the Nomarchy module surface uses.
let
cfg = config.nomarchy.overrides;
in
{
options.nomarchy.overrides = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Reserved for the future file-based override loader. Currently a
no-op setting this has no effect. See docs/ROADMAP.md.
Whether file-based overrides in nomarchy.overrides.paths are
applied. Defaults to true so an empty `paths` is a no-op and
a populated one Just Works without a second toggle.
'';
};
paths = lib.mkOption {
type = lib.types.attrsOf lib.types.path;
default = {};
example = lib.literalExpression ''
{
"nomarchy/default/hypr/looknfeel.conf" = ./looknfeel.conf;
"waybar/style.css" = ./waybar.css;
}
'';
description = ''
Reserved for the future file-based override loader. Currently
unused.
Attribute set mapping xdg.configFile paths (relative to
~/.config/) to Nix paths whose contents should replace the
Nomarchy-shipped source. Each entry deploys at lib.mkForce
priority so it overrides Nomarchy's lib.mkDefault writes;
recursive flags and other fields on the original entry are
preserved. Pointing at a path Nomarchy doesn't manage just
creates a new xdg.configFile entry.
'';
};
};
config = lib.mkIf cfg.enable {
xdg.configFile = lib.mapAttrs (_path: src: {
source = lib.mkForce src;
}) cfg.paths;
};
}

View File

@@ -247,7 +247,7 @@ Without prime config, supergfxd still switches modes but render-offload via `nvi
### `nomarchy.configOverrides`
`nullOr path`, default `null`. Path to a replacement config directory. When set, the items listed in `core/home/configs.nix` (`fastfetch`, `fcitx5`, `fontconfig`, `git`, `imv`, `nautilus-python`, `nomarchy`, `nomarchy-skill`, `uwsm`, `wiremix`, plus the loose files) are read from `<this-path>/<name>` instead of the bundled defaults. Distinct from `nomarchy.overrides.*` below — `configOverrides` is a working bulk redirect; `overrides.*` is a reserved option surface (currently a no-op).
`nullOr path`, default `null`. Path to a replacement config directory. When set, the items listed in `core/home/configs.nix` (`fastfetch`, `fcitx5`, `fontconfig`, `git`, `imv`, `nautilus-python`, `nomarchy`, `nomarchy-skill`, `uwsm`, `wiremix`, plus the loose files) are read from `<this-path>/<name>` instead of the bundled defaults. Distinct from `nomarchy.overrides.*` below — `configOverrides` is a working *bulk* redirect; `overrides.paths` is a *per-file* attrset map.
### `nomarchy.apps.opencode.enable`
@@ -275,11 +275,22 @@ Without prime config, supergfxd still switches modes but render-offload via `nvi
### `nomarchy.overrides.enable`
`bool`, default `true`. **Reserved — currently a no-op.** Intended to gate a future file-based override loader (drop a file under `~/.config/nomarchy/overrides/`, have it substitute the bundled default for that path). The option exists so configs that set it don't fail to evaluate; setting it has no effect today. Use `nomarchy.configOverrides` for bulk redirection, or set `xdg.configFile.<path>.source` directly in your `home.nix` for per-file overrides — Nomarchy's defaults use `lib.mkDefault` and yield to higher-priority assignments. Tracked in `docs/ROADMAP.md`.
`bool`, default `true`. Whether the entries in `nomarchy.overrides.paths` are applied. Default `true` so an empty `paths` is a no-op and a populated one Just Works without a second toggle.
### `nomarchy.overrides.paths`
`attrsOf path`, default `{}`. **Reserved — currently unused.** Will be populated by the future override loader.
`attrsOf path`, default `{}`. Per-file overrides. Each key is an `xdg.configFile` path (relative to `~/.config/`); each value is a Nix path whose contents replace the Nomarchy-shipped source. Substitution is done with `lib.mkForce` so it wins over Nomarchy's own `lib.mkDefault` writes. Other fields on the original entry (`recursive` etc.) survive the merge. Overriding a path Nomarchy doesn't manage just creates a new `xdg.configFile` entry.
Example:
```nix
nomarchy.overrides.paths = {
"nomarchy/default/hypr/looknfeel.conf" = ./looknfeel.conf;
"waybar/style.css" = ./waybar.css;
};
```
Drop-in-a-dir discovery (a runtime walk of `~/.config/nomarchy/overrides/`) is intentionally not supported — Nix needs every managed file declared at evaluation time, and the attrset is the explicit-config shape the rest of the Nomarchy module surface uses.
---
@@ -331,6 +342,6 @@ The same pattern works for any file Nomarchy deploys via `xdg.configFile.<path>.
- `core/system/hardware.nix``nomarchy.hardware.*`
- `core/system/impermanence.nix``impermanence.enable`
- `core/home/options.nix` — most home-side `nomarchy.*` options
- `core/home/overrides.nix``nomarchy.overrides.*` (reserved; currently no-op)
- `core/home/overrides.nix``nomarchy.overrides.*`
- `themes/engine/loader.nix``nomarchy.themeLoader.*`
- `features/apps/vscode.nix``nomarchy.vscode.*`