feat(menu): network/bluetooth/capture/ask modules + keybindings cheatsheet
Build out the rofi menu system roadmap item: - New nomarchy-menu modules: network (nmtui), bluetooth (blueman-manager), capture (grim/slurp submenu → clipboard/file), ask (free-text → claude CLI in a terminal), and keybinds (the SUPER+? cheatsheet). - modules/home/keybinds.nix is now the single source of truth for both the Hyprland bind strings and the cheatsheet, so the two can't drift — hyprland.nix maps it into `bind`, rofi.nix renders the padded two-column sheet (generated/mouse binds live in its `extra` rows). - New binds: SUPER+Space (quick launch), SUPER+M (main menu), SUPER+? (cheatsheet). SUPER+D stays rofi -show drun. - Ask Claude pulls claude-code fresh from npm via `npx @anthropic-ai/claude-code@latest` (the nixpkgs package lags model releases); nodejs is bundled for npx. nix flake check passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -261,7 +261,8 @@
|
|||||||
"Bash(pkill -f \"qemu-system-x86_64.*NOMARCHY\\\\|qemu-system-x86_64.*nomarchy\")",
|
"Bash(pkill -f \"qemu-system-x86_64.*NOMARCHY\\\\|qemu-system-x86_64.*nomarchy\")",
|
||||||
"Bash(NOMARCHY_PATH=__TRACKED_VAR__ python3 pkgs/nomarchy-theme-sync/nomarchy-theme-sync.py --quiet apply summer-night --no-switch)",
|
"Bash(NOMARCHY_PATH=__TRACKED_VAR__ python3 pkgs/nomarchy-theme-sync/nomarchy-theme-sync.py --quiet apply summer-night --no-switch)",
|
||||||
"Bash(NOMARCHY_PATH=__TRACKED_VAR__ python3 pkgs/nomarchy-theme-sync/nomarchy-theme-sync.py --quiet apply summer-day --no-switch)",
|
"Bash(NOMARCHY_PATH=__TRACKED_VAR__ python3 pkgs/nomarchy-theme-sync/nomarchy-theme-sync.py --quiet apply summer-day --no-switch)",
|
||||||
"Bash(xargs cat)"
|
"Bash(xargs cat)",
|
||||||
|
"Bash(nix-instantiate --parse modules/home/rofi.nix)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
README.md
22
README.md
@@ -274,14 +274,20 @@ close · `SUPER+1..9` workspaces · `Print` region screenshot.
|
|||||||
`theme` (SUPER+T) · `clipboard` (cliphist, SUPER+CTRL+V) · `calc`
|
`theme` (SUPER+T) · `clipboard` (cliphist, SUPER+CTRL+V) · `calc`
|
||||||
(qalc, copy/chain) · `files` (fd → xdg-open) · `web` (DuckDuckGo).
|
(qalc, copy/chain) · `files` (fd → xdg-open) · `web` (DuckDuckGo).
|
||||||
SUPER+D is `rofi -show drun`.
|
SUPER+D is `rofi -show drun`.
|
||||||
- next modules: Network ▸ nmtui · Bluetooth ▸ blueman · Capture ▸
|
- ✓ shipped modules: `network` (nmtui in `$TERMINAL`) · `bluetooth`
|
||||||
screenshot · **keybindings cheatsheet** (parse the bind list → rofi,
|
(blueman-manager) · `capture` (grim/slurp submenu: region/full →
|
||||||
so SUPER-? shows every shortcut) · **ask Claude**: free-text →
|
clipboard/file, saved to `~/Pictures/Screenshots`) · `keybinds` (the
|
||||||
`$TERMINAL -e claude "<question>"` — the claude CLI auths via OAuth
|
cheatsheet, see below) · `ask` (free-text → claude CLI in a terminal;
|
||||||
against a Pro/Max subscription (no API key); REPL stays open for
|
auths via OAuth, no API key; pulled fresh via `npx
|
||||||
follow-ups (claude-code in nixpkgs is unfree — allowUnfree is on)
|
@anthropic-ai/claude-code@latest` rather than the nixpkgs package, which
|
||||||
- planned binds: `SUPER+Space` → `rofi -dmenu`/quick-launch and
|
lags model releases — `nodejs` is bundled for npx; REPL stays open)
|
||||||
`SUPER+M` → `nomarchy-menu` (main menu); `SUPER+D` stays `-show drun`
|
- ✓ keybindings cheatsheet: `modules/home/keybinds.nix` is the **single
|
||||||
|
source** for both the Hyprland binds and the SUPER+? rofi list, so they
|
||||||
|
can't drift; `nomarchy-menu keybinds` renders the padded two-column
|
||||||
|
sheet (generated/mouse binds carried in its `extra` rows)
|
||||||
|
- ✓ shipped binds: `SUPER+Space` → `rofi -show drun` (quick launch) ·
|
||||||
|
`SUPER+M` → `nomarchy-menu` (main menu) · `SUPER+?` → the cheatsheet;
|
||||||
|
`SUPER+D` stays `-show drun`
|
||||||
- launcher icons: ✓ `show-icons` on, drawing from the theme's icon set
|
- launcher icons: ✓ `show-icons` on, drawing from the theme's icon set
|
||||||
(Papirus, via the icon-themes work below)
|
(Papirus, via the icon-themes work below)
|
||||||
- decision record: resolves the old Walker/Lua question — no GTK4
|
- decision record: resolves the old Walker/Lua question — no GTK4
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ let
|
|||||||
"$mod SHIFT, ${ws}, movetoworkspace, ${ws}"
|
"$mod SHIFT, ${ws}, movetoworkspace, ${ws}"
|
||||||
])
|
])
|
||||||
9);
|
9);
|
||||||
|
|
||||||
|
# The keyboard binds — single source shared with the SUPER+? cheatsheet
|
||||||
|
# (rofi.nix renders the same list). Edit them in ./keybinds.nix.
|
||||||
|
keybinds = import ./keybinds.nix;
|
||||||
|
mkBind = b: "${b.mods}, ${b.key}, ${b.action}";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
wayland.windowManager.hyprland = lib.mkIf config.nomarchy.hyprland.enable {
|
wayland.windowManager.hyprland = lib.mkIf config.nomarchy.hyprland.enable {
|
||||||
@@ -125,41 +130,11 @@ in
|
|||||||
force_default_wallpaper = lib.mkDefault 0;
|
force_default_wallpaper = lib.mkDefault 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
bind = [
|
# Rendered from ./keybinds.nix (the cheatsheet reads the same list),
|
||||||
"$mod, Return, exec, $terminal"
|
# plus the generated per-workspace binds. Like exec-once above this
|
||||||
"$mod, D, exec, rofi -show drun"
|
# stays a normal-priority list, so a downstream `bind = [...]`
|
||||||
"$mod, E, exec, $terminal -e yazi"
|
# concatenates rather than replaces.
|
||||||
"$mod, Q, killactive"
|
bind = map mkBind keybinds.binds ++ workspaceBinds;
|
||||||
"$mod, F, fullscreen"
|
|
||||||
"$mod, V, togglefloating"
|
|
||||||
"$mod SHIFT, E, exit"
|
|
||||||
|
|
||||||
# Theme picker (menu dispatcher): apply writes the state and
|
|
||||||
# runs home-manager switch (progress via notify-send).
|
|
||||||
"$mod, T, exec, nomarchy-menu theme"
|
|
||||||
# Cycle the current theme's wallpapers (instant, no rebuild).
|
|
||||||
"$mod SHIFT, T, exec, nomarchy-theme-sync bg next"
|
|
||||||
|
|
||||||
# Power menu (rofi dmenu via the nomarchy-menu dispatcher).
|
|
||||||
# Not Escape: Super+Escape gets swallowed before reaching the
|
|
||||||
# dispatcher on some setups (input methods / modal handling).
|
|
||||||
"$mod, X, exec, nomarchy-menu power"
|
|
||||||
|
|
||||||
# Notification centre (swaync).
|
|
||||||
"$mod, N, exec, swaync-client -t"
|
|
||||||
|
|
||||||
# Clipboard history (cliphist via the menu dispatcher).
|
|
||||||
"$mod CTRL, V, exec, nomarchy-menu clipboard"
|
|
||||||
|
|
||||||
# Focus
|
|
||||||
"$mod, H, movefocus, l"
|
|
||||||
"$mod, L, movefocus, r"
|
|
||||||
"$mod, K, movefocus, u"
|
|
||||||
"$mod, J, movefocus, d"
|
|
||||||
|
|
||||||
# Screenshot region to clipboard
|
|
||||||
", Print, exec, grim -g \"$(slurp)\" - | wl-copy"
|
|
||||||
] ++ workspaceBinds;
|
|
||||||
|
|
||||||
# Media keys via swayosd-client: it performs the action AND shows
|
# Media keys via swayosd-client: it performs the action AND shows
|
||||||
# the on-screen display (the nomarchy.osd module). e = repeat,
|
# the on-screen display (the nomarchy.osd module). e = repeat,
|
||||||
|
|||||||
56
modules/home/keybinds.nix
Normal file
56
modules/home/keybinds.nix
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Canonical keybind list — the single source of truth for BOTH the
|
||||||
|
# Hyprland `bind` strings (hyprland.nix) and the SUPER+? cheatsheet
|
||||||
|
# rendered by nomarchy-menu (rofi.nix). One place, no second renderer to
|
||||||
|
# keep in sync — the same rule the theme pipeline follows.
|
||||||
|
#
|
||||||
|
# mods — modifier string, Hyprland syntax ("$mod", "$mod SHIFT", "")
|
||||||
|
# key — the key name
|
||||||
|
# action — the Hyprland dispatcher (+args) that the bind runs
|
||||||
|
# desc — human label, shown in the cheatsheet
|
||||||
|
#
|
||||||
|
# `extra` holds cheatsheet-only rows for binds generated elsewhere
|
||||||
|
# (per-workspace numbers, mouse drags) so they still show up under SUPER+?.
|
||||||
|
{
|
||||||
|
binds = [
|
||||||
|
{ mods = "$mod"; key = "Return"; action = "exec, $terminal"; desc = "Open terminal"; }
|
||||||
|
{ mods = "$mod"; key = "Space"; action = "exec, rofi -show drun"; desc = "Quick launch (apps)"; }
|
||||||
|
{ mods = "$mod"; key = "D"; action = "exec, rofi -show drun"; desc = "App launcher"; }
|
||||||
|
{ mods = "$mod"; key = "M"; action = "exec, nomarchy-menu"; desc = "Main menu"; }
|
||||||
|
{ mods = "$mod"; key = "E"; action = "exec, $terminal -e yazi"; desc = "File manager (yazi)"; }
|
||||||
|
{ mods = "$mod"; key = "Q"; action = "killactive"; desc = "Close window"; }
|
||||||
|
{ mods = "$mod"; key = "F"; action = "fullscreen"; desc = "Fullscreen"; }
|
||||||
|
{ mods = "$mod"; key = "V"; action = "togglefloating"; desc = "Toggle floating"; }
|
||||||
|
{ mods = "$mod SHIFT"; key = "E"; action = "exit"; desc = "Exit Hyprland"; }
|
||||||
|
|
||||||
|
# Theme picker (menu dispatcher): apply writes the state and runs
|
||||||
|
# home-manager switch (progress via notify-send).
|
||||||
|
{ mods = "$mod"; key = "T"; action = "exec, nomarchy-menu theme"; desc = "Theme picker"; }
|
||||||
|
# Cycle the current theme's wallpapers (instant, no rebuild).
|
||||||
|
{ mods = "$mod SHIFT"; key = "T"; action = "exec, nomarchy-theme-sync bg next"; desc = "Next wallpaper"; }
|
||||||
|
|
||||||
|
# Power menu via the dispatcher. Not Escape: Super+Escape gets
|
||||||
|
# swallowed before reaching the dispatcher on some setups.
|
||||||
|
{ mods = "$mod"; key = "X"; action = "exec, nomarchy-menu power"; desc = "Power menu"; }
|
||||||
|
|
||||||
|
{ mods = "$mod"; key = "N"; action = "exec, swaync-client -t"; desc = "Notification centre"; }
|
||||||
|
{ mods = "$mod CTRL"; key = "V"; action = "exec, nomarchy-menu clipboard"; desc = "Clipboard history"; }
|
||||||
|
# SUPER+? (the "question" keysym already implies Shift on most layouts).
|
||||||
|
{ mods = "$mod"; key = "question"; action = "exec, nomarchy-menu keybinds"; desc = "Keybindings cheatsheet"; }
|
||||||
|
|
||||||
|
# Focus
|
||||||
|
{ mods = "$mod"; key = "H"; action = "movefocus, l"; desc = "Focus left"; }
|
||||||
|
{ mods = "$mod"; key = "L"; action = "movefocus, r"; desc = "Focus right"; }
|
||||||
|
{ mods = "$mod"; key = "K"; action = "movefocus, u"; desc = "Focus up"; }
|
||||||
|
{ mods = "$mod"; key = "J"; action = "movefocus, d"; desc = "Focus down"; }
|
||||||
|
|
||||||
|
# Screenshot region to clipboard (the menu's Capture module has more).
|
||||||
|
{ mods = ""; key = "Print"; action = "exec, grim -g \"$(slurp)\" - | wl-copy"; desc = "Screenshot region → clipboard"; }
|
||||||
|
];
|
||||||
|
|
||||||
|
extra = [
|
||||||
|
{ keys = "SUPER + 1-9"; desc = "Switch to workspace 1-9"; }
|
||||||
|
{ keys = "SUPER + SHIFT + 1-9"; desc = "Move window to workspace 1-9"; }
|
||||||
|
{ keys = "SUPER + drag"; desc = "Move (LMB) / resize (RMB) window"; }
|
||||||
|
{ keys = "Volume / Brightness"; desc = "Hardware keys, shown via the OSD"; }
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -19,6 +19,25 @@ let
|
|||||||
rasiOverride = cfg.themesDir + "/${t.slug}/rofi.rasi";
|
rasiOverride = cfg.themesDir + "/${t.slug}/rofi.rasi";
|
||||||
hasRasiOverride = builtins.pathExists rasiOverride;
|
hasRasiOverride = builtins.pathExists rasiOverride;
|
||||||
|
|
||||||
|
# Keybindings cheatsheet (SUPER+? → the `keybinds` menu module). Built
|
||||||
|
# from the SAME ./keybinds.nix that hyprland.nix binds, so it can never
|
||||||
|
# drift from the live shortcuts. "$mod" reads as SUPER; rows are padded
|
||||||
|
# into two columns. extra[] carries the generated/mouse binds.
|
||||||
|
keybinds = import ./keybinds.nix;
|
||||||
|
padRight = w: s:
|
||||||
|
let n = w - builtins.stringLength s;
|
||||||
|
in s + (if n > 0 then lib.concatStrings (builtins.genList (_: " ") n) else " ");
|
||||||
|
prettyKeys = b:
|
||||||
|
let m = lib.replaceStrings [ "$mod" ] [ "SUPER" ] b.mods;
|
||||||
|
prefix = if m == "" then "" else lib.concatStringsSep " + " (lib.splitString " " m) + " + ";
|
||||||
|
key = lib.replaceStrings [ "question" "slash" ] [ "?" "/" ] b.key;
|
||||||
|
in prefix + key;
|
||||||
|
cheatRows =
|
||||||
|
map (b: padRight 22 (prettyKeys b) + b.desc) keybinds.binds
|
||||||
|
++ map (e: padRight 22 e.keys + e.desc) keybinds.extra;
|
||||||
|
cheatsheetFile = pkgs.writeText "nomarchy-keybinds.txt"
|
||||||
|
(lib.concatStringsSep "\n" cheatRows + "\n");
|
||||||
|
|
||||||
nomarchy-menu = pkgs.writeShellScriptBin "nomarchy-menu" ''
|
nomarchy-menu = pkgs.writeShellScriptBin "nomarchy-menu" ''
|
||||||
# Nomarchy menu dispatcher — thin presentation layer over
|
# Nomarchy menu dispatcher — thin presentation layer over
|
||||||
# `rofi -dmenu`; actions delegate to nomarchy-theme-sync, systemctl,
|
# `rofi -dmenu`; actions delegate to nomarchy-theme-sync, systemctl,
|
||||||
@@ -89,6 +108,45 @@ let
|
|||||||
[ -n "$q" ] || exit 0
|
[ -n "$q" ] || exit 0
|
||||||
exec xdg-open "https://duckduckgo.com/?q=$(urlencode "$q")" ;;
|
exec xdg-open "https://duckduckgo.com/?q=$(urlencode "$q")" ;;
|
||||||
|
|
||||||
|
network)
|
||||||
|
# nmtui in a terminal (NetworkManager is the system network stack).
|
||||||
|
exec ${cfg.terminal} -e nmtui ;;
|
||||||
|
|
||||||
|
bluetooth)
|
||||||
|
# blueman-manager GUI (services.blueman.enable, system-side).
|
||||||
|
exec blueman-manager ;;
|
||||||
|
|
||||||
|
capture)
|
||||||
|
choice=$(printf '%s\n' \
|
||||||
|
" Region → clipboard" \
|
||||||
|
" Region → file" \
|
||||||
|
" Full screen → clipboard" \
|
||||||
|
" Full screen → file" \
|
||||||
|
| rofi -dmenu -p capture) || exit 0
|
||||||
|
dir="$HOME/Pictures/Screenshots"
|
||||||
|
file="$dir/$(date +%Y%m%d-%H%M%S).png"
|
||||||
|
case "$choice" in
|
||||||
|
*"Region → clipboard"*) grim -g "$(slurp)" - | wl-copy ;;
|
||||||
|
*"Region → file"*) mkdir -p "$dir"; grim -g "$(slurp)" "$file" \
|
||||||
|
&& notify-send "Screenshot saved" "$file" ;;
|
||||||
|
*"Full screen → clipboard"*) grim - | wl-copy ;;
|
||||||
|
*"Full screen → file"*) mkdir -p "$dir"; grim "$file" \
|
||||||
|
&& notify-send "Screenshot saved" "$file" ;;
|
||||||
|
esac ;;
|
||||||
|
|
||||||
|
keybinds)
|
||||||
|
# Read-only cheatsheet, generated from keybinds.nix at build time.
|
||||||
|
rofi -dmenu -i -p keys < ${cheatsheetFile} >/dev/null || exit 0 ;;
|
||||||
|
|
||||||
|
ask)
|
||||||
|
# Free-text question → claude CLI in a terminal (OAuth, no API key).
|
||||||
|
# Pulled fresh from npm via npx rather than nixpkgs' claude-code,
|
||||||
|
# which lags behind model releases; npx caches after first run. The
|
||||||
|
# REPL stays open for follow-ups.
|
||||||
|
q=$(rofi -dmenu -p claude < /dev/null) || exit 0
|
||||||
|
[ -n "$q" ] || exit 0
|
||||||
|
exec ${cfg.terminal} -e npx --yes @anthropic-ai/claude-code@latest "$q" ;;
|
||||||
|
|
||||||
"")
|
"")
|
||||||
choice=$(printf '%s\n' \
|
choice=$(printf '%s\n' \
|
||||||
" Apps" \
|
" Apps" \
|
||||||
@@ -97,6 +155,11 @@ let
|
|||||||
" Calculator" \
|
" Calculator" \
|
||||||
" Files" \
|
" Files" \
|
||||||
" Web search" \
|
" Web search" \
|
||||||
|
" Network" \
|
||||||
|
" Bluetooth" \
|
||||||
|
" Capture" \
|
||||||
|
" Keybindings" \
|
||||||
|
" Ask Claude" \
|
||||||
" Power" \
|
" Power" \
|
||||||
| rofi -dmenu -p menu) || exit 0
|
| rofi -dmenu -p menu) || exit 0
|
||||||
case "$choice" in
|
case "$choice" in
|
||||||
@@ -106,11 +169,16 @@ let
|
|||||||
*Calc*) exec "$0" calc ;;
|
*Calc*) exec "$0" calc ;;
|
||||||
*Files*) exec "$0" files ;;
|
*Files*) exec "$0" files ;;
|
||||||
*Web*) exec "$0" web ;;
|
*Web*) exec "$0" web ;;
|
||||||
|
*Network*) exec "$0" network ;;
|
||||||
|
*Bluetooth*) exec "$0" bluetooth ;;
|
||||||
|
*Capture*) exec "$0" capture ;;
|
||||||
|
*Keybindings*) exec "$0" keybinds ;;
|
||||||
|
*Ask*) exec "$0" ask ;;
|
||||||
*Power*) exec "$0" power ;;
|
*Power*) exec "$0" power ;;
|
||||||
esac ;;
|
esac ;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
echo "usage: nomarchy-menu [power|theme|clipboard|calc|files|web]" >&2
|
echo "usage: nomarchy-menu [power|theme|clipboard|calc|files|web|network|bluetooth|capture|keybinds|ask]" >&2
|
||||||
exit 64 ;;
|
exit 64 ;;
|
||||||
esac
|
esac
|
||||||
'';
|
'';
|
||||||
@@ -122,6 +190,7 @@ in
|
|||||||
pkgs.libqalculate # qalc, the calc module's engine
|
pkgs.libqalculate # qalc, the calc module's engine
|
||||||
pkgs.fd # files module
|
pkgs.fd # files module
|
||||||
pkgs.xdg-utils # xdg-open for files/web
|
pkgs.xdg-utils # xdg-open for files/web
|
||||||
|
pkgs.nodejs # npx, for the Ask Claude module (claude-code from npm)
|
||||||
];
|
];
|
||||||
|
|
||||||
programs.rofi = {
|
programs.rofi = {
|
||||||
|
|||||||
Reference in New Issue
Block a user