#!/usr/bin/env bash set -euo pipefail # Fixes nwg-displays not auto-updating monitor/workspace configs on hyprctl reload # in Hyprland 0.55+ Lua-based configs. # # Problem: require() caches modules in package.loaded, so updated monitors.lua # is ignored on config reload. Solution: clear the cache before require(). # Also auto-generates workspaces.lua from nwg-displays' workspace.conf if missing. # See https://lua.org/manual/5.1/manual.html#pdf-require HYPR_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/hypr" MAIN_LUA="$HYPR_DIR/hyprland.lua" if [ ! -f "$MAIN_LUA" ]; then echo "Error: $MAIN_LUA not found. Is Hyprland 0.55+ configured with Lua?" exit 1 fi # Create a backup (only if none exists) if [ ! -f "$MAIN_LUA.bak" ]; then cp "$MAIN_LUA" "$MAIN_LUA.bak" echo "Backup saved: $MAIN_LUA.bak" fi patched=0 # Fix monitors if grep -q 'require("monitors")' "$MAIN_LUA" && \ ! grep -q 'package.loaded\["monitors"\]' "$MAIN_LUA"; then sed -i 's/^\s*--\s*require("monitors")/package.loaded["monitors"] = nil\nrequire("monitors")/' "$MAIN_LUA" echo "Patched: monitors.lua require() cache cleared" patched=1 else echo "Skipped monitors: already patched or not found" fi # Fix workspaces if grep -q 'require("workspaces")' "$MAIN_LUA" && \ ! grep -q 'package.loaded\["workspaces"\]' "$MAIN_LUA"; then sed -i 's/^\s*--\s*require("workspaces")/package.loaded["workspaces"] = nil\nrequire("workspaces")/' "$MAIN_LUA" echo "Patched: workspaces.lua require() cache cleared" patched=1 else echo "Skipped workspaces: already patched or not found" fi # --------------------------------------------------------------------------- # Generate workspaces.lua from nwg-displays' workspace.conf if it's missing # --------------------------------------------------------------------------- WORKSPACES_LUA="$HYPR_DIR/workspaces.lua" WORKSPACE_CONF="$HYPR_DIR/workspace.conf" if [ ! -f "$WORKSPACES_LUA" ]; then if [ -f "$WORKSPACE_CONF" ]; then echo "Generating $WORKSPACES_LUA from $WORKSPACE_CONF ..." # Read header comment (first line if it starts with #) HEADER_LINE=$(head -1 "$WORKSPACE_CONF") if [[ "$HEADER_LINE" =~ ^#(.*)$ ]]; then COMMENT_LINE="--${BASH_REMATCH[1]}" fi { [ -n "${COMMENT_LINE:-}" ] && echo "$COMMENT_LINE" echo "" while IFS=',' read -ra fields; do line="${fields[*]}" [[ "$line" =~ ^#.*$ ]] && continue [[ -z "$line" ]] && continue ws_id="" monitor_val="" # Parse workspace=N for field in "${fields[@]}"; do field="$(echo "$field" | xargs)" if [[ "$field" =~ ^workspace=([0-9]+)$ ]]; then ws_id="${BASH_REMATCH[1]}" elif [[ "$field" =~ ^monitor:(.+)$ ]]; then monitor_val="${BASH_REMATCH[1]}" fi done [ -z "$ws_id" ] && continue # Skip disabled workspaces (monitor:false) [ "$monitor_val" = "false" ] && continue if [ "$monitor_val" = "true" ] || [ -z "$monitor_val" ]; then echo "hl.workspace_rule({ workspace = \"$ws_id\" })" else echo "hl.workspace_rule({ workspace = \"$ws_id\", monitor = \"$monitor_val\" })" fi done < <(sed 's/,\s*/,/g' "$WORKSPACE_CONF") } > "$WORKSPACES_LUA" echo "Generated $WORKSPACES_LUA" patched=1 else echo "Warning: $WORKSPACE_CONF not found. Creating default $WORKSPACES_LUA ..." cat > "$WORKSPACES_LUA" <<- 'LUA' -- Default workspaces generated by fix-nwg-hyprland-lua.sh -- Workspaces 1-10 are available on all monitors for i = 1, 10 do hl.workspace_rule({ workspace = tostring(i) }) end LUA echo "Created default $WORKSPACES_LUA" patched=1 fi else echo "Skipped workspaces.lua: already exists" fi # When monitors.lua is missing, only warn (conversion from monitors.conf is # non-trivial; run nwg-displays to generate it, or `cp monitors.conf monitors.lua` # is not valid because the formats differ). if [ ! -f "$HYPR_DIR/monitors.lua" ]; then echo "Warning: $HYPR_DIR/monitors.lua not found." echo " Run nwg-displays to generate it, or create it manually with hl.monitor() calls." fi if [ "$patched" -eq 1 ]; then echo "" echo "Done! Run 'hyprctl reload' or restart Hyprland for the fix to take effect." echo "nwg-displays changes should now apply immediately." else echo "" echo "No changes needed." fi