feat(keyboard): per-device layout memory in-flake (no ~/.local/state)

Phase 2 of the in-flake-state philosophy, mirroring night-light: the
nomarchy-keyboard-watch daemon now remembers per-device layouts in the
git-tracked state file (settings.keyboard.devices) instead of
~/.local/state/nomarchy/keyboard-layouts.

- Reads the LIVE working-tree map (theme-sync get → jq) so a pick this
  session is honoured at once; writes instantly with --no-switch (no
  rebuild). Writes the whole map back at the dot-free parent path
  (read-modify-write) so a device name with a dot can't corrupt the
  tool's dotted set-path (Hyprland only sanitises spaces→-).
- Graduation: nomarchy.keyboard.devices now mkDefault-merges entries
  from settings.keyboard.devices, so each remembered device becomes a
  generated Hyprland device{} block on the next rebuild (reproducible,
  hotplug-applied). A hand-written keyboard.devices.<name> still wins;
  once baked, the watcher's is_declared check makes it step back.
- theme.nix seeds settings.keyboard.devices = {} (sparse state still
  evaluates); options/template descriptions updated; ROADMAP marked done.

Eval-verified (graduation + mkDefault precedence) and the set/get
writer round-trips. Still needs the on-hardware hotplug re-verify (the
picker path isn't testable in CI).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Bernardo Magri
2026-06-23 09:18:33 +01:00
parent 685126ab47
commit aed41793f8
5 changed files with 83 additions and 28 deletions

View File

@@ -38,8 +38,9 @@
# "keychron-keychron-k2" = { layout = "de"; };
# };
#
# nomarchy.keyboard.layouts = [ "de" "fr" ]; # rofi-prompt for a layout when a
# # new keyboard connects + remember it
# nomarchy.keyboard.layouts = [ "de" "fr" ]; # rofi-prompt for a layout when a new
# # keyboard connects + remember it in the
# # flake state (graduates to .devices above)
# ── Application suite ───────────────────────────────────────────────
# A starter complete-workstation set, installed for your user — yours to