aboutsummaryrefslogtreecommitdiff
path: root/lib/python/qmk/keymap.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python/qmk/keymap.py')
-rw-r--r--lib/python/qmk/keymap.py75
1 files changed, 61 insertions, 14 deletions
diff --git a/lib/python/qmk/keymap.py b/lib/python/qmk/keymap.py
index 69cdc8d5b..70730eb4a 100644
--- a/lib/python/qmk/keymap.py
+++ b/lib/python/qmk/keymap.py
@@ -2,8 +2,8 @@
2""" 2"""
3from pathlib import Path 3from pathlib import Path
4 4
5import qmk.path 5from qmk.path import is_keyboard
6import qmk.makefile 6from qmk.keyboard import rules_mk
7 7
8# The `keymap.c` template to use when a keyboard doesn't have its own 8# The `keymap.c` template to use when a keyboard doesn't have its own
9DEFAULT_KEYMAP_C = """#include QMK_KEYBOARD_H 9DEFAULT_KEYMAP_C = """#include QMK_KEYBOARD_H
@@ -47,6 +47,14 @@ def _strip_any(keycode):
47 return keycode 47 return keycode
48 48
49 49
50def is_keymap_dir(keymap):
51 """Return True if Path object `keymap` has a keymap file inside.
52 """
53 for file in ('keymap.c', 'keymap.json'):
54 if (keymap / file).is_file():
55 return True
56
57
50def generate(keyboard, layout, layers): 58def generate(keyboard, layout, layers):
51 """Returns a keymap.c for the specified keyboard, layout, and layers. 59 """Returns a keymap.c for the specified keyboard, layout, and layers.
52 60
@@ -95,7 +103,7 @@ def write(keyboard, keymap, layout, layers):
95 An array of arrays describing the keymap. Each item in the inner array should be a string that is a valid QMK keycode. 103 An array of arrays describing the keymap. Each item in the inner array should be a string that is a valid QMK keycode.
96 """ 104 """
97 keymap_c = generate(keyboard, layout, layers) 105 keymap_c = generate(keyboard, layout, layers)
98 keymap_file = qmk.path.keymap(keyboard) / keymap / 'keymap.c' 106 keymap_file = keymap(keyboard) / keymap / 'keymap.c'
99 107
100 keymap_file.parent.mkdir(parents=True, exist_ok=True) 108 keymap_file.parent.mkdir(parents=True, exist_ok=True)
101 keymap_file.write_text(keymap_c) 109 keymap_file.write_text(keymap_c)
@@ -103,37 +111,76 @@ def write(keyboard, keymap, layout, layers):
103 return keymap_file 111 return keymap_file
104 112
105 113
106def list_keymaps(keyboard_name): 114def locate_keymap(keyboard, keymap):
115 """Returns the path to a keymap for a specific keyboard.
116 """
117 if not is_keyboard(keyboard):
118 raise KeyError('Invalid keyboard: ' + repr(keyboard))
119
120 # Check the keyboard folder first, last match wins
121 checked_dirs = ''
122 keymap_path = ''
123
124 for dir in keyboard.split('/'):
125 if checked_dirs:
126 checked_dirs = '/'.join((checked_dirs, dir))
127 else:
128 checked_dirs = dir
129
130 keymap_dir = Path('keyboards') / checked_dirs / 'keymaps'
131
132 if (keymap_dir / keymap / 'keymap.c').exists():
133 keymap_path = keymap_dir / keymap / 'keymap.c'
134 if (keymap_dir / keymap / 'keymap.json').exists():
135 keymap_path = keymap_dir / keymap / 'keymap.json'
136
137 if keymap_path:
138 return keymap_path
139
140 # Check community layouts as a fallback
141 rules = rules_mk(keyboard)
142
143 if "LAYOUTS" in rules:
144 for layout in rules["LAYOUTS"].split():
145 community_layout = Path('layouts/community') / layout / keymap
146 if community_layout.exists():
147 if (community_layout / 'keymap.json').exists():
148 return community_layout / 'keymap.json'
149 if (community_layout / 'keymap.c').exists():
150 return community_layout / 'keymap.c'
151
152
153def list_keymaps(keyboard):
107 """ List the available keymaps for a keyboard. 154 """ List the available keymaps for a keyboard.
108 155
109 Args: 156 Args:
110 keyboard_name: the keyboards full name with vendor and revision if necessary, example: clueboard/66/rev3 157 keyboard: the keyboards full name with vendor and revision if necessary, example: clueboard/66/rev3
111 158
112 Returns: 159 Returns:
113 a set with the names of the available keymaps 160 a set with the names of the available keymaps
114 """ 161 """
115 # parse all the rules.mk files for the keyboard 162 # parse all the rules.mk files for the keyboard
116 rules_mk = qmk.makefile.get_rules_mk(keyboard_name) 163 rules = rules_mk(keyboard)
117 names = set() 164 names = set()
118 165
119 if rules_mk: 166 if rules:
120 # qmk_firmware/keyboards 167 # qmk_firmware/keyboards
121 keyboards_dir = Path.cwd() / "keyboards" 168 keyboards_dir = Path('keyboards')
122 # path to the keyboard's directory 169 # path to the keyboard's directory
123 kb_path = keyboards_dir / keyboard_name 170 kb_path = keyboards_dir / keyboard
124 # walk up the directory tree until keyboards_dir 171 # walk up the directory tree until keyboards_dir
125 # and collect all directories' name with keymap.c file in it 172 # and collect all directories' name with keymap.c file in it
126 while kb_path != keyboards_dir: 173 while kb_path != keyboards_dir:
127 keymaps_dir = kb_path / "keymaps" 174 keymaps_dir = kb_path / "keymaps"
128 if keymaps_dir.exists(): 175 if keymaps_dir.exists():
129 names = names.union([keymap for keymap in keymaps_dir.iterdir() if (keymaps_dir / keymap / "keymap.c").is_file()]) 176 names = names.union([keymap.name for keymap in keymaps_dir.iterdir() if is_keymap_dir(keymap)])
130 kb_path = kb_path.parent 177 kb_path = kb_path.parent
131 178
132 # if community layouts are supported, get them 179 # if community layouts are supported, get them
133 if "LAYOUTS" in rules_mk: 180 if "LAYOUTS" in rules:
134 for layout in rules_mk["LAYOUTS"].split(): 181 for layout in rules["LAYOUTS"].split():
135 cl_path = Path.cwd() / "layouts" / "community" / layout 182 cl_path = Path('layouts/community') / layout
136 if cl_path.exists(): 183 if cl_path.exists():
137 names = names.union([keymap for keymap in cl_path.iterdir() if (cl_path / keymap / "keymap.c").is_file()]) 184 names = names.union([keymap.name for keymap in cl_path.iterdir() if is_keymap_dir(keymap)])
138 185
139 return sorted(names) 186 return sorted(names)