qmk

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.z3bra.org/qmk.git
Log | Files | Refs | Submodules | LICENSE

generate_km.py (7580B)


      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 ("X("+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")