Files
NixOS-Configs/home/hypr/hyprland.lua
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

283 lines
9.1 KiB
Lua

-- 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)