151 lines
4.0 KiB
Python
151 lines
4.0 KiB
Python
import os
|
|
import re
|
|
import json
|
|
|
|
HOME = os.path.expanduser("~")
|
|
CONFIG = f"{HOME}/dotfiles/hypr"
|
|
|
|
files = [
|
|
f"{CONFIG}/UserConfigs/UserKeybinds.conf",
|
|
f"{CONFIG}/configs/Keybinds.conf"
|
|
]
|
|
|
|
categories_dict: dict[str, str] = {}
|
|
variables_dict: dict[str, str] = {}
|
|
|
|
category_pattern = r"\n#! @(\w+): (.+)"
|
|
variable_pattern = r"\n\$(\w+)\s*=\s*(.*)"
|
|
text = ""
|
|
bindings: dict[str, dict[str, str]] = {}
|
|
|
|
|
|
def extract_category_and_description(
|
|
line: str
|
|
) -> tuple[str | None, str | None, tuple | None]:
|
|
pattern2 = r'bind\s*=\s*.*! @description:\s*"((?:[^"]|\\")*)"\s*;\s*@(\w+);\s*@replace\s*"([^"]*)"\s*>\s*"([^"]*)";.*' # noqa
|
|
pattern = r'bind\s*=\s*.*! @description:\s*"((?:[^"]|\\")*)"\s*;\s*@(\w+);.*' # noqa
|
|
|
|
match = re.search(pattern, line)
|
|
match2 = re.search(pattern2, line)
|
|
if match2:
|
|
description = match2.group(1).strip().replace('\\"', '"')
|
|
replace_from = match2.group(3).strip().lower()
|
|
replace_to = match2.group(4).strip().lower()
|
|
category = match2.group(2).strip()
|
|
|
|
if category not in categories_dict:
|
|
return None, None, None
|
|
|
|
return description, category, (replace_from, replace_to)
|
|
elif match:
|
|
description = match.group(1).strip().replace('\\"', '"')
|
|
category = match.group(2).strip()
|
|
|
|
if category not in categories_dict:
|
|
return None, None, None
|
|
|
|
return description, category, None
|
|
else:
|
|
return None, None, None
|
|
|
|
|
|
def extract_binding(line: str):
|
|
line = line.replace(" =", "=")
|
|
if not line.startswith("bind="):
|
|
return
|
|
line = line.lstrip("bind=").strip().lower().replace("super_l", "")
|
|
_bindings = line.split(",")
|
|
bindings = ' '.join([_bindings[0].strip(), _bindings[1].strip()])
|
|
return bindings
|
|
|
|
|
|
def replace_variable(match: re.Match[str]):
|
|
var_name = match.group(1)
|
|
return variables_dict.get(var_name, match.group(0))
|
|
|
|
|
|
def load_categories(content: str):
|
|
matches = re.findall(category_pattern, content)
|
|
|
|
for key, value in matches:
|
|
categories_dict[key] = value
|
|
bindings[value] = {}
|
|
return content
|
|
|
|
|
|
def load_sources(file: str):
|
|
with open(file) as f:
|
|
content = f.read()
|
|
for line in content.split("\n"):
|
|
line = line.replace(" = ", "=")
|
|
if not line.startswith("source="):
|
|
continue
|
|
file = os.path.expanduser(line.replace("source=", ""))
|
|
if file not in files:
|
|
files.append(file)
|
|
|
|
|
|
def load_variables(content: str):
|
|
matches = re.findall(variable_pattern, content)
|
|
|
|
for var_name, var_value in matches:
|
|
variables_dict[var_name] = var_value
|
|
|
|
content_lines = content.split("\n")
|
|
content_lines = [
|
|
line for line in content_lines if not line.startswith("$")
|
|
]
|
|
content = "\n".join(content_lines)
|
|
return content
|
|
|
|
|
|
def load_file(file: str):
|
|
global text
|
|
with open(file) as f:
|
|
content = f.read()
|
|
|
|
content = load_categories(content)
|
|
content = load_variables(content)
|
|
|
|
# remove comments
|
|
content = re.sub(r'^#.*$\n', '', content, flags=re.MULTILINE)
|
|
text += f"\n{content}"
|
|
|
|
|
|
def load():
|
|
global text, bindings
|
|
text = re.sub(r"\$(\w+)", replace_variable, text)
|
|
for line in text.split('\n'):
|
|
if not line.replace(" ", "").startswith("bind="):
|
|
continue
|
|
|
|
description, category, replace = extract_category_and_description(line)
|
|
if category is None or description is None:
|
|
continue
|
|
|
|
binding = extract_binding(line)
|
|
if binding is None:
|
|
continue
|
|
|
|
category_name = categories_dict[category]
|
|
if category_name not in bindings:
|
|
bindings[category_name] = {}
|
|
|
|
if replace is not None:
|
|
binding = binding.replace(*replace)
|
|
|
|
bindings[category_name][binding.strip()] = description.strip()
|
|
|
|
|
|
while True:
|
|
old_list = files
|
|
for file in files:
|
|
load_sources(file)
|
|
if old_list == files:
|
|
break
|
|
|
|
for file in files:
|
|
load_file(file)
|
|
load()
|
|
print(json.dumps(bindings, indent=4))
|