#!/usr/bin/env python3 import sys import re KEY_TRANSLATIONS = { "Print": "PrintScreen", "mouse_up": "Mouse Up", "mouse_down": "Mouse Down", "mouse:272": "Left Click", "mouse:273": "Right Click", "left": "Left Arrow", "right": "Right Arrow", "up": "Up Arrow", "down": "Down Arrow", } def normalize_key_name(key: str) -> str: key = key.strip() return KEY_TRANSLATIONS.get(key, key) def extract_main_mod(lines): """ Extracts $mainMod value, e.g. $mainMod = SUPER """ pattern = re.compile(r"^\s*\$mainMod\s*=\s*([A-Za-z0-9_]+)") for line in lines: match = pattern.match(line) if match: return match.group(1) return None def normalize_key(mods: str, key: str, main_mod_value: str) -> str: mods = mods.strip() key = normalize_key_name(key.strip()) if mods: mod_parts = mods.split() resolved_mods = [] for m in mod_parts: if m == "$mainMod" and main_mod_value: resolved_mods.append(main_mod_value) else: resolved_mods.append(m) return " + ".join(resolved_mods) + f" + {key}" return key def parse_hyprland_config(path: str): with open(path, "r", encoding="utf-8") as f: lines = f.readlines() main_mod_value = extract_main_mod(lines) results = [] last_comment = None bind_pattern = re.compile(r"^\s*(bindm?|bind)\s*=\s*(.+)$") for line in lines: stripped = line.strip() if stripped.startswith("#"): last_comment = stripped.lstrip("#").strip() continue match = bind_pattern.match(line) if match: full_cmd = match.group(2) parts = [p.strip() for p in full_cmd.split(",")] if len(parts) >= 2: mods = parts[0] key = parts[1] keybind = normalize_key(mods, key, main_mod_value) comment = last_comment if last_comment else "(no comment)" results.append(f"{keybind} = {comment}") last_comment = None else: if stripped != "": last_comment = None return results def main(): if len(sys.argv) != 2: print(f"Usage: {sys.argv[0]} ") sys.exit(1) config_path = sys.argv[1] keybinds = parse_hyprland_config(config_path) for line in keybinds: print(line) if __name__ == "__main__": main()