]> git.donarmstrong.com Git - qmk_firmware.git/blob - lib/python/qmk/keymap.py
QMK CLI and JSON keymap support (#6176)
[qmk_firmware.git] / lib / python / qmk / keymap.py
1 """Functions that help you work with QMK keymaps.
2 """
3 import json
4 import logging
5 import os
6 from traceback import format_exc
7
8 import qmk.path
9 from qmk.errors import NoSuchKeyboardError
10
11 # The `keymap.c` template to use when a keyboard doesn't have its own
12 DEFAULT_KEYMAP_C = """#include QMK_KEYBOARD_H
13
14 /* THIS FILE WAS GENERATED!
15  *
16  * This file was generated by qmk-compile-json. You may or may not want to
17  * edit it directly.
18  */
19
20 const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
21 __KEYMAP_GOES_HERE__
22 };
23 """
24
25
26 def template(keyboard):
27     """Returns the `keymap.c` template for a keyboard.
28
29     If a template exists in `keyboards/<keyboard>/templates/keymap.c` that
30     text will be used instead of `DEFAULT_KEYMAP_C`.
31
32     Args:
33         keyboard
34             The keyboard to return a template for.
35     """
36     template_name = 'keyboards/%s/templates/keymap.c' % keyboard
37
38     if os.path.exists(template_name):
39         with open(template_name, 'r') as fd:
40             return fd.read()
41
42     return DEFAULT_KEYMAP_C
43
44
45 def generate(keyboard, layout, layers):
46     """Returns a keymap.c for the specified keyboard, layout, and layers.
47
48     Args:
49         keyboard
50             The name of the keyboard
51
52         layout
53             The LAYOUT macro this keymap uses.
54
55         layers
56             An array of arrays describing the keymap. Each item in the inner array should be a string that is a valid QMK keycode.
57     """
58     layer_txt = []
59     for layer_num, layer in enumerate(layers):
60         if layer_num != 0:
61             layer_txt[-1] = layer_txt[-1] + ','
62         layer_keys = ', '.join(layer)
63         layer_txt.append('\t[%s] = %s(%s)' % (layer_num, layout, layer_keys))
64
65     keymap = '\n'.join(layer_txt)
66     keymap_c = template(keyboard, keymap)
67
68     return keymap_c.replace('__KEYMAP_GOES_HERE__', keymap)
69
70
71 def write(keyboard, keymap, layout, layers):
72     """Generate the `keymap.c` and write it to disk.
73
74     Returns the filename written to.
75
76     Args:
77         keyboard
78             The name of the keyboard
79
80         keymap
81             The name of the keymap
82
83         layout
84             The LAYOUT macro this keymap uses.
85
86         layers
87             An array of arrays describing the keymap. Each item in the inner array should be a string that is a valid QMK keycode.
88     """
89     keymap_c = generate(keyboard, layout, layers)
90     keymap_path = qmk.path.keymap(keyboard)
91     keymap_dir = os.path.join(keymap_path, keymap)
92     keymap_file = os.path.join(keymap_dir, 'keymap.c')
93
94     if not os.path.exists(keymap_dir):
95         os.makedirs(keymap_dir)
96
97     with open(keymap_file, 'w') as keymap_fd:
98         keymap_fd.write(keymap_c)
99
100     return keymap_file