generate_km.py (7581B)
1 #!/usr/bin/env python3 2 # -*- coding: utf-8 -*- 3 4 import json 5 import layout 6 import os 7 import re 8 9 10 def gen_uc_iter(): 11 length = len(layout.uc_dict) 12 for key, value in sorted(layout.uc_dict.items()): 13 length -= 1 14 if length: 15 yield (key, value, False) 16 else: 17 yield (key, value, True) 18 19 20 def _translate(s): 21 if re.match("^[0-9]$", s): 22 return ("KC_{0}".format(s), " {0} ".format(s)) 23 elif re.match("^[a-z]$", s): 24 return ("KC_{0}".format(s.upper()), " {0} ".format(s)) 25 elif re.match("^[A-Z]$", s): 26 return ("S(KC_{0})".format(s), " {0} ".format(s)) 27 elif re.match("^F[0-9]{1,2}$", s): # Fn, works from F0 to F99 28 return ("KC_{0}".format(s), "{0:^7}".format(s)) 29 elif re.match("^DF[0-9]{1,2}$", s): # DFn, works from DF0 to DF99 30 return ("DF({0})".format(s[2:]), "{0:^7}".format(s)) 31 elif re.match("^MO[0-9]{1,2}$", s): # MOn, works from MO0 to MO99 32 return ("MO({0})".format(s[2:]), "{0:^7}".format(s)) 33 elif re.match("^OSL[0-9]{1,2}$", s): # OSLn, works from OSL0 to OSL99 34 return ("OSL({0})".format(s[3:]), "{0:^7}".format(s)) 35 elif re.match("^TG[0-9]{1,2}$", s): # TGn, works from TG0 to TG99 36 return ("TG({0})".format(s[2:]), "{0:^7}".format(s)) 37 elif re.match("^TO[0-9]{1,2}$", s): # Tn, works from TO0 to TO99 38 return ("TO({0})".format(s[2:]), "{0:^7}".format(s)) 39 elif re.match("^TT[0-9]{1,2}$", s): # Tn, works from TT0 to TT99 40 return ("TT({0})".format(s[2:]), "{0:^7}".format(s)) 41 elif s in layout.uc_dict: 42 return ("UM("+s+")", " {0} ".format(chr(int(layout.uc_dict[s], 0)))) 43 elif s in layout.qmk_dict: 44 return (layout.qmk_dict[s], "{0:^7}".format(s)) 45 elif s == s.upper() and s.startswith("KC_"): 46 return (s, "{0:^7}".format(s[2:])) 47 else: 48 return ("XXXXXXX", " {0} ".format(chr(128165))) 49 50 51 def toKC(s): 52 return _translate(s)[0] 53 54 55 def toLgd(s): 56 return _translate(s)[1] 57 58 59 def quoteC(text): 60 yield "/*" 61 for line in text: 62 yield " * " + line 63 yield " */\n" 64 65 66 def getKeymapText(id, layer, columns, rows): 67 keymap = [] 68 keymap.append("Layer %d" % id) 69 keymap.append("------------------------------------------------- -------------------------------------------------") 70 keymap.append("|{0}|{1}|{2}|{3}|{4}|{5}| |{6}|{7}|{8}|{9}|{10}|{11}|".format(*map(toLgd, layer[:12]))) 71 keymap.append("------------------------------------------------- -------------------------------------------------") 72 keymap.append("|{0}|{1}|{2}|{3}|{4}|{5}| |{6}|{7}|{8}|{9}|{10}|{11}|".format(*map(toLgd, layer[12:24]))) 73 keymap.append("------------------------------------------------- -------------------------------------------------") 74 keymap.append("|{0}|{1}|{2}|{3}|{4}|{5}| |{6}|{7}|{8}|{9}|{10}|{11}|".format(*map(toLgd, layer[24:36]))) 75 keymap.append("-----------------------------------------------------------------------------------------------------------------") 76 keymap.append(" {0} {1} {2} |{3}|{4}|{5}|{6}|{7}|{8}| {9} {10} {11}".format(*map(toLgd, layer[36:48])).rstrip()) 77 keymap.append(" -------------------------------------------------") 78 return keymap 79 80 81 def writeKeymap(f_template, f_keymap, layers, columns, rows): 82 doCopy = False 83 84 for line in f_template: 85 doCopy = True 86 if line.startswith("//<enum/>"): 87 doCopy = False 88 # f_keymap.write(str(layout.uc_dict)) 89 for k, v, isLast in gen_uc_iter(): 90 if isLast: 91 f_keymap.write(k + "\n") 92 else: 93 f_keymap.write(k + ",\n") 94 elif line.startswith("//<uc_map/>"): 95 doCopy = False 96 for k, v, isLast in gen_uc_iter(): 97 if isLast: 98 f_keymap.write(u"\t[{0}] = {1} // {2}\n".format(k, v, chr(int(v, 0)))) 99 else: 100 f_keymap.write(u"\t[{0}] = {1}, // {2}\n".format(k, v, chr(int(v, 0)))) 101 elif line.startswith("//<keymaps/>"): 102 doCopy = False 103 for layer, L in enumerate(layers): 104 r_counter = rows 105 f_keymap.write('\n'.join(quoteC(getKeymapText(layer, L, columns, rows)))) 106 107 l_code = '\tLAYOUT_ortho_4x12(\n' 108 for r in range(r_counter): 109 r_counter -= 1 110 c_counter = columns 111 l_code += '\t\t' 112 for c in range(c_counter): 113 c_counter -= 1 114 if c != 0: 115 l_code += " " 116 l_code += "%s" % toKC(L[r*columns + columns-c_counter-1]) 117 if r_counter or c_counter: 118 l_code += "," 119 l_code += '\n' 120 if layer + 1 != len(layout.layers): 121 l_code += "\t),\n\n" 122 else: 123 l_code += "\t)\n" 124 f_keymap.write(l_code) 125 if doCopy: 126 f_keymap.write(line) 127 128 129 def getKeymapJSON(keyboard, keymap, layout, layers): 130 return json.dumps({ 131 'keyboard': keyboard, 132 'keymap': keymap, 133 'layout': layout, 134 'layers': layers 135 }, sort_keys=True, indent=4) 136 137 138 def getKeymapAsciidoc(title, layers, columns, rows): 139 yield '= ' + title 140 yield '' 141 for id, layer in enumerate(layers): 142 keymap = getKeymapText(id, layer, columns, rows) 143 if len(keymap): 144 yield '.' + keymap[0] 145 yield '--------------------------' 146 for line in keymap[1:]: 147 yield ' ' + line 148 yield '--------------------------' 149 yield '' 150 151 152 def layersToKC(layers): 153 return [list(map(toKC, layer)) for layer in layers] 154 155 156 def pathToKeymap(path): 157 head, keymap = os.path.split(path) 158 _, keymapsdir = os.path.split(head) 159 if keymapsdir == 'keymaps': 160 return keymap 161 162 163 def pathToKeyboard(path): 164 head, keymap = os.path.split(path) 165 head, keymapsdir = os.path.split(head) 166 if keymapsdir == 'keymaps': 167 head, dir = os.path.split(head) 168 while dir not in ('/', 'keyboards'): 169 yield dir 170 head, dir = os.path.split(head) 171 172 173 if __name__ == "__main__": 174 with open("km_template.txt", mode="r") as f_template: 175 with open("keymap.c", mode="w", encoding='utf-8') as f_keymap: 176 writeKeymap(f_template, f_keymap, layout.layers, columns=12, rows=4) 177 178 abspath = os.path.dirname(os.path.abspath(__file__)) 179 keyboard = list(reversed(list(pathToKeyboard(abspath)))) 180 keymap = pathToKeymap(abspath) 181 keyboard_layout = 'LAYOUT_ortho_4x12' 182 with open("%s_%s.json" % ('_'.join(keyboard), keymap), mode="w") as f_keymapjson: 183 f_keymapjson.write( 184 getKeymapJSON( 185 '/'.join(keyboard), 186 keymap, 187 keyboard_layout, 188 layersToKC(layout.layers)) 189 ) 190 191 with open("keymap.adoc", mode="w") as f_keymapasciidoc: 192 f_keymapasciidoc.write('\n'.join(getKeymapAsciidoc('Signum 3.0 %s_%s' % ('_'.join(keyboard), keymap), layout.layers, columns=12, rows=4))) 193 print("Run the following command to generate a PDF from the keymap") 194 print("a2x -f pdf --xsltproc-opts '--stringparam page.orientation landscape --stringparam body.font.master 12' --fop -v keymap.adoc")