hypr,nvim,quickshell: make configs live-editable
Symlink three configs straight from the repo with mkOutOfStoreSymlink so edits apply without a rebuild: - home/hypr/hyprland.lua -> reload with `hyprctl reload` - home/hypr/quickshell/** -> restart quickshell - home/nvim/config/** -> next nvim start (lazy-lock.json now writable) Hyprland's config was generated Lua; extract it to a hand-maintained file and keep the palette and per-host monitors as generated fragments (theme.lua / monitors.lua) loaded via dofile. The file also restores the startup hook that imports the Wayland env into systemd and starts graphical-session.target, which the removed home-manager hyprland module used to provide. Verified: lua syntax + execution against a stub hl, and flake check.
This commit is contained in:
26
README.md
26
README.md
@@ -83,3 +83,29 @@ every home-manager module through `extraSpecialArgs`. Tools that only accept a
|
||||
raw config file (starship, rofi, the herdr picker) carry `@color@` placeholders
|
||||
that are substituted from the same palette at build time, so changing an accent
|
||||
means editing one file.
|
||||
|
||||
## Editing configs: live vs generated
|
||||
|
||||
Most configs are generated from Nix and symlinked read-only from the store, so
|
||||
they need a `rebuild switch` to change:
|
||||
|
||||
- `foot.ini`, `hyprlock.conf`, `hypridle.conf`, `mako/config`, `starship.toml`,
|
||||
`rofi/config.rasi`, `.zshenv`/`.zshrc` (Nix attrs, themed)
|
||||
|
||||
Three configs are instead symlinked **straight from the repo** with
|
||||
`mkOutOfStoreSymlink`, so edits apply without a rebuild:
|
||||
|
||||
| Live file | Applies on |
|
||||
| --- | --- |
|
||||
| `home/hypr/hyprland.lua` | `hyprctl reload` |
|
||||
| `home/hypr/quickshell/**` | quickshell restart |
|
||||
| `home/nvim/config/**` (incl. `lazy-lock.json`) | next nvim start; `:Lazy update` writes here |
|
||||
|
||||
Because `hyprland.lua` is live, the palette and per-host monitors are emitted as
|
||||
generated fragments, `~/.config/hypr/theme.lua` and
|
||||
`~/.config/hypr/monitors.lua`, which the live file loads with `dofile`. Edit the
|
||||
Lua directly for anything else.
|
||||
|
||||
The tradeoff: live files are not part of the Nix closure, so the repo must exist
|
||||
at `my.flakeDir` for the symlinks to resolve, and uncommitted edits can drift
|
||||
from git. Keep them committed like any other tracked file.
|
||||
|
||||
282
home/hypr/hyprland.lua
Normal file
282
home/hypr/hyprland.lua
Normal file
@@ -0,0 +1,282 @@
|
||||
-- Silicon Volt Hyprland configuration (hand-maintained).
|
||||
--
|
||||
-- home-manager symlinks this file straight from the repo, so edits apply
|
||||
-- on `hyprctl reload` without a rebuild. The generated fragments
|
||||
-- `theme.lua` (from home/theme.nix) and `monitors.lua` (from hypr.monitors)
|
||||
-- live next to this file and are loaded below.
|
||||
|
||||
local configDir = (os.getenv("XDG_CONFIG_HOME") or (os.getenv("HOME") .. "/.config")) .. "/hypr"
|
||||
local theme = dofile(configDir .. "/theme.lua")
|
||||
local monitors = dofile(configDir .. "/monitors.lua")
|
||||
|
||||
|
||||
-- settings.locals
|
||||
local browser = "brave"
|
||||
local mainMod = "SUPER"
|
||||
local terminal = "foot"
|
||||
|
||||
-- settings.curve
|
||||
hl.curve("myBezier", {
|
||||
["points"] = {
|
||||
{
|
||||
0.05,
|
||||
0.9
|
||||
},
|
||||
{
|
||||
0.1,
|
||||
1.05
|
||||
}
|
||||
},
|
||||
["type"] = "bezier"
|
||||
})
|
||||
|
||||
-- settings.animation
|
||||
hl.animation({
|
||||
["bezier"] = "myBezier",
|
||||
["enabled"] = true,
|
||||
["leaf"] = "windows",
|
||||
["speed"] = 7
|
||||
})
|
||||
hl.animation({
|
||||
["bezier"] = "default",
|
||||
["enabled"] = true,
|
||||
["leaf"] = "windowsOut",
|
||||
["speed"] = 7,
|
||||
["style"] = "popin 80%"
|
||||
})
|
||||
hl.animation({
|
||||
["bezier"] = "default",
|
||||
["enabled"] = true,
|
||||
["leaf"] = "border",
|
||||
["speed"] = 10
|
||||
})
|
||||
hl.animation({
|
||||
["bezier"] = "default",
|
||||
["enabled"] = true,
|
||||
["leaf"] = "borderangle",
|
||||
["speed"] = 8
|
||||
})
|
||||
hl.animation({
|
||||
["bezier"] = "default",
|
||||
["enabled"] = true,
|
||||
["leaf"] = "fade",
|
||||
["speed"] = 7
|
||||
})
|
||||
hl.animation({
|
||||
["bezier"] = "default",
|
||||
["enabled"] = true,
|
||||
["leaf"] = "workspaces",
|
||||
["speed"] = 6
|
||||
})
|
||||
|
||||
-- settings.bind
|
||||
hl.bind((mainMod .. " + Q"), (hl.dsp.exec_cmd(terminal)))
|
||||
hl.bind((mainMod .. " + C"), (hl.dsp.window.close()))
|
||||
hl.bind((mainMod .. " + SPACE"), (hl.dsp.exec_cmd("rofi -show combi -show-icons")))
|
||||
hl.bind((mainMod .. " + N"), (hl.dsp.exec_cmd("swaync-client -t -sw")))
|
||||
hl.bind((mainMod .. " + TAB"), (hl.dsp.exec_cmd("qs ipc call overview toggle")))
|
||||
hl.bind((mainMod .. " + V"), (hl.dsp.window.float({ action = "toggle" })))
|
||||
hl.bind((mainMod .. " + R"), (hl.dsp.exec_cmd("rofi -show combi")))
|
||||
hl.bind((mainMod .. " + G"), (hl.dsp.group.toggle()))
|
||||
hl.bind((mainMod .. " + F"), (hl.dsp.window.fullscreen({ fullscreen = 0 })))
|
||||
hl.bind((mainMod .. " + h"), (hl.dsp.focus({ direction = "left" })))
|
||||
hl.bind((mainMod .. " + l"), (hl.dsp.focus({ direction = "right" })))
|
||||
hl.bind((mainMod .. " + k"), (hl.dsp.focus({ direction = "up" })))
|
||||
hl.bind((mainMod .. " + j"), (hl.dsp.focus({ direction = "down" })))
|
||||
hl.bind((mainMod .. " + e"), (hl.dsp.group.next()))
|
||||
hl.bind((mainMod .. " + d"), (hl.dsp.group.prev()))
|
||||
hl.bind((mainMod .. " + SHIFT + h"), (hl.dsp.window.move({ direction = "left" })))
|
||||
hl.bind((mainMod .. " + SHIFT + l"), (hl.dsp.window.move({ direction = "right" })))
|
||||
hl.bind((mainMod .. " + SHIFT + k"), (hl.dsp.window.move({ direction = "up" })))
|
||||
hl.bind((mainMod .. " + SHIFT + j"), (hl.dsp.window.move({ direction = "down" })))
|
||||
hl.bind((mainMod .. " + mouse_down"), (hl.dsp.focus({ workspace = "e+1" })))
|
||||
hl.bind((mainMod .. " + mouse_up"), (hl.dsp.focus({ workspace = "e-1" })))
|
||||
hl.bind((mainMod .. " + S"), (hl.dsp.exec_cmd("hyprlock")))
|
||||
hl.bind((mainMod .. " + b"), (hl.dsp.exec_cmd(browser)))
|
||||
hl.bind((mainMod .. " + RETURN"), (hl.dsp.workspace.toggle_special("scratch")))
|
||||
hl.bind((mainMod .. " + SHIFT + RETURN"), (hl.dsp.window.move({ workspace = "special:scratch" })))
|
||||
hl.bind((mainMod .. " + M"), (hl.dsp.workspace.toggle_special("messaging")))
|
||||
hl.bind((mainMod .. " + mouse:272"), (hl.dsp.window.drag()), {
|
||||
["mouse"] = true
|
||||
})
|
||||
hl.bind((mainMod .. " + mouse:273"), (hl.dsp.window.resize()), {
|
||||
["mouse"] = true
|
||||
})
|
||||
hl.bind("XF86AudioRaiseVolume", (hl.dsp.exec_cmd("pactl -- set-sink-volume @DEFAULT_SINK@ +5%")), {
|
||||
["repeating"] = true
|
||||
})
|
||||
hl.bind("XF86AudioLowerVolume", (hl.dsp.exec_cmd("pactl -- set-sink-volume @DEFAULT_SINK@ -5%")), {
|
||||
["locked"] = true,
|
||||
["repeating"] = true
|
||||
})
|
||||
hl.bind("XF86AudioMute", (hl.dsp.exec_cmd("pactl -- set-sink-mute @DEFAULT_SINK@ toggle")), {
|
||||
["locked"] = true,
|
||||
["repeating"] = true
|
||||
})
|
||||
hl.bind("XF86MonBrightnessUp", (hl.dsp.exec_cmd("brightnessctl set 5%+")), {
|
||||
["locked"] = true,
|
||||
["repeating"] = true
|
||||
})
|
||||
hl.bind("XF86MonBrightnessDown", (hl.dsp.exec_cmd("brightnessctl set 5%-")), {
|
||||
["locked"] = true,
|
||||
["repeating"] = true
|
||||
})
|
||||
hl.bind("switch:off:Lid Switch", (hl.dsp.exec_cmd("m=$(hyprctl monitors | awk '$1==\"Monitor\"{print $2; exit}'); [ -n \"$m\" ] && hyprctl keyword monitor \"$m, preferred, auto, auto\"")), {
|
||||
["locked"] = true
|
||||
})
|
||||
hl.bind("switch:on:Lid Switch", (hl.dsp.exec_cmd("m=$(hyprctl monitors | awk '$1==\"Monitor\"{print $2; exit}'); [ -n \"$m\" ] && hyprctl keyword monitor \"$m, disable\"")), {
|
||||
["locked"] = true
|
||||
})
|
||||
hl.bind((mainMod .. " + 1"), (hl.dsp.focus({ workspace = 1 })))
|
||||
hl.bind((mainMod .. " + SHIFT + 1"), (hl.dsp.window.move({ workspace = 1 })))
|
||||
hl.bind((mainMod .. " + 2"), (hl.dsp.focus({ workspace = 2 })))
|
||||
hl.bind((mainMod .. " + SHIFT + 2"), (hl.dsp.window.move({ workspace = 2 })))
|
||||
hl.bind((mainMod .. " + 3"), (hl.dsp.focus({ workspace = 3 })))
|
||||
hl.bind((mainMod .. " + SHIFT + 3"), (hl.dsp.window.move({ workspace = 3 })))
|
||||
hl.bind((mainMod .. " + 4"), (hl.dsp.focus({ workspace = 4 })))
|
||||
hl.bind((mainMod .. " + SHIFT + 4"), (hl.dsp.window.move({ workspace = 4 })))
|
||||
hl.bind((mainMod .. " + 5"), (hl.dsp.focus({ workspace = 5 })))
|
||||
hl.bind((mainMod .. " + SHIFT + 5"), (hl.dsp.window.move({ workspace = 5 })))
|
||||
hl.bind((mainMod .. " + 6"), (hl.dsp.focus({ workspace = 6 })))
|
||||
hl.bind((mainMod .. " + SHIFT + 6"), (hl.dsp.window.move({ workspace = 6 })))
|
||||
hl.bind((mainMod .. " + 7"), (hl.dsp.focus({ workspace = 7 })))
|
||||
hl.bind((mainMod .. " + SHIFT + 7"), (hl.dsp.window.move({ workspace = 7 })))
|
||||
hl.bind((mainMod .. " + 8"), (hl.dsp.focus({ workspace = 8 })))
|
||||
hl.bind((mainMod .. " + SHIFT + 8"), (hl.dsp.window.move({ workspace = 8 })))
|
||||
hl.bind((mainMod .. " + 9"), (hl.dsp.focus({ workspace = 9 })))
|
||||
hl.bind((mainMod .. " + SHIFT + 9"), (hl.dsp.window.move({ workspace = 9 })))
|
||||
hl.bind((mainMod .. " + 0"), (hl.dsp.focus({ workspace = 10 })))
|
||||
hl.bind((mainMod .. " + SHIFT + 0"), (hl.dsp.window.move({ workspace = 10 })))
|
||||
|
||||
-- settings.config
|
||||
hl.config({
|
||||
["animations"] = {
|
||||
["enabled"] = true
|
||||
},
|
||||
["cursor"] = {
|
||||
["inactive_timeout"] = 3,
|
||||
["no_hardware_cursors"] = false
|
||||
},
|
||||
["decoration"] = {
|
||||
["blur"] = {
|
||||
["brightness"] = 0.9,
|
||||
["contrast"] = 1.1,
|
||||
["enabled"] = true,
|
||||
["ignore_opacity"] = true,
|
||||
["new_optimizations"] = true,
|
||||
["passes"] = 2,
|
||||
["size"] = 4,
|
||||
["vibrancy"] = 0.1
|
||||
},
|
||||
["rounding"] = 4,
|
||||
["shadow"] = {
|
||||
["color"] = "rgba(00000066)",
|
||||
["enabled"] = true,
|
||||
["range"] = 12,
|
||||
["render_power"] = 3
|
||||
}
|
||||
},
|
||||
["dwindle"] = {
|
||||
["preserve_split"] = true
|
||||
},
|
||||
["general"] = {
|
||||
["border_size"] = 2,
|
||||
["col"] = {
|
||||
["active_border"] = {
|
||||
["angle"] = 45,
|
||||
["colors"] = {
|
||||
"rgba(" .. theme.bare.accentVolt .. "ee)",
|
||||
"rgba(" .. theme.bare.accentVoltLight .. "ee)"
|
||||
}
|
||||
},
|
||||
["inactive_border"] = "rgba(" .. theme.bare.textPrimary .. "14)"
|
||||
},
|
||||
["gaps_in"] = 5,
|
||||
["gaps_out"] = 10,
|
||||
["layout"] = "dwindle"
|
||||
},
|
||||
["group"] = {
|
||||
["col"] = {
|
||||
["border_active"] = {
|
||||
["angle"] = 45,
|
||||
["colors"] = {
|
||||
"rgba(" .. theme.bare.accentVolt .. "ee)",
|
||||
"rgba(" .. theme.bare.accentVoltLight .. "ee)"
|
||||
}
|
||||
},
|
||||
["border_inactive"] = "rgba(" .. theme.bare.textPrimary .. "14)"
|
||||
},
|
||||
["groupbar"] = {
|
||||
["col"] = {
|
||||
["active"] = "rgba(" .. theme.bare.accentVolt .. "22)",
|
||||
["inactive"] = "rgba(" .. theme.bare.textPrimary .. "08)"
|
||||
},
|
||||
["font_family"] = "JetBrainsMono Nerd Font",
|
||||
["font_size"] = 14
|
||||
}
|
||||
},
|
||||
["input"] = {
|
||||
["follow_mouse"] = 1,
|
||||
["kb_layout"] = "us",
|
||||
["repeat_delay"] = 300,
|
||||
["repeat_rate"] = 50,
|
||||
["sensitivity"] = 0,
|
||||
["touchpad"] = {
|
||||
["natural_scroll"] = false
|
||||
}
|
||||
},
|
||||
["master"] = {
|
||||
["new_status"] = "master"
|
||||
},
|
||||
["misc"] = {
|
||||
["disable_hyprland_logo"] = true,
|
||||
["disable_splash_rendering"] = true
|
||||
}
|
||||
})
|
||||
|
||||
-- settings.env
|
||||
hl.env("XCURSOR_SIZE", "24")
|
||||
hl.env("XDG_SESSION_TYPE", "wayland")
|
||||
|
||||
-- monitors (generated from hypr.monitors)
|
||||
for _, m in ipairs(monitors) do
|
||||
hl.monitor(m)
|
||||
end
|
||||
-- settings.window_rule
|
||||
hl.window_rule({
|
||||
["match"] = {
|
||||
["class"] = "Signal"
|
||||
},
|
||||
["name"] = "signal-messaging",
|
||||
["workspace"] = "special:messaging"
|
||||
})
|
||||
hl.window_rule({
|
||||
["match"] = {
|
||||
["class"] = "vesktop"
|
||||
},
|
||||
["name"] = "vesktop-messaging",
|
||||
["workspace"] = "special:messaging"
|
||||
})
|
||||
hl.window_rule({
|
||||
["float"] = false,
|
||||
["match"] = {
|
||||
["class"] = "ghidra-Ghidra"
|
||||
},
|
||||
["name"] = "ghidra-tile"
|
||||
})
|
||||
|
||||
-- settings.workspace_rule
|
||||
hl.workspace_rule({
|
||||
["on_created_empty"] = "[] togglegroup",
|
||||
["workspace"] = "name:messaging"
|
||||
})
|
||||
|
||||
|
||||
-- Start the systemd user session target after importing the Wayland
|
||||
-- environment, so the desktop services declared in home/hypr/services.nix
|
||||
-- and home/hypr/quickshell.nix (hypridle, hyprpaper, mako, cliphist,
|
||||
-- quickshell, polkit agent) are pulled in. This replaces the hook that the
|
||||
-- home-manager hyprland module used to generate.
|
||||
hl.on("hyprland.start", function()
|
||||
hl.exec_cmd("dbus-update-activation-environment --systemd DISPLAY HYPRLAND_INSTANCE_SIGNATURE WAYLAND_DISPLAY XDG_CURRENT_DESKTOP XDG_SESSION_TYPE && systemctl --user start graphical-session.target")
|
||||
end)
|
||||
@@ -2,11 +2,47 @@
|
||||
lib,
|
||||
config,
|
||||
theme,
|
||||
my,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
mkLua = lib.generators.mkLuaInline;
|
||||
# Minimal Lua value renderer for the generated fragments.
|
||||
toLua =
|
||||
v:
|
||||
if builtins.isString v then
|
||||
''"${v}"''
|
||||
else if builtins.isBool v then
|
||||
(if v then "true" else "false")
|
||||
else if builtins.isInt v || builtins.isFloat v then
|
||||
toString v
|
||||
else if v == null then
|
||||
"nil"
|
||||
else if builtins.isList v then
|
||||
"{ " + lib.concatMapStringsSep ", " toLua v + " }"
|
||||
else if builtins.isAttrs v then
|
||||
"{ " + lib.concatStringsSep ", " (lib.mapAttrsToList (k: val: "${k} = ${toLua val}") v) + " }"
|
||||
else
|
||||
throw "toLua: unsupported value type";
|
||||
|
||||
themeLua = "return " + toLua { inherit (theme) colors bare; };
|
||||
|
||||
monitorsLua =
|
||||
"return "
|
||||
+ toLua (
|
||||
map (
|
||||
m:
|
||||
{
|
||||
inherit (m)
|
||||
output
|
||||
mode
|
||||
position
|
||||
scale
|
||||
;
|
||||
}
|
||||
// lib.optionalAttrs (m.vrr != null) { inherit (m) vrr; }
|
||||
) config.hypr.monitors
|
||||
);
|
||||
in
|
||||
{
|
||||
# -------------------------------------------------------------------------
|
||||
@@ -14,8 +50,8 @@ in
|
||||
#
|
||||
# Hosts declare their displays once, in hosts/<host>/default.nix, via:
|
||||
# home-manager.users.<my.username>.hypr.monitors = [ { ... } ];
|
||||
# and the setting flows into Hyprland here. The default (empty output +
|
||||
# preferred mode) works on any machine with any display.
|
||||
# The list is rendered to ~/.config/hypr/monitors.lua, which the
|
||||
# hand-maintained hyprland.lua pulls in with require("monitors").
|
||||
# -------------------------------------------------------------------------
|
||||
options.hypr.monitors = lib.mkOption {
|
||||
description = "Hyprland monitor rules for this host";
|
||||
@@ -59,563 +95,13 @@ in
|
||||
};
|
||||
|
||||
config = {
|
||||
wayland.windowManager.hyprland.settings.monitor = map (
|
||||
m:
|
||||
{
|
||||
inherit (m)
|
||||
output
|
||||
mode
|
||||
position
|
||||
scale
|
||||
;
|
||||
}
|
||||
// (lib.optionalAttrs (m.vrr != null) { inherit (m) vrr; })
|
||||
) config.hypr.monitors;
|
||||
# Live, hand-maintained config: symlinked straight to the repo so edits
|
||||
# apply on `hyprctl reload` without a rebuild.
|
||||
xdg.configFile."hypr/hyprland.lua".source =
|
||||
config.lib.file.mkOutOfStoreSymlink "${my.flakeDir}/home/hypr/hyprland.lua";
|
||||
|
||||
wayland.windowManager.hyprland = {
|
||||
enable = true;
|
||||
configType = "lua";
|
||||
package = null; # Hyprland package is managed system-wide via NixOS programs.hyprland
|
||||
|
||||
settings = {
|
||||
# -----------------------------------------------------------------------
|
||||
# 1. Variables & Modifiers (Rendered as Lua local variables)
|
||||
# -----------------------------------------------------------------------
|
||||
mainMod = {
|
||||
_var = "SUPER";
|
||||
};
|
||||
terminal = {
|
||||
_var = "foot";
|
||||
};
|
||||
browser = {
|
||||
_var = "brave";
|
||||
};
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# 2. Monitors (hl.monitor) - declared per-host via hypr.monitors
|
||||
# (see hosts/<host>/default.nix); defaults to any display @ preferred.
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# 3. Environment Variables (hl.env)
|
||||
# -----------------------------------------------------------------------
|
||||
env = [
|
||||
{
|
||||
_args = [
|
||||
"XCURSOR_SIZE"
|
||||
"24"
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
"XDG_SESSION_TYPE"
|
||||
"wayland"
|
||||
];
|
||||
}
|
||||
];
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# 4. Main Configuration (hl.config) - Strictly validates against Hyprland 0.55+ schema
|
||||
# -----------------------------------------------------------------------
|
||||
config = {
|
||||
input = {
|
||||
kb_layout = "us";
|
||||
repeat_delay = 300;
|
||||
repeat_rate = 50;
|
||||
follow_mouse = 1;
|
||||
sensitivity = 0;
|
||||
touchpad = {
|
||||
natural_scroll = false;
|
||||
};
|
||||
};
|
||||
|
||||
cursor = {
|
||||
inactive_timeout = 3;
|
||||
# Hardware cursors ON (explicit). Note: this replaces the old
|
||||
# WLR_NO_HARDWARE_CURSORS=1, which forced software rendering.
|
||||
no_hardware_cursors = false;
|
||||
};
|
||||
|
||||
general = {
|
||||
gaps_in = 5;
|
||||
gaps_out = 10;
|
||||
border_size = 2;
|
||||
col = {
|
||||
# Silicon Volt: electric lime gradient on focus, glass gray at rest
|
||||
active_border = {
|
||||
colors = [
|
||||
"rgba(${theme.bare.accentVolt}ee)"
|
||||
"rgba(${theme.bare.accentVoltLight}ee)"
|
||||
];
|
||||
angle = 45;
|
||||
};
|
||||
inactive_border = "rgba(${theme.bare.textPrimary}14)";
|
||||
};
|
||||
layout = "dwindle";
|
||||
};
|
||||
|
||||
group = {
|
||||
groupbar = {
|
||||
font_size = 14;
|
||||
font_family = "JetBrainsMono Nerd Font";
|
||||
col = {
|
||||
active = "rgba(${theme.bare.accentVolt}22)";
|
||||
inactive = "rgba(${theme.bare.textPrimary}08)";
|
||||
};
|
||||
};
|
||||
|
||||
col = {
|
||||
border_active = {
|
||||
colors = [
|
||||
"rgba(${theme.bare.accentVolt}ee)"
|
||||
"rgba(${theme.bare.accentVoltLight}ee)"
|
||||
];
|
||||
angle = 45;
|
||||
};
|
||||
border_inactive = "rgba(${theme.bare.textPrimary}14)";
|
||||
};
|
||||
};
|
||||
|
||||
misc = {
|
||||
disable_hyprland_logo = true;
|
||||
disable_splash_rendering = true;
|
||||
};
|
||||
|
||||
decoration = {
|
||||
rounding = 4;
|
||||
|
||||
# Subtle glass blur to match the brutalist-glass aesthetic
|
||||
blur = {
|
||||
enabled = true;
|
||||
size = 4;
|
||||
passes = 2;
|
||||
new_optimizations = true;
|
||||
ignore_opacity = true;
|
||||
contrast = 1.1;
|
||||
brightness = 0.9;
|
||||
vibrancy = 0.1;
|
||||
};
|
||||
|
||||
shadow = {
|
||||
enabled = true;
|
||||
range = 12;
|
||||
render_power = 3;
|
||||
color = "rgba(00000066)";
|
||||
};
|
||||
};
|
||||
|
||||
animations = {
|
||||
enabled = true;
|
||||
};
|
||||
|
||||
dwindle = {
|
||||
preserve_split = true;
|
||||
};
|
||||
|
||||
master = {
|
||||
new_status = "master";
|
||||
};
|
||||
};
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# 5. Curves & Animations (hl.curve & hl.animation)
|
||||
# -----------------------------------------------------------------------
|
||||
curve = [
|
||||
{
|
||||
_args = [
|
||||
"myBezier"
|
||||
{
|
||||
type = "bezier";
|
||||
points = [
|
||||
[
|
||||
0.05
|
||||
0.9
|
||||
]
|
||||
[
|
||||
0.1
|
||||
1.05
|
||||
]
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
|
||||
animation = [
|
||||
{
|
||||
leaf = "windows";
|
||||
enabled = true;
|
||||
speed = 7;
|
||||
bezier = "myBezier";
|
||||
}
|
||||
{
|
||||
leaf = "windowsOut";
|
||||
enabled = true;
|
||||
speed = 7;
|
||||
bezier = "default";
|
||||
style = "popin 80%";
|
||||
}
|
||||
{
|
||||
leaf = "border";
|
||||
enabled = true;
|
||||
speed = 10;
|
||||
bezier = "default";
|
||||
}
|
||||
{
|
||||
leaf = "borderangle";
|
||||
enabled = true;
|
||||
speed = 8;
|
||||
bezier = "default";
|
||||
}
|
||||
{
|
||||
leaf = "fade";
|
||||
enabled = true;
|
||||
speed = 7;
|
||||
bezier = "default";
|
||||
}
|
||||
{
|
||||
leaf = "workspaces";
|
||||
enabled = true;
|
||||
speed = 6;
|
||||
bezier = "default";
|
||||
}
|
||||
];
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# 6. Autostart Daemons & Apps
|
||||
# -----------------------------------------------------------------------
|
||||
# Desktop daemons (quickshell, hyprpaper, mako, cliphist and the
|
||||
# polkit agent) are declared as systemd user services in
|
||||
# home/hypr/services.nix and home/hypr/quickshell.nix, tied to the
|
||||
# Wayland session target instead of exec-once.
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# 7. Keybindings (hl.bind)
|
||||
# -----------------------------------------------------------------------
|
||||
bind = [
|
||||
# Launchers & Window Controls
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + Q\"")
|
||||
(mkLua "hl.dsp.exec_cmd(terminal)")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + C\"")
|
||||
(mkLua "hl.dsp.window.close()")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + SPACE\"")
|
||||
(mkLua "hl.dsp.exec_cmd(\"rofi -show combi -show-icons\")")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + N\"")
|
||||
(mkLua "hl.dsp.exec_cmd(\"swaync-client -t -sw\")")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + TAB\"")
|
||||
(mkLua "hl.dsp.exec_cmd(\"qs ipc call overview toggle\")")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + V\"")
|
||||
(mkLua "hl.dsp.window.float({ action = \"toggle\" })")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + R\"")
|
||||
(mkLua "hl.dsp.exec_cmd(\"rofi -show combi\")")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + G\"")
|
||||
(mkLua "hl.dsp.group.toggle()")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + F\"")
|
||||
(mkLua "hl.dsp.window.fullscreen({ fullscreen = 0 })")
|
||||
];
|
||||
}
|
||||
|
||||
# Move focus with mainMod + vim
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + h\"")
|
||||
(mkLua "hl.dsp.focus({ direction = \"left\" })")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + l\"")
|
||||
(mkLua "hl.dsp.focus({ direction = \"right\" })")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + k\"")
|
||||
(mkLua "hl.dsp.focus({ direction = \"up\" })")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + j\"")
|
||||
(mkLua "hl.dsp.focus({ direction = \"down\" })")
|
||||
];
|
||||
}
|
||||
|
||||
# Move focus within a grouped page
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + e\"")
|
||||
(mkLua "hl.dsp.group.next()")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + d\"")
|
||||
(mkLua "hl.dsp.group.prev()")
|
||||
];
|
||||
}
|
||||
|
||||
# Move window or group with vim keys
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + SHIFT + h\"")
|
||||
(mkLua "hl.dsp.window.move({ direction = \"left\" })")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + SHIFT + l\"")
|
||||
(mkLua "hl.dsp.window.move({ direction = \"right\" })")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + SHIFT + k\"")
|
||||
(mkLua "hl.dsp.window.move({ direction = \"up\" })")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + SHIFT + j\"")
|
||||
(mkLua "hl.dsp.window.move({ direction = \"down\" })")
|
||||
];
|
||||
}
|
||||
|
||||
# Scroll through existing workspaces with mainMod + scroll
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + mouse_down\"")
|
||||
(mkLua "hl.dsp.focus({ workspace = \"e+1\" })")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + mouse_up\"")
|
||||
(mkLua "hl.dsp.focus({ workspace = \"e-1\" })")
|
||||
];
|
||||
}
|
||||
|
||||
# Lock shortcut
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + S\"")
|
||||
(mkLua "hl.dsp.exec_cmd(\"hyprlock\")")
|
||||
];
|
||||
}
|
||||
|
||||
# Quick access applications
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + b\"")
|
||||
(mkLua "hl.dsp.exec_cmd(browser)")
|
||||
];
|
||||
}
|
||||
|
||||
# Scratch workspace
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + RETURN\"")
|
||||
(mkLua "hl.dsp.workspace.toggle_special(\"scratch\")")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + SHIFT + RETURN\"")
|
||||
(mkLua "hl.dsp.window.move({ workspace = \"special:scratch\" })")
|
||||
];
|
||||
}
|
||||
|
||||
# Messaging workspace
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + M\"")
|
||||
(mkLua "hl.dsp.workspace.toggle_special(\"messaging\")")
|
||||
];
|
||||
}
|
||||
|
||||
# Move/resize windows with mouse and dragging
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + mouse:272\"")
|
||||
(mkLua "hl.dsp.window.drag()")
|
||||
{ mouse = true; }
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + mouse:273\"")
|
||||
(mkLua "hl.dsp.window.resize()")
|
||||
{ mouse = true; }
|
||||
];
|
||||
}
|
||||
|
||||
# Function Row Keys
|
||||
{
|
||||
_args = [
|
||||
"XF86AudioRaiseVolume"
|
||||
(mkLua "hl.dsp.exec_cmd(\"pactl -- set-sink-volume @DEFAULT_SINK@ +5%\")")
|
||||
{ repeating = true; }
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
"XF86AudioLowerVolume"
|
||||
(mkLua "hl.dsp.exec_cmd(\"pactl -- set-sink-volume @DEFAULT_SINK@ -5%\")")
|
||||
{
|
||||
repeating = true;
|
||||
locked = true;
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
"XF86AudioMute"
|
||||
(mkLua "hl.dsp.exec_cmd(\"pactl -- set-sink-mute @DEFAULT_SINK@ toggle\")")
|
||||
{
|
||||
repeating = true;
|
||||
locked = true;
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
"XF86MonBrightnessUp"
|
||||
(mkLua "hl.dsp.exec_cmd(\"brightnessctl set 5%+\")")
|
||||
{
|
||||
repeating = true;
|
||||
locked = true;
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
"XF86MonBrightnessDown"
|
||||
(mkLua "hl.dsp.exec_cmd(\"brightnessctl set 5%-\")")
|
||||
{
|
||||
repeating = true;
|
||||
locked = true;
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
# Lid switch - generically detects the embedded (eDP*) panel on any laptop
|
||||
{
|
||||
_args = [
|
||||
"switch:off:Lid Switch"
|
||||
(mkLua "hl.dsp.exec_cmd(\"m=$(hyprctl monitors | awk '$1==\\\"Monitor\\\"{print $2; exit}'); [ -n \\\"$m\\\" ] && hyprctl keyword monitor \\\"$m, preferred, auto, auto\\\"\")")
|
||||
{ locked = true; }
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
"switch:on:Lid Switch"
|
||||
(mkLua "hl.dsp.exec_cmd(\"m=$(hyprctl monitors | awk '$1==\\\"Monitor\\\"{print $2; exit}'); [ -n \\\"$m\\\" ] && hyprctl keyword monitor \\\"$m, disable\\\"\")")
|
||||
{ locked = true; }
|
||||
];
|
||||
}
|
||||
]
|
||||
# Workspace 1-9 switching and moving
|
||||
++ (lib.concatMap (i: [
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + ${toString i}\"")
|
||||
(mkLua "hl.dsp.focus({ workspace = ${toString i} })")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + SHIFT + ${toString i}\"")
|
||||
(mkLua "hl.dsp.window.move({ workspace = ${toString i} })")
|
||||
];
|
||||
}
|
||||
]) (lib.range 1 9))
|
||||
# Workspace 10 switching and moving (mapped to key 0)
|
||||
++ [
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + 0\"")
|
||||
(mkLua "hl.dsp.focus({ workspace = 10 })")
|
||||
];
|
||||
}
|
||||
{
|
||||
_args = [
|
||||
(mkLua "mainMod .. \" + SHIFT + 0\"")
|
||||
(mkLua "hl.dsp.window.move({ workspace = 10 })")
|
||||
];
|
||||
}
|
||||
];
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# 8. Workspace Rules (hl.workspace_rule)
|
||||
# -----------------------------------------------------------------------
|
||||
workspace_rule = [
|
||||
{
|
||||
workspace = "name:messaging";
|
||||
on_created_empty = "[] togglegroup";
|
||||
}
|
||||
];
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# 9. Window Rules (hl.window_rule)
|
||||
# -----------------------------------------------------------------------
|
||||
window_rule = [
|
||||
{
|
||||
name = "signal-messaging";
|
||||
match = {
|
||||
class = "Signal";
|
||||
};
|
||||
workspace = "special:messaging";
|
||||
}
|
||||
{
|
||||
name = "vesktop-messaging";
|
||||
match = {
|
||||
class = "vesktop";
|
||||
};
|
||||
workspace = "special:messaging";
|
||||
}
|
||||
{
|
||||
name = "ghidra-tile";
|
||||
match = {
|
||||
class = "ghidra-Ghidra";
|
||||
};
|
||||
float = false;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
# Generated fragments required by the live config.
|
||||
xdg.configFile."hypr/theme.lua".text = themeLua;
|
||||
xdg.configFile."hypr/monitors.lua".text = monitorsLua;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
{ pkgs, inputs, ... }:
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
config,
|
||||
my,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
quickshellPkg =
|
||||
@@ -16,11 +22,10 @@ in
|
||||
{
|
||||
# Quickshell overview module for Hyprland (Super+Tab workspace overview).
|
||||
# Vendored from: https://github.com/Shanu-Kumawat/quickshell-overview
|
||||
# Placed at the quickshell config root so a bare `qs` finds shell.qml.
|
||||
xdg.configFile."quickshell" = {
|
||||
source = ./quickshell;
|
||||
recursive = true;
|
||||
};
|
||||
# Symlinked straight from the repo so edits are live; placed at the
|
||||
# quickshell config root so a bare `qs` finds shell.qml.
|
||||
xdg.configFile."quickshell".source =
|
||||
config.lib.file.mkOutOfStoreSymlink "${my.flakeDir}/home/hypr/quickshell";
|
||||
|
||||
# Run quickshell as a systemd user service tied to the Wayland session.
|
||||
programs.quickshell = {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
my,
|
||||
...
|
||||
}:
|
||||
|
||||
@@ -72,15 +73,14 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
# Symlink LazyVim configuration to ~/.config/nvim recursively. This includes
|
||||
# lazy-lock.json, which pins every plugin to a specific commit for
|
||||
# reproducible builds. To update plugins, run `:Lazy update` in a writable
|
||||
# copy and commit the resulting lazy-lock.json back to this repo, since the
|
||||
# linked file is read-only.
|
||||
xdg.configFile."nvim" = {
|
||||
source = ./config;
|
||||
recursive = true;
|
||||
};
|
||||
# Live LazyVim config symlinked straight from the repo: edits (and
|
||||
# `:Lazy update` writes to lazy-lock.json) apply without a rebuild.
|
||||
xdg.configFile."nvim/init.lua".source =
|
||||
config.lib.file.mkOutOfStoreSymlink "${my.flakeDir}/home/nvim/config/init.lua";
|
||||
xdg.configFile."nvim/lua".source =
|
||||
config.lib.file.mkOutOfStoreSymlink "${my.flakeDir}/home/nvim/config/lua";
|
||||
xdg.configFile."nvim/lazy-lock.json".source =
|
||||
config.lib.file.mkOutOfStoreSymlink "${my.flakeDir}/home/nvim/config/lazy-lock.json";
|
||||
|
||||
# Symlink precompiled Treesitter parsers directly into ~/.config/nvim/parser
|
||||
xdg.configFile."nvim/parser".source = "${treesitterParsers}/parser";
|
||||
|
||||
Reference in New Issue
Block a user