Created
August 21, 2023 10:40
-
-
Save haji-ali/b80489baf53fb33e75d2f8dd6d43fd9f to your computer and use it in GitHub Desktop.
A script to convert a short karabiner YAML config to JSON one
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import yaml | |
import json | |
import re | |
import sys | |
def transform_key(key, is_from=True): | |
mod_map = {"M":"option", "C":"control", "S":"command", "F":"fn"} | |
m = re.match(r"^((?:(?:C|F|S|M)-)*)(.*)", key) | |
mod, key = [m.group(i) for i in range(1, 3)] | |
mod = [mod_map[c] for c in mod.split("-") if len(c)>0] | |
if key.isupper(): | |
mod += ["left_shift"] | |
key = key.lower() | |
if len(mod)>0: | |
return {"key_code" : key, | |
"modifiers" : {"mandatory": mod} if is_from else mod} | |
return {"key_code" : key} | |
def transform_manip(manip): | |
m = re.match(r"(.*)\s=>\s(.*)", manip) | |
m_from, m_to = [m.group(i) for i in range(1, 3)] | |
return {"from": transform_key(m_from), | |
"to": [transform_key(m_to, False)]} | |
def transform_all(d): | |
if isinstance(d, list): | |
for vv in d: | |
transform_all(vv) | |
elif isinstance(d, dict): | |
for k,v in d.items(): | |
if k in ("manipulators", "simple_modifications", "fn_function_keys"): | |
for i, manip in enumerate(v): | |
if isinstance(manip, str): | |
v[i] = transform_manip(manip) | |
else: | |
transform_all(v[i]) | |
if k in ("manipulators") and "type" not in v[i]: | |
v[i]["type"] = "basic" | |
elif k in ("from") and isinstance(v, str): | |
d[k] = transform_key(v) | |
elif k in ("to") and isinstance(v, str): | |
d[k] = transform_key(v, False) | |
else: | |
transform_all(v) | |
def parse_subrule(conditions_dict, rule): | |
conds = None | |
if "conditions" in rule: | |
conds = [conditions_dict[c] for c in rule.pop("conditions")] | |
if "manipulators" in rule: | |
manips = rule["manipulators"] | |
for i in range(len(manips)): | |
if conds is not None: | |
manips[i]["conditions"] = conds | |
return manips | |
return [] | |
def main(input_yaml): | |
with open(input_yaml, 'r') as stream: | |
try: | |
K_config = yaml.safe_load(stream) | |
except yaml.YAMLError as exc: | |
print(exc) | |
raise | |
transform_all(K_config) | |
conditions_dict = K_config["profiles"][0]["complex_modifications"].pop("conditions_dict") | |
rules = K_config["profiles"][0]["complex_modifications"]["rules"] | |
for rule in rules: | |
manips = parse_subrule(conditions_dict, rule) | |
if "sub-rules" in rule: | |
for sr in rule.pop("sub-rules"): | |
manips += parse_subrule(conditions_dict, sr) | |
rule["manipulators"] = manips | |
json.dump(K_config, sys.stdout, indent=2) | |
if __name__ == "__main__": | |
if len(sys.argv) < 2: | |
print("USAGE: karabiner-yaml YAML-FILE") | |
else: | |
main(sys.argv[1]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment