All checks were successful
Check / eval (push) Successful in 3m27s
The indicator answers "which layout am I typing in?", so it is worth bar space exactly when that question has more than one answer. It was gated on a per-device override merely *existing*, which is the trap this box walked into: the junk rows a keyboard's extra HID collections leave behind are all remembered at the session layout, so they added no second answer and still raised an indicator that could only ever show one value. Gate on layouts rather than devices, and read the runtime-remembered settings.keyboard.devices alongside the declared option — the new-keyboard watcher writes those without a rebuild and they only graduate into keyboard.devices later, so a bar reading the option alone was wrong for exactly as long as the memory was fresh, which is when it matters most. keyboard.layouts is now excluded on purpose: hyprland.nix keeps it as the pool the picker offers first and deliberately never merges it into kb_layout, so listing candidates cannot make the current layout ambiguous. A device actually using one of them still does. All four whole-swaps list the module unconditionally, so a single-layout setup saw on a swapped bar what the generated bar hides — the parity rule was already broken. Filter a swap through the same answer instead of asking four hand-written files to re-derive it. Logic is pure in modules/home/waybar-language.nix, matching monitor-rules / dock-audio-rules; checks.waybar-language unit-tests both halves against boreal's real swap, including a fixture-drift guard so the parity assertion cannot pass vacuously. Verified V2: new check passes, docking-ux and theme-wholeswap still pass, `nix flake check` is clean, and the live config's generated bar now resolves modules-right without hyprland/language on its single-layout default. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
52 lines
2.3 KiB
Nix
52 lines
2.3 KiB
Nix
# When the keyboard-layout indicator earns a place in the bar, and how a
|
|
# whole-swap bar is held to the same answer (BACKLOG #109).
|
|
#
|
|
# Pure so checks.waybar-language can unit-test the contract without building
|
|
# a bar. Consumed by modules/home/waybar.nix.
|
|
{ lib }:
|
|
|
|
rec {
|
|
# The session's layouts are the comma-separated kb_layout.
|
|
# nomarchy.keyboard.layouts is deliberately NOT among them — hyprland.nix
|
|
# keeps it as the pool the new-keyboard picker offers first and never
|
|
# merges it into kb_layout — so listing candidates cannot by itself make
|
|
# the current layout ambiguous.
|
|
sessionLayouts = layout: lib.filter (l: l != "") (lib.splitString "," layout);
|
|
|
|
# The indicator answers "which layout am I typing in?", so it is worth bar
|
|
# space exactly when that has more than one answer.
|
|
#
|
|
# devices = declared nomarchy.keyboard.devices (submodules with .layout)
|
|
# remembered = settings.keyboard.devices from the in-flake state: what the
|
|
# new-keyboard watcher writes the moment a layout is chosen.
|
|
# These only graduate into `devices` at the next rebuild, so a
|
|
# bar reading `devices` alone stays wrong for exactly as long
|
|
# as the memory is fresh — which is when it matters most.
|
|
#
|
|
# Counting devices rather than layouts is the trap: remembering "us" for a
|
|
# device on a "us" session adds no second answer, and the rows a keyboard's
|
|
# extra HID collections leave behind are all of that kind.
|
|
show = { layout, devices ? { }, remembered ? { } }:
|
|
let
|
|
session = sessionLayouts layout;
|
|
perDevice = lib.mapAttrsToList (_: d: d.layout) devices
|
|
++ lib.attrValues remembered;
|
|
in
|
|
lib.length session > 1 || lib.any (l: ! lib.elem l session) perDevice;
|
|
|
|
# A whole-swap authors its bar in full and every one of them lists the
|
|
# language module unconditionally, so without this a single-layout setup
|
|
# showed on a swapped bar what the generated bar hides. Filter the swap
|
|
# through the one answer rather than asking four hand-written files to
|
|
# re-derive it (CONVENTIONS: the parity rule).
|
|
gate = showLanguage: bar:
|
|
if showLanguage then bar
|
|
else
|
|
lib.mapAttrs
|
|
(n: v:
|
|
if lib.hasPrefix "modules-" n && builtins.isList v
|
|
then lib.filter (m: m != "hyprland/language") v
|
|
else v)
|
|
bar;
|
|
}
|