feat(hyprland): migrate config from .conf to .lua format (Hyprland 0.55+)
- Add hyprland.lua.j2 Ansible template with full Lua DSL config - Update tasks to deploy hyprland.lua instead of hyprland.conf - Add docs/tech/hyprland-lua-migration.md with API reference, dispatcher mapping, pitfalls, and validation commands - Update keybindings doc to reflect .lua config format Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Hyprland Keybindings — Full Cheatsheet
|
||||
# Hyprland Keybindings - Full Cheatsheet
|
||||
|
||||
**Layout:** German (de) | **Mod key:** SUPER (Windows key) | **Source:** `hyprctl binds` live
|
||||
**Layout:** German (de) | **Mod key:** SUPER (Windows key) | **Config:** `hyprland.lua` (Hyprland 0.55+)
|
||||
|
||||
---
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
| `SUPER+SHIFT+TAB` | Cycle previous window | cyclenext prev |
|
||||
| `SUPER+` `` ` `` (Grave) | Toggle scratchpad | togglespecialworkspace |
|
||||
| `SUPER+SHIFT+` `` ` `` | Send window to scratchpad | movetoworkspace special |
|
||||
| `SUPER+CTRL+K` | Keybind cheat menu | *(broken — pipelines to grep+fuzzel)* |
|
||||
| `SUPER+CTRL+K` | Keybind cheat menu | *(broken - pipelines to grep+fuzzel)* |
|
||||
| `SUPER+CTRL+L` | Lock screen | hyprlock |
|
||||
| `SUPER+B` | Web browser | google-chrome-stable |
|
||||
|
||||
@@ -103,8 +103,10 @@ Every kitty terminal tile shows a title bar with:
|
||||
|
||||
## Notes
|
||||
|
||||
- `SUPER+CTRL+K` (keybind menu) does **not work** — the `sed` pipeline breaks. Needs fix.
|
||||
- The `sed` pipeline `sed 's/^bind\s*=\s*\$mainMod/SUPER/;s/\s*#/#/'` fails silently because the unescaped `$` in the `sed` command gets interpreted as a variable.
|
||||
- `SUPER+CTRL+K` (keybind menu) does **not work** - the `sed` pipeline breaks.
|
||||
The Lua config format makes this harder to grep; consider a different approach.
|
||||
- Config migrated from `.conf` to `.lua` format (Hyprland 0.55+).
|
||||
See `docs/tech/hyprland-lua-migration.md` for the migration mapping.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
# Hyprland Lua Config Migration (0.55+)
|
||||
|
||||
## Summary
|
||||
|
||||
Hyprland 0.55 deprecates the legacy `hyprlang` (`.conf`) format in favor of a native Lua
|
||||
DSL (`hyprland.lua`). Both formats coexist during transition, but `.lua` is the future.
|
||||
|
||||
## Configuration File Priority
|
||||
|
||||
| File | Format | Priority |
|
||||
|------|--------|----------|
|
||||
| `~/.config/hypr/hyprland.lua` | Lua DSL (`hl.*` API) | **Preferred** (0.55+) |
|
||||
| `~/.config/hypr/hyprland.conf` | Legacy hyprlang | Deprecated |
|
||||
|
||||
When both exist, Hyprland loads `.lua` first. If `.lua` is present, `.conf` is ignored.
|
||||
|
||||
## Lua API Quick Reference
|
||||
|
||||
```lua
|
||||
-- Variables
|
||||
local terminal = "kitty"
|
||||
local mainMod = "SUPER"
|
||||
|
||||
-- Config blocks
|
||||
hl.config({ general = { gaps_in = 5 } })
|
||||
hl.env("XCURSOR_SIZE", "24")
|
||||
hl.monitor({ output = "", mode = "preferred", position = "auto", scale = "auto" })
|
||||
|
||||
-- Keybindings (single combined key string)
|
||||
hl.bind(mainMod .. " + Q", hl.dsp.window.close())
|
||||
hl.bind(mainMod .. " + T", hl.dsp.exec_cmd(terminal))
|
||||
|
||||
-- Window/workspace rules
|
||||
hl.window_rule({ name = "my-rule", match = { class = ".*" }, suppress_event = "maximize" })
|
||||
hl.workspace_rule({ workspace = 1, monitor = "DP-1", default = true })
|
||||
|
||||
-- Autostart
|
||||
hl.on("hyprland.start", function() hl.exec_cmd("waybar &") end)
|
||||
|
||||
-- Gestures, animations
|
||||
hl.gesture({ fingers = 3, direction = "horizontal", action = "workspace" })
|
||||
hl.curve("easeOutQuint", { type = "bezier", points = { {0.23, 1}, {0.32, 1} } })
|
||||
hl.animation({ leaf = "windows", enabled = true, speed = 4.79, spring = "easy" })
|
||||
```
|
||||
|
||||
## Dispatcher Functions (`hl.dsp.*`)
|
||||
|
||||
| Lua API | Legacy .conf equivalent |
|
||||
|---------|------------------------|
|
||||
| `hl.dsp.exec_cmd("cmd")` | `exec, cmd` |
|
||||
| `hl.dsp.window.close()` | `killactive` |
|
||||
| `hl.dsp.window.float({ action = "toggle" })` | `togglefloating` |
|
||||
| `hl.dsp.window.pseudo()` | `pseudo` |
|
||||
| `hl.dsp.window.fullscreen({ mode = 0 })` | `fullscreen, 0` |
|
||||
| `hl.dsp.window.move({ direction = "left" })` | `movewindow, l` |
|
||||
| `hl.dsp.window.move({ workspace = 2 })` | `movetoworkspace, 2` |
|
||||
| `hl.dsp.window.drag()` / `.resize()` | mouse bind |
|
||||
| `hl.dsp.focus({ direction = "left" })` | `movefocus, l` |
|
||||
| `hl.dsp.focus({ workspace = 2 })` | `workspace, 2` |
|
||||
| `hl.dsp.focus({ workspace = "e+1" })` | `workspace, e+1` |
|
||||
| `hl.dsp.workspace.toggle_special("magic")` | `togglespecialworkspace` |
|
||||
| `hl.dsp.layout("togglesplit")` | `layoutmsg, togglesplit` |
|
||||
|
||||
## Pitfalls Learned
|
||||
|
||||
| Issue | Fix |
|
||||
|-------|-----|
|
||||
| `hl.dsp.focus({ direction = "next" })` | **Invalid.** Only `left/right/up/down` accepted. Use `hl.dsp.exec_cmd("hyprctl dispatch cyclenext")` instead. |
|
||||
| `tap-to-click = true` | **Invalid Lua.** Hyphens not allowed in identifiers. Use `tap_to_click` (Hyprland accepts underscores). |
|
||||
| `hl.bind("", "Print", ...)` | **Invalid.** Lua API uses single key string: `hl.bind("Print", ...)`. |
|
||||
| `hl.bind(mainMod, "Q", ...)` | **Invalid.** Combine into one string: `hl.bind(mainMod .. " + Q", ...)`. |
|
||||
| `resizeactive` not in `hl.dsp.*` | Use `hl.dsp.exec_cmd("hyprctl dispatch resizeactive -40 0")` as wrapper. |
|
||||
| `luac -p` false positives | Standard `luac` can't validate Hyprland's custom `hl.*` API. Use `hyprctl configerrors` at runtime instead. |
|
||||
|
||||
## Validation
|
||||
|
||||
```bash
|
||||
# Runtime validation (requires running Hyprland session)
|
||||
hyprctl configerrors
|
||||
|
||||
# Over SSH (find instance signature first)
|
||||
HYPRLAND_INSTANCE_SIGNATURE=$(ls /run/user/$(id -u)/hypr/) hyprctl configerrors
|
||||
|
||||
# Syntax-only check (limited - won't catch hl.* API issues)
|
||||
luac -p ~/.config/hypr/hyprland.lua
|
||||
```
|
||||
|
||||
## conf-to-lua Migration Mapping
|
||||
|
||||
| Legacy `.conf` | Lua `.lua` |
|
||||
|----------------|------------|
|
||||
| `$mainMod = SUPER` | `local mainMod = "SUPER"` |
|
||||
| `monitor=DP-1,...` | `hl.monitor({ output = "DP-1", ... })` |
|
||||
| `env = KEY,VALUE` | `hl.env("KEY", "VALUE")` |
|
||||
| `input { ... }` | `hl.config({ input = { ... } })` |
|
||||
| `general { ... }` | `hl.config({ general = { ... } })` |
|
||||
| `bind = MOD, KEY, exec, cmd` | `hl.bind(mod .. " + KEY", hl.dsp.exec_cmd("cmd"))` |
|
||||
| `bind = MOD, KEY, killactive` | `hl.bind(mod .. " + KEY", hl.dsp.window.close())` |
|
||||
| `bind = MOD, KEY, togglefloating` | `hl.bind(mod .. " + KEY", hl.dsp.window.float({ action = "toggle" }))` |
|
||||
| `bind = MOD, KEY, fullscreen, 0` | `hl.bind(mod .. " + KEY", hl.dsp.window.fullscreen({ mode = 0 }))` |
|
||||
| `bind = MOD, KEY, movefocus, l` | `hl.bind(mod .. " + KEY", hl.dsp.focus({ direction = "left" }))` |
|
||||
| `bind = MOD, KEY, movewindow, l` | `hl.bind(mod .. " + KEY", hl.dsp.window.move({ direction = "left" }))` |
|
||||
| `bind = MOD, KEY, workspace, N` | `hl.bind(mod .. " + KEY", hl.dsp.focus({ workspace = N }))` |
|
||||
| `bind = MOD, KEY, cyclenext` | `hl.bind(mod .. " + KEY", hl.dsp.exec_cmd("hyprctl dispatch cyclenext"))` |
|
||||
| `bind = MOD, KEY, pseudo` | `hl.bind(mod .. " + KEY", hl.dsp.window.pseudo())` |
|
||||
| `bind = MOD, KEY, layoutmsg, togglesplit` | `hl.bind(mod .. " + KEY", hl.dsp.layout("togglesplit"))` |
|
||||
| `bind = , Print, exec, cmd` | `hl.bind("Print", hl.dsp.exec_cmd("cmd"))` |
|
||||
| `bind = MOD, KEY, exit` | `hl.bind(mod .. " + KEY", hl.dsp.exec_cmd("hyprctl dispatch exit"))` |
|
||||
| `device { name = "..."; ... }` | `hl.device({ name = "...", ... })` |
|
||||
| `workspace = 1, monitor:DP-1, default:true` | `hl.workspace_rule({ workspace = 1, monitor = "DP-1", default = true })` |
|
||||
| `exec-once = cmd` | `hl.on("hyprland.start", function() hl.exec_cmd("cmd") end)` |
|
||||
| `col.active_border = rgba(...) 45deg` | `col = { active_border = { colors = {"rgba(...)"}, angle = 45 } }` |
|
||||
|
||||
## Multi-Machine Setup
|
||||
|
||||
This project manages configs for two machines with identical keybindings but different hardware:
|
||||
|
||||
| Aspect | Workstation (pfeddersheim) | MacBook Pro 16,1 |
|
||||
|--------|---------------------------|-------------------|
|
||||
| GPU | NVIDIA (6 env vars) | Intel UHD 630 + AMD RX 5500M (no env vars) |
|
||||
| Monitors | 3 fixed (DP-1, DVI-D-1, HDMI-A-1) | Built-in + HDMI dock (auto-detect) |
|
||||
| Input | de layout, left-handed mouse | de + mac_nodeadkeys + caps:swapescape, touchpad |
|
||||
| Touchpad | N/A | natural_scroll, gestures, disable_while_typing |
|
||||
| Media keys | N/A | Volume, brightness, playerctl |
|
||||
| Window rules | None | Suppress maximize, XWayland fix |
|
||||
| Config format | `.lua` (Ansible-managed) | `.lua` (manual) |
|
||||
Reference in New Issue
Block a user