Compare commits

..

3 Commits

Author SHA1 Message Date
0c483f9512 feat(menu): network + audio modules; case-insensitive fuzzy search
- network: replace the nmtui-in-a-terminal flow with networkmanager_dmenu
  (native rofi wifi/VPN picker), configured via xdg config.ini to drive
  rofi with rofi_highlight; editing a connection drops to nmtui.
- audio: new System -> Audio sink/source switcher via rofi-pulse-select,
  self-gated on the PipeWire/pulse socket.
- search: case-insensitive fuzzy matching with fzf sorting across every
  menu module and the launcher (so "system" finds "System").

Secrets module (rbw/pass) deferred — no Bitwarden/pass setup here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 18:23:21 +01:00
dfb57c2e34 feat(home): create XDG user directories by default
Enable xdg.userDirs with createDirectories so a fresh install lands with
Downloads/Documents/Pictures/Music/Videos/Desktop/Public/Templates (plus
home-manager's Projects) present and written to user-dirs.dirs, rather
than appearing only on first app use. mkDefault so a downstream home.nix
can flip it off or remap individual paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 18:23:21 +01:00
995810927d fix(install): pin HOME=/root so root nix never strays into /home/nomarchy
`exec sudo --preserve-env` (needed to carry the NOMARCHY_* vars) also
drags the live session user's HOME=/home/nomarchy into the root install
process. Root-run `nix build` then writes an eval cache + .nix-defexpr
there, and the in-chroot one lands on the TARGET as a stray, orphaned
/home/nomarchy (no such user on the installed system). Pin root's own
HOME after the sudo re-exec, and again inside the nixos-enter chroot
script. The user activation already sets HOME=/home/$USERNAME and is
unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 18:23:21 +01:00
4 changed files with 89 additions and 12 deletions

View File

@@ -72,11 +72,19 @@ how to override it. Items marked ✓ are shipped.
launcher, and yazi (SUPER+E) already covers real browsing. launcher, and yazi (SUPER+E) already covers real browsing.
- **More menu modules from rofi tools:** the script-based counterparts - **More menu modules from rofi tools:** the script-based counterparts
(run via `rofi -dmenu`, like the hand-rolled modules), each a deliberate (run via `rofi -dmenu`, like the hand-rolled modules), each a deliberate
replacement of an existing flow: **rofi-network-manager** (a keyboard replacement of an existing flow.
wifi/VPN picker vs today's `nmtui`-in-terminal `network`), **rofi-rbw / -**Network** (`networkmanager_dmenu`): a native rofi wifi/VPN picker
rofi-pass** (a secrets module — Bitwarden via rbw, or `pass` — pairs with replacing the old `nmtui`-in-terminal `network` flow. Configured (xdg
`keys.nix`), and **rofi-pulse-select** (an audio sink/source switcher). `networkmanager-dmenu/config.ini`) to drive rofi with `rofi_highlight`
Decide per-module whether it earns replacing the current path. for connected/available rows; editing a connection drops to nmtui in the
terminal. Inherits the generated theme like every other module.
-**Audio** (`rofi-pulse-select`): a PipeWire/pulse sink/source switcher
under System → Audio (Output/Input), self-gated on the pulse socket.
- Deferred: **rofi-rbw / rofi-pass** secrets module — no Bitwarden/`pass`
setup here today (secrets are gpg/ssh + gnome-keyring, see `keys.nix`),
so it'd mean adopting a new secret manager. Revisit if that changes.
- Also: menu search is now **case-insensitive fuzzy** (`matching = fuzzy`,
`sorting-method = fzf`) across every module + the launcher.
- **Theme parity with legacy:** summer-day/night now carry their legacy - **Theme parity with legacy:** summer-day/night now carry their legacy
bar layouts as `waybar.jsonc` whole-swaps (adapted: dead legacy script bar layouts as `waybar.jsonc` whole-swaps (adapted: dead legacy script
modules dropped, Nerd-Fonts-v2 codepoints remapped to FontAwesome/v3, modules dropped, Nerd-Fonts-v2 codepoints remapped to FontAwesome/v3,

View File

@@ -1,7 +1,7 @@
# Nomarchy — Home Manager entry point. # Nomarchy — Home Manager entry point.
# Consume this via homeModules.nomarchy (flake.nix), which also pulls in # Consume this via homeModules.nomarchy (flake.nix), which also pulls in
# the stylix home module that stylix.nix configures. # the stylix home module that stylix.nix configures.
{ config, pkgs, ... }: { config, lib, pkgs, ... }:
{ {
imports = [ imports = [
@@ -33,6 +33,16 @@
services.network-manager-applet.enable = true; services.network-manager-applet.enable = true;
xsession.preferStatusNotifierItems = true; xsession.preferStatusNotifierItems = true;
# Standard XDG user directories (Downloads, Documents, Pictures, Music,
# Videos, Desktop, Public, Templates): written to user-dirs.dirs so file
# pickers/browsers resolve them, and created on activation so a fresh
# install lands with them present (not just on first app use). mkDefault
# so a downstream home.nix can flip it off or remap individual paths.
xdg.userDirs = {
enable = lib.mkDefault true;
createDirectories = lib.mkDefault true;
};
home.stateVersion = "26.05"; home.stateVersion = "26.05";
home.packages = with pkgs; [ home.packages = with pkgs; [

View File

@@ -241,13 +241,32 @@ ${themeRows}
exec xdg-open "https://www.google.com/search?q=$(urlencode "$q")" ;; exec xdg-open "https://www.google.com/search?q=$(urlencode "$q")" ;;
network) network)
# nmtui in a terminal (NetworkManager is the system network stack). # Native rofi wifi/VPN picker (networkmanager_dmenu) over the system
exec ${cfg.terminal} -e nmtui ;; # NetworkManager replaces the old nmtui-in-a-terminal flow. Reads
# its config from xdg.configFile below (told to drive rofi).
exec networkmanager_dmenu ;;
bluetooth) bluetooth)
# blueman-manager GUI (services.blueman.enable, system-side). # blueman-manager GUI (services.blueman.enable, system-side).
exec blueman-manager ;; exec blueman-manager ;;
audio)
# PipeWire (pulse) sink/source switcher via rofi-pulse-select. Self-
# gated in the System menu on the pulse socket; guarded here too.
if [ ! -e "''${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/pulse/native" ]; then
notify-send "Audio" "No PipeWire/PulseAudio socket (nomarchy.audio off?)."; exit 0
fi
choice=$( {
row "Output device" audio-volume-high
row "Input device" audio-input-microphone
back
} | rofi -dmenu -show-icons -p Audio) || exit 0
case "$choice" in
"$BACK") exec "$0" system ;;
*Output*) exec rofi-pulse-select sink ;;
*Input*) exec rofi-pulse-select source ;;
esac ;;
capture) capture)
choice=$( { choice=$( {
row "Region clipboard" applets-screenshooter row "Region clipboard" applets-screenshooter
@@ -339,6 +358,8 @@ ${themeRows}
choice=$( { choice=$( {
row "Network" network-wireless row "Network" network-wireless
row "Bluetooth" bluetooth row "Bluetooth" bluetooth
[ -e "''${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/pulse/native" ] \
&& row "Audio" audio-volume-high
row "Do Not Disturb" notification-disabled row "Do Not Disturb" notification-disabled
systemctl --user cat hyprsunset.service >/dev/null 2>&1 \ systemctl --user cat hyprsunset.service >/dev/null 2>&1 \
&& row "Night light" weather-clear-night && row "Night light" weather-clear-night
@@ -352,6 +373,7 @@ ${themeRows}
"$BACK") exec "$0" ;; "$BACK") exec "$0" ;;
*Network*) exec "$0" network ;; *Network*) exec "$0" network ;;
*Bluetooth*) exec "$0" bluetooth ;; *Bluetooth*) exec "$0" bluetooth ;;
*Audio*) exec "$0" audio ;;
*"Do Not Disturb"*) exec "$0" dnd ;; *"Do Not Disturb"*) exec "$0" dnd ;;
*"Night light"*) exec "$0" nightlight ;; *"Night light"*) exec "$0" nightlight ;;
*Snapshots*) exec "$0" snapshot ;; *Snapshots*) exec "$0" snapshot ;;
@@ -380,7 +402,7 @@ ${themeRows}
esac ;; esac ;;
*) *)
echo "usage: nomarchy-menu [tools|system|power|power-profile|theme|clipboard|calc|files|emoji|web|network|bluetooth|capture|keybinds|ask|dnd|nightlight|snapshot]" >&2 echo "usage: nomarchy-menu [tools|system|power|power-profile|theme|clipboard|calc|files|emoji|web|network|bluetooth|audio|capture|keybinds|ask|dnd|nightlight|snapshot]" >&2
exit 64 ;; exit 64 ;;
esac esac
''; '';
@@ -392,8 +414,26 @@ in
pkgs.fd # files module (fuzzy search over $HOME) pkgs.fd # files module (fuzzy search over $HOME)
pkgs.xdg-utils # xdg-open for the files + web modules pkgs.xdg-utils # xdg-open for the files + web modules
pkgs.nodejs # npx, for the Ask Claude module (claude-code from npm) pkgs.nodejs # npx, for the Ask Claude module (claude-code from npm)
pkgs.networkmanager_dmenu # network module: rofi wifi/VPN picker
pkgs.rofi-pulse-select # audio module: sink/source switcher
]; ];
# networkmanager_dmenu drives rofi (not bare dmenu) and uses rofi's
# active/urgent row styling for the connected/available networks, so it
# inherits the generated theme like every other menu module. Editing a
# connection drops to nmtui in the configured terminal.
xdg.configFile."networkmanager-dmenu/config.ini".text = ''
[dmenu]
dmenu_command = rofi
rofi_highlight = True
compact = False
wifi_chars =
[editor]
terminal = ${cfg.terminal}
gui_if_available = False
'';
programs.rofi = { programs.rofi = {
enable = true; enable = true;
terminal = cfg.terminal; terminal = cfg.terminal;
@@ -416,6 +456,14 @@ in
# reserving `lines` (8) — so a 6-entry menu doesn't leave empty space, # reserving `lines` (8) — so a 6-entry menu doesn't leave empty space,
# while the app launcher still fills + scrolls past `lines`. # while the app launcher still fills + scrolls past `lines`.
fixed-num-lines = false; fixed-num-lines = false;
# Search: case-insensitive fuzzy across every menu + the launcher, so
# "system" finds "System" and "fzr" finds "Firefox". fzf sorting ranks
# the closest match to the top (the per-keystroke modules — calc/emoji
# — opt out per-invocation with -no-sort).
matching = "fuzzy";
case-sensitive = false;
sort = true;
sorting-method = "fzf";
}; };
# Whole-swap themes bring their own rofi.rasi; otherwise the theme # Whole-swap themes bring their own rofi.rasi; otherwise the theme

View File

@@ -54,6 +54,15 @@ if [[ $EUID -ne 0 ]]; then
exec sudo --preserve-env "$0" "$@" exec sudo --preserve-env "$0" "$@"
fi fi
# `sudo --preserve-env` (needed to carry the NOMARCHY_* vars) also drags in
# the live session user's HOME=/home/nomarchy. Root-run `nix` calls below
# would then scribble an eval cache + .nix-defexpr into /home/nomarchy —
# and the in-chroot one lands on the TARGET disk as a stray, orphaned
# /home/nomarchy (no such user on the installed system). Pin root's own
# HOME so every root nix invocation stays in /root; the user activation
# sets HOME=/home/$USERNAME explicitly and is unaffected.
export HOME=/root
header "Nomarchy installer" "NixOS, themed and ready to go." header "Nomarchy installer" "NixOS, themed and ready to go."
[[ -d /sys/firmware/efi ]] \ [[ -d /sys/firmware/efi ]] \
@@ -628,6 +637,8 @@ cat > /mnt/root/nomarchy-hm-activate.sh <<EOF
set -ex set -ex
exec > /var/log/nomarchy-hm-preactivate.log 2>&1 exec > /var/log/nomarchy-hm-preactivate.log 2>&1
export PATH=/run/current-system/sw/bin:\$PATH export PATH=/run/current-system/sw/bin:\$PATH
# Keep root's nix state in /root, not a stray /home/nomarchy on the target.
export HOME=/root
# Normally pre-built in the live env and copied over; the in-chroot # Normally pre-built in the live env and copied over; the in-chroot
# build (default substituters — the live-side build already proved the # build (default substituters — the live-side build already proved the
# no-network case) is a last-resort fallback. # no-network case) is a last-resort fallback.