from typing import Set import sys import kb import kc import mac_parser IN_PATH = sys.argv[1] OUT_PATH = sys.argv[2] mac_kb = mac_parser.parse_keyboard_layout(IN_PATH) keyboard = kb.from_mac(mac_kb) with open(OUT_PATH, "w") as out_file: out_file.write("xkb_keymap {\n") out_file.write(' xkb_keycodes "mjaucodes"{\n') for knr, name in kc.MAC_KEY_NAMES.items(): key = kc.KeyCode(knr) for lin_n, lin_name in key.linux_keycodes(): out_file.write(f' {lin_name} = {lin_n}; // {key}\n') out_file.write(' = 22; // Backspace\n') out_file.write(' = 50; // Left shift\n') out_file.write(' = 62; // Right alt\n') out_file.write(' = 64; // Left alt\n') out_file.write(' = 108; // Right alt\n') out_file.write(' = 9; // Escape\n') out_file.write(' = 23; // Tab\n') out_file.write(' = 36; // Return\n') out_file.write(' = 37; // Left Control\n') out_file.write(' = 105; // Right Control\n') out_file.write(' = 111; // Arrow up\n') out_file.write(' = 116; // Arrow down\n') out_file.write(' = 113; // Arrow left\n') out_file.write(' = 114; // Arrow right\n') out_file.write(' = 66; // Caps lock\n') out_file.write(' };\n') out_file.write('''\ xkb_types "mjautypes" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; type "ONE_LEVEL" { modifiers= none; level_name[Level1]= "Any"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= Level2; map[Lock]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Caps"; }; type "ALTABLE" { modifiers= Shift+Mod2; map[Shift]= Level2; map[Mod2]= Level3; map[Shift+Mod2]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; }; xkb_compatibility "mjaucomp" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret.locking= False; interpret LSHF+AnyOfOrNone(all) { action= SetMods(modifiers=Shift,clearLocks); }; interpret LSHF+AnyOfOrNone(all) { action= SetMods(modifiers=Shift,clearLocks); }; interpret LALT+AnyOf(all) { action= SetMods(modifiers=Mod2,clearLocks); }; interpret RALT+AnyOf(all) { action= SetMods(modifiers=modMapMode,clearLocks); }; }; ''') out_file.write('''\ xkb_symbols "mjau"{ key { [ Alt_L ] }; key { [ Alt_R ] }; key { [ Shift_L ] }; key { [ Shift_R ] }; key { [ Control_L ] }; key { [ Control_R ] }; key { [ BackSpace ] }; key { [ Tab ] }; key { [ Escape ] }; key { [ Escape ] }; key { [ Return ] }; key { [ Up ] }; key { [ Down ] }; key { [ Left ] }; key { [ Right ] }; modifier_map Control { }; modifier_map Control { }; modifier_map Mod1 { }; modifier_map Mod2 { }; ''') def get_output(layer: kb.Layer, kc: kb.KeyCode, mods: Set[kb.Modifier]) -> str: key = kb.Key(kc, mods) if key not in layer.buttons: return "none" press = layer.buttons[key] if not isinstance(press, kb.Output): return "none" if len(press.output) != 1: print(f"Ignoring multi-output key {kc}+{mods}") return "none" return "U" + hex(ord(press.output[0]))[2:].rjust(4, "0") layer = keyboard.layers[keyboard.default_layer] for keycode in kc.KEYCODES: none = get_output(layer, keycode, set()) shifted = get_output(layer, keycode, set([kb.Modifier.SHIFT])) alted = get_output(layer, keycode, set([kb.Modifier.OPTION])) shalted = get_output(layer, keycode, set([kb.Modifier.SHIFT, kb.Modifier.OPTION])) if none == shifted == alted == shalted == "none": continue for _, lin_name in keycode.linux_keycodes(): out_file.write(f' key {lin_name} {{ type = "ALTABLE", symbols[Group1]= [ {none}, {shifted}, {alted}, {shalted} ] }}; // {keycode}\n') out_file.write(' };\n') out_file.write(' xkb_geometry "mjauometry" {};\n') out_file.write("};\n") print("Wrote to", OUT_PATH)