diff options
| author | Zach White <skullydazed@users.noreply.github.com> | 2020-05-26 13:05:41 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-05-26 13:05:41 -0700 |
| commit | 751316c34465ea77e066c3052729b207f3d62e0c (patch) | |
| tree | cb99656b93c156757e2fd7c84fe716f9c300ca89 /lib/python/qmk/keymap.py | |
| parent | 5d3bf8a050f3c0beb1f91147dc1ab54de36cbb05 (diff) | |
| download | qmk_firmware-751316c34465ea77e066c3052729b207f3d62e0c.tar.gz qmk_firmware-751316c34465ea77e066c3052729b207f3d62e0c.zip | |
[CLI] Add a subcommand for getting information about a keyboard (#8666)
You can now use `qmk info` to get information about keyboards and keymaps.
Co-authored-by: Erovia <Erovia@users.noreply.github.com>
Diffstat (limited to 'lib/python/qmk/keymap.py')
| -rw-r--r-- | lib/python/qmk/keymap.py | 75 |
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 | """ |
| 3 | from pathlib import Path | 3 | from pathlib import Path |
| 4 | 4 | ||
| 5 | import qmk.path | 5 | from qmk.path import is_keyboard |
| 6 | import qmk.makefile | 6 | from 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 |
| 9 | DEFAULT_KEYMAP_C = """#include QMK_KEYBOARD_H | 9 | DEFAULT_KEYMAP_C = """#include QMK_KEYBOARD_H |
| @@ -47,6 +47,14 @@ def _strip_any(keycode): | |||
| 47 | return keycode | 47 | return keycode |
| 48 | 48 | ||
| 49 | 49 | ||
| 50 | def 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 | |||
| 50 | def generate(keyboard, layout, layers): | 58 | def 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 | ||
| 106 | def list_keymaps(keyboard_name): | 114 | def 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 | |||
| 153 | def 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) |
