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:
@@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user