Skip to content

Instantly share code, notes, and snippets.

@haji-ali
Created August 21, 2023 10:40
Show Gist options
  • Save haji-ali/b80489baf53fb33e75d2f8dd6d43fd9f to your computer and use it in GitHub Desktop.
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
#!/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