117 lines
3.8 KiB
Python
Executable File
117 lines
3.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
import re
|
||
|
||
# Path to your Hyprland config
|
||
config_path = "/home/megnas/.config/hypr/hyprland.conf" # replace USERNAME
|
||
|
||
variables = {}
|
||
bind_lines = []
|
||
|
||
# 1️⃣ Read config
|
||
with open(config_path) as f:
|
||
for line in f:
|
||
line = line.strip()
|
||
if not line or line.startswith("#"):
|
||
continue
|
||
# Parse variables
|
||
if line.startswith("$"):
|
||
m = re.match(r"(\$\w+)\s*=\s*(.*)", line)
|
||
if m:
|
||
var, val = m.groups()
|
||
val = val.split("#")[0].strip() # remove comment
|
||
variables[var] = val
|
||
# Parse binds
|
||
if line.startswith(("bind =","bindm =")): #"bindl =","bindel ="
|
||
bind_lines.append(line.split("=",1)[1].strip())
|
||
|
||
# 2️⃣ Map commands to readable actions
|
||
def command_to_text(parts):
|
||
cmd = " ".join(parts[2:]).strip()
|
||
# movefocus mapping
|
||
movefocus_map = {"l":"left","r":"right","u":"up","d":"down"}
|
||
if cmd.startswith("movefocus"):
|
||
dir_key = cmd.split()[-1]
|
||
dir_text = movefocus_map.get(dir_key, dir_key)
|
||
return f"Move focus {dir_text}"
|
||
if "split-workspace" in cmd:
|
||
return f"Changes workspace to {parts[-1]}"
|
||
if "exit" in cmd:
|
||
return "Exits Hyprland"
|
||
if "killactive" in cmd:
|
||
return "Closes active window"
|
||
if "exec" in cmd:
|
||
# handle known variables
|
||
cmd = cmd.replace("$fileManager", "Filemanager").replace("$menu", "Menu").replace("$terminal","Terminal")
|
||
# remove leading "exec "
|
||
if cmd.startswith("exec "):
|
||
cmd_body = cmd[5:]
|
||
else:
|
||
cmd_body = cmd
|
||
# Special case for screenshot script
|
||
if "~/.scripts/screenshot.sh" in cmd_body:
|
||
return "Takes screenshot"
|
||
if "~/.scripts/hypr-help.sh" in cmd_body:
|
||
return "Shows this help menu"
|
||
return f"Runs {cmd_body}"
|
||
if "togglefloating" in cmd:
|
||
return "Toggles floating for window"
|
||
if "fullscreen" in cmd:
|
||
return "Toggles fullscreen"
|
||
if "pseudo" in cmd:
|
||
return "Pseudotiles window (dwindle)"
|
||
if "togglesplit" in cmd:
|
||
return "Toggles split (dwindle)"
|
||
if "focusmonitor" in cmd:
|
||
return "Changes focused monitor"
|
||
if "split-changemonitor" in cmd:
|
||
return "Moves window to next monitor"
|
||
if "togglespecialworkspace" in cmd:
|
||
return f"Toggles special workspace {parts[-1]}"
|
||
if "movetoworkspace" in cmd:
|
||
return f"Moves window to {parts[-1]}"
|
||
if "split-cycleworkspacesnowrap" in cmd:
|
||
return f"Cycles workspace {parts[-1]}"
|
||
if "movewindow" in cmd:
|
||
return "Move window with mouse"
|
||
if "resizewindow" in cmd:
|
||
return "Resize window with mouse"
|
||
# fallback
|
||
return cmd
|
||
|
||
# 3️⃣ Resolve variables in combos and rename mouse keys
|
||
def resolve_combo(combo):
|
||
combo = combo.replace("$mainMod", variables.get("$mainMod",""))
|
||
combo = combo.replace("#"," + ") # ALT#SUPER -> ALT + SUPER
|
||
# Mouse key mapping
|
||
mouse_map = {
|
||
"mouse:272": "Mouse (left click)",
|
||
"mouse:273": "Mouse (right click)",
|
||
"mouse_down": "Mouse (scroll down)",
|
||
"mouse_up": "Mouse (scroll up)",
|
||
"Print": "PrintScreen"
|
||
}
|
||
combo = mouse_map.get(combo, combo)
|
||
return combo.strip(" +")
|
||
|
||
# 4️⃣ Format each bind
|
||
formatted = []
|
||
for b in bind_lines:
|
||
parts = [p.strip() for p in b.split(",")]
|
||
if len(parts) < 2:
|
||
continue
|
||
combo = resolve_combo(parts[0])
|
||
key = resolve_combo(parts[1])
|
||
# combine combo + key
|
||
if combo and key:
|
||
combo_text = f"{combo} + {key}"
|
||
elif combo:
|
||
combo_text = combo
|
||
else:
|
||
combo_text = key
|
||
action = command_to_text(parts)
|
||
formatted.append(f"{combo_text} -> {action}")
|
||
|
||
# 5️⃣ Print results
|
||
for line in formatted:
|
||
print(line)
|