Files
NixOS-Configs/home/hypr/hyprland.nix
Anish Govind d1e243dd12 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.
2026-09-19 01:14:33 -07:00

108 lines
3.1 KiB
Nix

{
lib,
config,
theme,
my,
...
}:
let
# 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
{
# -------------------------------------------------------------------------
# Per-host monitor configuration.
#
# Hosts declare their displays once, in hosts/<host>/default.nix, via:
# home-manager.users.<my.username>.hypr.monitors = [ { ... } ];
# 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";
type = lib.types.listOf (
lib.types.submodule {
options = {
output = lib.mkOption {
type = lib.types.str;
default = "";
description = "Output name or desc: match. Empty string matches every output.";
};
mode = lib.mkOption {
type = lib.types.str;
default = "preferred";
description = "Resolution@refresh, e.g. \"3840x2160@164.99Hz\" or \"preferred\".";
};
position = lib.mkOption {
type = lib.types.str;
default = "auto";
};
scale = lib.mkOption {
type = lib.types.either lib.types.number lib.types.str;
default = "auto";
};
vrr = lib.mkOption {
type = lib.types.nullOr (lib.types.either lib.types.number lib.types.str);
default = null;
description = "Optional per-monitor VRR setting (0/1/on-demand).";
};
};
}
);
default = [
{
output = "";
mode = "preferred";
position = "auto";
scale = "auto";
}
];
};
config = {
# 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";
# Generated fragments required by the live config.
xdg.configFile."hypr/theme.lua".text = themeLua;
xdg.configFile."hypr/monitors.lua".text = monitorsLua;
};
}