Compare commits

...

4 Commits

Author SHA1 Message Date
Bernardo Magri
05d995f8e0 feat(keybinds): direct SUPER+CTRL binds for the menu functions
Each nomarchy-menu module is now reachable directly, not just through the
SUPER+M picker: SUPER+CTRL+ V clipboard · C calc · W web · F files ·
N network · B bluetooth · S capture · A ask. Added to keybinds.nix (the
single source), so they render in the SUPER+? cheatsheet too. No key
collisions; nix flake check passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 20:39:12 +01:00
Bernardo Magri
f6c4a2a591 fix(waybar): stop summer themes rendering phantom workspaces
summer-day/summer-night showed all 10 workspace icons up-front. The cause:
legacy used the deprecated `persistent_workspaces` (underscore), which
current Waybar silently ignores — so legacy only ever showed *existing*
workspaces. The v1 port rewrote it to the modern `persistent-workspaces`
(hyphen), which Waybar honours, surfacing all ten as phantoms.

Drop the block from both summer waybar.jsonc whole-swaps. The other themes
render from waybar.nix, which never declared persistent-workspaces, so they
already only show existing workspaces — no change needed there.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 20:35:25 +01:00
Bernardo Magri
7c34eed2ca fix(theme): solid per-theme hyprland borders, matching legacy
v1 forced an accent→accentAlt 45deg gradient on every theme's window
border; the legacy identity themes all used a *solid* border — accent for
nord/retro-82/lumon, the text tone for kanagawa/summer-day/summer-night.

Add a palette-resolved `border` field ({active, inactive}, each a palette
key or literal hex) to the theme schema with accent/overlay defaults in
theme.nix, consume it solid in hyprland.nix, and declare it in every
preset (and the live state). Declaring it everywhere is required because
`nomarchy-theme-sync apply` deep-merges presets — an omitted field would
stick across switches, like colors already are fully specified per theme.

All six identity themes resolve to their exact legacy active border
(verified: nord #81a1c1, retro-82 #faa968, lumon #f2fcff, kanagawa
#dcd7ba, summer-night #d3c6aa, summer-day #5c6a72). nix flake check passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 20:32:18 +01:00
Bernardo Magri
d252f01f17 feat(shell): flat starship prompt, drop the powerline styling
The powerline look (the `[]` separator glyph + bg-filled segments) didn't
read well. Switch to a flat prompt: bold-accent directory, warn git
branch, subtext git-status/duration, `❯` character — plain colored text,
no background fills, each module carrying its own trailing space so there
are no stray gaps. Also reference cmd_duration in `format` (it was
configured but never shown).

Generated starship.toml verified valid; nix flake check passes. Visual
pass still wants a live terminal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 20:18:46 +01:00
30 changed files with 164 additions and 43 deletions

View File

@@ -262,7 +262,9 @@
"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)" "Bash(nix-instantiate --parse modules/home/rofi.nix)",
"Bash(nix-instantiate --parse modules/home/shell.nix)",
"Bash(command -v nix)"
] ]
} }
} }

View File

@@ -364,25 +364,32 @@ close · `SUPER+1..9` workspaces · `Print` region screenshot.
and yazi fell back to presets. Fixed by adding `group = "git"` to both and yazi fell back to presets. Fixed by adding `group = "git"` to both
git fetcher entries in `modules/home/yazi.nix` (the git plugin's git fetcher entries in `modules/home/yazi.nix` (the git plugin's
`setup()` only renders the linemode; the fetcher still needs registering). `setup()` only renders the linemode; the fetcher still needs registering).
- **Starship prompt styling:** drop the powerline look the current prompt - **Starship prompt styling:** dropped the powerline look (the `[]`
doesn't read well. Rework the `format`/segment styling in separator glyph + `bg:` fills) for a flat prompt — bold-accent directory,
`modules/home/shell.nix:59` toward a flat, plain prompt. warn git branch, subtext status/duration, `` character, all plain
colored text (`modules/home/shell.nix`). Also wired in `cmd_duration`,
which was configured but never referenced in `format`.
-**xfce deprecation warnings:** moved `xfce.exo``pkgs.xfce4-exo` and -**xfce deprecation warnings:** moved `xfce.exo``pkgs.xfce4-exo` and
the three Thunar plugins to their new top-level names in the three Thunar plugins to their new top-level names in
`modules/nixos/file-manager.nix`; the eval warnings are gone. `modules/nixos/file-manager.nix`; the eval warnings are gone.
- **Rofi function keybindings:** add direct Hyprland binds for the - **Rofi function keybindings:** direct `SUPER+CTRL+<mnemonic>` binds jump
`nomarchy-menu` sub-functions (calc, web search, file search, clipboard, straight to each `nomarchy-menu` module — V clipboard · C calc · W web ·
…) instead of only reaching them through the menu — see the planned binds F files · N network · B bluetooth · S capture · A ask — added to
in the Menu-system roadmap item and `modules/home/hyprland.nix`. `modules/home/keybinds.nix`, so they also show in the SUPER+? cheatsheet.
-**Enable nix-ld by default:** `programs.nix-ld.enable` is on distro-wide -**Enable nix-ld by default:** `programs.nix-ld.enable` is on distro-wide
(`modules/nixos/default.nix`), so prebuilt/foreign dynamically-linked (`modules/nixos/default.nix`), so prebuilt/foreign dynamically-linked
binaries run out of the box. binaries run out of the box.
- **Hyprland border colors off for some themes:** the active/inactive border - **Hyprland border colors off for some themes:** the cause was v1
colors don't match the legacy branch for several themes — audit forcing an `accent→accentAlt` gradient on every theme; legacy used a
`col.active_border`/`col.inactive_border` generation in *solid* border (accent for nord/retro-82/lumon, the text tone for
`modules/home/hyprland.nix` against legacy. kanagawa/summer-day/summer-night). Added a palette-resolved `border`
- **Waybar shows non-existent workspaces:** in summer-night/summer-day the field (`{active, inactive}`) to the theme schema (`theme.nix`), consumed
bar renders every workspace icon up-front via `persistent-workspaces` / solid in `hyprland.nix`, and declared it in every preset so a switch
`all-outputs` in `themes/summer-{day,night}/waybar.jsonc`. Restore the always replaces it. All six identity themes now match legacy exactly.
legacy behaviour (only show workspaces that exist) here and across the -**Waybar shows non-existent workspaces:** the v1 summer port "fixed"
other themes. legacy's deprecated `persistent_workspaces` (underscore — silently
ignored by current Waybar, so legacy only ever showed existing
workspaces) into the modern `persistent-workspaces` (hyphen), which
Waybar honours → all 10 rendered as phantoms. Dropped the block from
`themes/summer-{day,night}/waybar.jsonc`; the other themes use the
generated `waybar.nix`, which never had it, so they already match.

View File

@@ -65,8 +65,10 @@ in
gaps_in = t.ui.gapsIn; gaps_in = t.ui.gapsIn;
gaps_out = t.ui.gapsOut; gaps_out = t.ui.gapsOut;
border_size = t.ui.borderSize; border_size = t.ui.borderSize;
"col.active_border" = "${rgb c.accent} ${rgb c.accentAlt} 45deg"; # Solid borders from theme.border (per-theme, palette-resolved) —
"col.inactive_border" = rgb c.overlay; # matches the legacy identity themes, which never used a gradient.
"col.active_border" = rgb t.border.active;
"col.inactive_border" = rgb t.border.inactive;
layout = lib.mkDefault "dwindle"; layout = lib.mkDefault "dwindle";
resize_on_border = lib.mkDefault true; resize_on_border = lib.mkDefault true;
}; };

View File

@@ -33,10 +33,20 @@
{ mods = "$mod"; key = "X"; action = "exec, nomarchy-menu power"; desc = "Power menu"; } { 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"; 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). # SUPER+? (the "question" keysym already implies Shift on most layouts).
{ mods = "$mod"; key = "question"; action = "exec, nomarchy-menu keybinds"; desc = "Keybindings cheatsheet"; } { mods = "$mod"; key = "question"; action = "exec, nomarchy-menu keybinds"; desc = "Keybindings cheatsheet"; }
# Menu functions — SUPER+CTRL+<mnemonic> jumps straight to a
# nomarchy-menu module (all also reachable from the SUPER+M picker).
{ mods = "$mod CTRL"; key = "V"; action = "exec, nomarchy-menu clipboard"; desc = "Clipboard history"; }
{ mods = "$mod CTRL"; key = "C"; action = "exec, nomarchy-menu calc"; desc = "Calculator"; }
{ mods = "$mod CTRL"; key = "W"; action = "exec, nomarchy-menu web"; desc = "Web search"; }
{ mods = "$mod CTRL"; key = "F"; action = "exec, nomarchy-menu files"; desc = "File search"; }
{ mods = "$mod CTRL"; key = "N"; action = "exec, nomarchy-menu network"; desc = "Network (nmtui)"; }
{ mods = "$mod CTRL"; key = "B"; action = "exec, nomarchy-menu bluetooth"; desc = "Bluetooth"; }
{ mods = "$mod CTRL"; key = "S"; action = "exec, nomarchy-menu capture"; desc = "Screenshot / capture"; }
{ mods = "$mod CTRL"; key = "A"; action = "exec, nomarchy-menu ask"; desc = "Ask Claude"; }
# Focus # Focus
{ mods = "$mod"; key = "H"; action = "movefocus, l"; desc = "Focus left"; } { mods = "$mod"; key = "H"; action = "movefocus, l"; desc = "Focus left"; }
{ mods = "$mod"; key = "L"; action = "movefocus, r"; desc = "Focus right"; } { mods = "$mod"; key = "L"; action = "movefocus, r"; desc = "Focus right"; }

View File

@@ -56,35 +56,41 @@ in
palettes.nomarchy = { palettes.nomarchy = {
inherit (c) base text accent good warn bad subtext; inherit (c) base text accent good warn bad subtext;
}; };
# Flat prompt — colored text only, no powerline separators or
# background fills. Each module emits its own trailing space so
# there are no stray gaps when git/duration are absent.
format = lib.concatStrings [ format = lib.concatStrings [
"[](accent)"
"$directory" "$directory"
"$git_branch$git_status" "$git_branch"
"$git_status"
"$cmd_duration"
"$character" "$character"
]; ];
directory = { directory = {
style = "fg:text bg:accent"; style = "bold accent";
format = "[ $path ]($style)"; format = "[$path]($style) ";
truncation_length = 3; truncation_length = 3;
truncate_to_repo = true; truncate_to_repo = true;
}; };
git_branch = { git_branch = {
style = "fg:base bg:warn"; style = "warn";
format = "[ $symbol$branch ]($style)"; format = "[$symbol$branch]($style) ";
symbol = " "; symbol = " ";
}; };
git_status = { git_status = {
style = "fg:base bg:warn"; style = "subtext";
format = "[$all_status$ahead_behind ]($style)"; # Parenthesised → the segment (and its trailing space) only
# render when there's actually a status to show.
format = "([$all_status$ahead_behind]($style) )";
}; };
character = { character = {
success_symbol = "[ ](good)"; success_symbol = "[](good)";
error_symbol = "[ ](bad)"; error_symbol = "[](bad)";
}; };
cmd_duration = { cmd_duration = {
min_time = 2000; min_time = 2000;
style = "fg:subtext"; style = "subtext";
format = "[ $duration ]($style)"; format = "[ $duration]($style) ";
}; };
}; };
}; };

View File

@@ -47,10 +47,24 @@ let
# Icon theme name; "" means "pick by mode" (resolved below). A preset # Icon theme name; "" means "pick by mode" (resolved below). A preset
# or the state file can name any theme in the shipped icon package. # or the state file can name any theme in the shipped icon package.
icons = ""; icons = "";
# Window border colors. Values are palette keys (resolved against
# `colors` below) or literal #rrggbb. Solid, not a gradient — every
# legacy identity theme used a solid border (accent for most, the text
# tone for kanagawa/summer-*). Each preset declares its own so a theme
# switch always replaces it (deep_merge would otherwise leave it stuck).
border = { active = "accent"; inactive = "overlay"; };
}; };
parsed = lib.recursiveUpdate defaults themeState; parsed = lib.recursiveUpdate defaults themeState;
# A border value is a palette key (look it up in colors) unless it's
# already a literal hex; unknown keys fall through to the raw string.
resolveColor = v: if lib.hasPrefix "#" v then v else parsed.colors.${v} or v;
border = {
active = resolveColor parsed.border.active;
inactive = resolveColor parsed.border.inactive;
};
# Resolve the icon theme once and expose it on nomarchy.theme so both # Resolve the icon theme once and expose it on nomarchy.theme so both
# the GTK side (stylix.nix) and rofi (rofi.nix) agree. The shipped # the GTK side (stylix.nix) and rofi (rofi.nix) agree. The shipped
# package (papirus-icon-theme) carries the Dark/Light pair. # package (papirus-icon-theme) carries the Dark/Light pair.
@@ -61,7 +75,7 @@ let
in in
{ {
config = { config = {
nomarchy.theme = parsed // { inherit iconTheme; }; nomarchy.theme = parsed // { inherit iconTheme border; };
nomarchy.lib = { nomarchy.lib = {
# "#7aa2f7" -> "rgb(7aa2f7)" (Hyprland color syntax) # "#7aa2f7" -> "rgb(7aa2f7)" (Hyprland color syntax)

View File

@@ -18,6 +18,10 @@
"warn": "#e0af68", "warn": "#e0af68",
"bad": "#f7768e" "bad": "#f7768e"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#32344a", "#32344a",
"#f7768e", "#f7768e",

View File

@@ -18,6 +18,10 @@
"warn": "#df8e1d", "warn": "#df8e1d",
"bad": "#d20f39" "bad": "#d20f39"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#bcc0cc", "#bcc0cc",
"#d20f39", "#d20f39",

View File

@@ -18,6 +18,10 @@
"warn": "#f9e2af", "warn": "#f9e2af",
"bad": "#f38ba8" "bad": "#f38ba8"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#45475a", "#45475a",
"#f38ba8", "#f38ba8",

View File

@@ -18,6 +18,10 @@
"warn": "#E9BB4F", "warn": "#E9BB4F",
"bad": "#ED5B5A" "bad": "#ED5B5A"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#060B1E", "#060B1E",
"#ED5B5A", "#ED5B5A",

View File

@@ -18,6 +18,10 @@
"warn": "#dbbc7f", "warn": "#dbbc7f",
"bad": "#e67e80" "bad": "#e67e80"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#475258", "#475258",
"#e67e80", "#e67e80",

View File

@@ -18,6 +18,10 @@
"warn": "#D0A215", "warn": "#D0A215",
"bad": "#D14D41" "bad": "#D14D41"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#100F0F", "#100F0F",
"#D14D41", "#D14D41",

View File

@@ -18,6 +18,10 @@
"warn": "#d8a657", "warn": "#d8a657",
"bad": "#ea6962" "bad": "#ea6962"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#3c3836", "#3c3836",
"#ea6962", "#ea6962",

View File

@@ -18,6 +18,10 @@
"warn": "#50f7d4", "warn": "#50f7d4",
"bad": "#50f872" "bad": "#50f872"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#0B0C16", "#0B0C16",
"#50f872", "#50f872",

View File

@@ -18,6 +18,10 @@
"warn": "#c0a36e", "warn": "#c0a36e",
"bad": "#c34043" "bad": "#c34043"
}, },
"border": {
"active": "text",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#090618", "#090618",
"#c34043", "#c34043",

View File

@@ -18,6 +18,10 @@
"warn": "#6fa4c9", "warn": "#6fa4c9",
"bad": "#4d86b0" "bad": "#4d86b0"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#1b2d40", "#1b2d40",
"#4d86b0", "#4d86b0",

View File

@@ -18,6 +18,10 @@
"warn": "#b91c1c", "warn": "#b91c1c",
"bad": "#D35F5F" "bad": "#D35F5F"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#333333", "#333333",
"#D35F5F", "#D35F5F",

View File

@@ -18,6 +18,10 @@
"warn": "#b36d43", "warn": "#b36d43",
"bad": "#685742" "bad": "#685742"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#000000", "#000000",
"#685742", "#685742",

View File

@@ -18,6 +18,10 @@
"warn": "#ebcb8b", "warn": "#ebcb8b",
"bad": "#bf616a" "bad": "#bf616a"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#3b4252", "#3b4252",
"#bf616a", "#bf616a",

View File

@@ -18,6 +18,10 @@
"warn": "#459451", "warn": "#459451",
"bad": "#FF5345" "bad": "#FF5345"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#23372B", "#23372B",
"#FF5345", "#FF5345",

View File

@@ -18,6 +18,10 @@
"warn": "#e97b3c", "warn": "#e97b3c",
"bad": "#f85525" "bad": "#f85525"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#00172e", "#00172e",
"#f85525", "#f85525",

View File

@@ -18,6 +18,10 @@
"warn": "#f9cc6c", "warn": "#f9cc6c",
"bad": "#fd6883" "bad": "#fd6883"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#72696a", "#72696a",
"#fd6883", "#fd6883",

View File

@@ -18,6 +18,10 @@
"warn": "#ea9d34", "warn": "#ea9d34",
"bad": "#b4637a" "bad": "#b4637a"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#f2e9e1", "#f2e9e1",
"#b4637a", "#b4637a",

View File

@@ -18,6 +18,10 @@
"warn": "#dfa000", "warn": "#dfa000",
"bad": "#f85552" "bad": "#f85552"
}, },
"border": {
"active": "text",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#5c6a72", "#5c6a72",
"#f85552", "#f85552",

View File

@@ -18,11 +18,7 @@
"all-outputs": true, "all-outputs": true,
"on-click": "activate", "on-click": "activate",
"on-scroll-up": "hyprctl dispatch workspace e+1", "on-scroll-up": "hyprctl dispatch workspace e+1",
"on-scroll-down": "hyprctl dispatch workspace e-1", "on-scroll-down": "hyprctl dispatch workspace e-1"
"persistent-workspaces": {
"1": [], "2": [], "3": [], "4": [], "5": [],
"6": [], "7": [], "8": [], "9": [], "10": []
}
}, },
"custom/launcher": { "custom/launcher": {

View File

@@ -18,6 +18,10 @@
"warn": "#d9bb80", "warn": "#d9bb80",
"bad": "#e68183" "bad": "#e68183"
}, },
"border": {
"active": "text",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#3c474d", "#3c474d",
"#e68183", "#e68183",

View File

@@ -18,11 +18,7 @@
"all-outputs": true, "all-outputs": true,
"on-click": "activate", "on-click": "activate",
"on-scroll-up": "hyprctl dispatch workspace r+1", "on-scroll-up": "hyprctl dispatch workspace r+1",
"on-scroll-down": "hyprctl dispatch workspace r-1", "on-scroll-down": "hyprctl dispatch workspace r-1"
"persistent-workspaces": {
"1": [], "2": [], "3": [], "4": [], "5": [],
"6": [], "7": [], "8": [], "9": [], "10": []
}
}, },
"custom/nomarchy": { "custom/nomarchy": {

View File

@@ -18,6 +18,10 @@
"warn": "#e0af68", "warn": "#e0af68",
"bad": "#f7768e" "bad": "#f7768e"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#32344a", "#32344a",
"#f7768e", "#f7768e",

View File

@@ -18,6 +18,10 @@
"warn": "#cecece", "warn": "#cecece",
"bad": "#a4a4a4" "bad": "#a4a4a4"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#0d0d0d", "#0d0d0d",
"#a4a4a4", "#a4a4a4",

View File

@@ -18,6 +18,10 @@
"warn": "#4a4a4a", "warn": "#4a4a4a",
"bad": "#2a2a2a" "bad": "#2a2a2a"
}, },
"border": {
"active": "accent",
"inactive": "overlay"
},
"ansi": [ "ansi": [
"#ffffff", "#ffffff",
"#2a2a2a", "#2a2a2a",