Auto-inject the Hyprland capture hook on plugin load

The capture script must run inside Hyprland's Lua config, but a plugin
cannot register itself in the user-owned hyprland.lua. On first load the
panel appends a small guarded block that dofiles key-visualizer.lua; Hyprland
auto-reloads its config on save, so install is now just add + enable.

The block is idempotent (marker comment), upgrades older plain dofile
lines, and no-ops when the plugin folder is removed so uninstalling never
breaks the config.
This commit is contained in:
felixzsh
2026-08-11 10:11:35 -05:00
parent 64e44c299b
commit 4955c33767
+64
View File
@@ -11,6 +11,11 @@ import qs.Ui
// $XDG_RUNTIME_DIR/omarchy-key-visualizer.json. This panel watches that file
// and renders. No images, no animations: the combo appears while held and
// disappears the moment the keys are released.
//
// On first load the panel also appends a small guarded block to
// ~/.config/hypr/hyprland.lua that dofiles the capture script, so install
// is just add + enable; Hyprland auto-reloads its config on save. The
// block no-ops if the plugin folder is later removed.
Item {
id: root
@@ -98,6 +103,65 @@ Item {
onFileChanged: reload()
}
// ------------------------------------------------- capture hook injection
//
// The capture script (key-visualizer.lua) must run inside Hyprland's Lua
// config, but the plugin cannot register itself there — the user owns
// hyprland.lua. On first load we append a small guarded block that
// dofiles the script; Hyprland auto-reloads its config on save, so the
// whole install is: add + enable. The block is idempotent and no-ops if
// the plugin folder is later removed, so uninstalling never breaks the
// config.
readonly property string captureMarker: "-- [key-visualizer] capture hook"
readonly property string captureBlock: {
var lines = [
"",
"-- [key-visualizer] capture hook (managed by the plugin; safe to remove)",
'local kc_path = os.getenv("HOME") .. "/.config/omarchy/plugins/felixzsh.key-visualizer/key-visualizer.lua"',
'local kc_file = io.open(kc_path, "r")',
'if kc_file then kc_file:close(); dofile(kc_path) end',
""
]
return lines.join("\n")
}
function maybeInjectCapture(raw) {
if (!raw) return
if (raw.indexOf(root.captureMarker) !== -1) return
var kept = []
var lines = raw.split("\n")
for (var i = 0; i < lines.length; i++) {
// Drop an older plain dofile line (manual installs, previous versions)
// so the block below is the only reference and stays upgradeable.
if (lines[i].indexOf("key-visualizer.lua") !== -1) continue
kept.push(lines[i])
}
console.log("key-visualizer: injecting capture hook into hyprland.lua")
hyprConfFile.setText(kept.join("\n") + root.captureBlock)
injectReloadTimer.start()
}
Timer {
id: injectReloadTimer
interval: 400
onTriggered: reloadProc.running = true
}
Process {
id: reloadProc
command: ["hyprctl", "reload"]
}
FileView {
id: hyprConfFile
path: Quickshell.env("HOME") + "/.config/hypr/hyprland.lua"
watchChanges: true
printErrors: false
onLoaded: root.maybeInjectCapture(text())
onFileChanged: reload()
}
// Lifecycle required for panel plugins: summoning is a no-op because the
// display is driven by the state file; hiding closes the window.
function open(payloadJson) {}