diff options
Diffstat (limited to 'lib/python/qmk/keymap.py')
-rw-r--r-- | lib/python/qmk/keymap.py | 137 |
1 files changed, 88 insertions, 49 deletions
diff --git a/lib/python/qmk/keymap.py b/lib/python/qmk/keymap.py index 11e8d39dad..b7bf897377 100644 --- a/lib/python/qmk/keymap.py +++ b/lib/python/qmk/keymap.py @@ -12,7 +12,8 @@ from pygments.token import Token from pygments import lex import qmk.path -from qmk.keyboard import find_keyboard_from_dir, keyboard_folder +from qmk.constants import QMK_FIRMWARE, QMK_USERSPACE, HAS_QMK_USERSPACE +from qmk.keyboard import find_keyboard_from_dir, keyboard_folder, keyboard_aliases from qmk.errors import CppError from qmk.info import info_json @@ -191,33 +192,41 @@ def _strip_any(keycode): return keycode -def find_keymap_from_dir(): - """Returns `(keymap_name, source)` for the directory we're currently in. - +def find_keymap_from_dir(*args): + """Returns `(keymap_name, source)` for the directory provided (or cwd if not specified). """ - relative_cwd = qmk.path.under_qmk_firmware() + def _impl_find_keymap_from_dir(relative_path): + if relative_path and len(relative_path.parts) > 1: + # If we're in `qmk_firmware/keyboards` and `keymaps` is in our path, try to find the keyboard name. + if relative_path.parts[0] == 'keyboards' and 'keymaps' in relative_path.parts: + current_path = Path('/'.join(relative_path.parts[1:])) # Strip 'keyboards' from the front + + if 'keymaps' in current_path.parts and current_path.name != 'keymaps': + while current_path.parent.name != 'keymaps': + current_path = current_path.parent - if relative_cwd and len(relative_cwd.parts) > 1: - # If we're in `qmk_firmware/keyboards` and `keymaps` is in our path, try to find the keyboard name. - if relative_cwd.parts[0] == 'keyboards' and 'keymaps' in relative_cwd.parts: - current_path = Path('/'.join(relative_cwd.parts[1:])) # Strip 'keyboards' from the front + return current_path.name, 'keymap_directory' - if 'keymaps' in current_path.parts and current_path.name != 'keymaps': - while current_path.parent.name != 'keymaps': - current_path = current_path.parent + # If we're in `qmk_firmware/layouts` guess the name from the community keymap they're in + elif relative_path.parts[0] == 'layouts' and is_keymap_dir(relative_path): + return relative_path.name, 'layouts_directory' - return current_path.name, 'keymap_directory' + # If we're in `qmk_firmware/users` guess the name from the userspace they're in + elif relative_path.parts[0] == 'users': + # Guess the keymap name based on which userspace they're in + return relative_path.parts[1], 'users_directory' + return None, None - # If we're in `qmk_firmware/layouts` guess the name from the community keymap they're in - elif relative_cwd.parts[0] == 'layouts' and is_keymap_dir(relative_cwd): - return relative_cwd.name, 'layouts_directory' + if HAS_QMK_USERSPACE: + name, source = _impl_find_keymap_from_dir(qmk.path.under_qmk_userspace(*args)) + if name and source: + return name, source - # If we're in `qmk_firmware/users` guess the name from the userspace they're in - elif relative_cwd.parts[0] == 'users': - # Guess the keymap name based on which userspace they're in - return relative_cwd.parts[1], 'users_directory' + name, source = _impl_find_keymap_from_dir(qmk.path.under_qmk_firmware(*args)) + if name and source: + return name, source - return None, None + return (None, None) def keymap_completer(prefix, action, parser, parsed_args): @@ -418,29 +427,45 @@ def locate_keymap(keyboard, keymap): raise KeyError('Invalid keyboard: ' + repr(keyboard)) # Check the keyboard folder first, last match wins - checked_dirs = '' keymap_path = '' - for dir in keyboard_folder(keyboard).split('/'): - if checked_dirs: - checked_dirs = '/'.join((checked_dirs, dir)) - else: - checked_dirs = dir + search_dirs = [QMK_FIRMWARE] + keyboard_dirs = [keyboard_folder(keyboard)] + if HAS_QMK_USERSPACE: + # When we've got userspace, check there _last_ as we want them to override anything in the main repo. + search_dirs.append(QMK_USERSPACE) + # We also want to search for any aliases as QMK's folder structure may have changed, with an alias, but the user + # hasn't updated their keymap location yet. + keyboard_dirs.extend(keyboard_aliases(keyboard)) + keyboard_dirs = list(set(keyboard_dirs)) + + for search_dir in search_dirs: + for keyboard_dir in keyboard_dirs: + checked_dirs = '' + for dir in keyboard_dir.split('/'): + if checked_dirs: + checked_dirs = '/'.join((checked_dirs, dir)) + else: + checked_dirs = dir - keymap_dir = Path('keyboards') / checked_dirs / 'keymaps' + keymap_dir = Path(search_dir) / Path('keyboards') / checked_dirs / 'keymaps' - if (keymap_dir / keymap / 'keymap.c').exists(): - keymap_path = keymap_dir / keymap / 'keymap.c' - if (keymap_dir / keymap / 'keymap.json').exists(): - keymap_path = keymap_dir / keymap / 'keymap.json' + if (keymap_dir / keymap / 'keymap.c').exists(): + keymap_path = keymap_dir / keymap / 'keymap.c' + if (keymap_dir / keymap / 'keymap.json').exists(): + keymap_path = keymap_dir / keymap / 'keymap.json' - if keymap_path: - return keymap_path + if keymap_path: + return keymap_path # Check community layouts as a fallback info = info_json(keyboard) - for community_parent in Path('layouts').glob('*/'): + community_parents = list(Path('layouts').glob('*/')) + if HAS_QMK_USERSPACE and (Path(QMK_USERSPACE) / "layouts").exists(): + community_parents.append(Path(QMK_USERSPACE) / "layouts") + + for community_parent in community_parents: for layout in info.get("community_layouts", []): community_layout = community_parent / layout / keymap if community_layout.exists(): @@ -450,6 +475,16 @@ def locate_keymap(keyboard, keymap): return community_layout / 'keymap.c' +def is_keymap_target(keyboard, keymap): + if keymap == 'all': + return True + + if locate_keymap(keyboard, keymap): + return True + + return False + + def list_keymaps(keyboard, c=True, json=True, additional_files=None, fullpath=False): """List the available keymaps for a keyboard. @@ -474,26 +509,30 @@ def list_keymaps(keyboard, c=True, json=True, additional_files=None, fullpath=Fa """ names = set() - keyboards_dir = Path('keyboards') - kb_path = keyboards_dir / keyboard - # walk up the directory tree until keyboards_dir # and collect all directories' name with keymap.c file in it - while kb_path != keyboards_dir: - keymaps_dir = kb_path / "keymaps" - - if keymaps_dir.is_dir(): - for keymap in keymaps_dir.iterdir(): - if is_keymap_dir(keymap, c, json, additional_files): - keymap = keymap if fullpath else keymap.name - names.add(keymap) + for search_dir in [QMK_FIRMWARE, QMK_USERSPACE] if HAS_QMK_USERSPACE else [QMK_FIRMWARE]: + keyboards_dir = search_dir / Path('keyboards') + kb_path = keyboards_dir / keyboard + + while kb_path != keyboards_dir: + keymaps_dir = kb_path / "keymaps" + if keymaps_dir.is_dir(): + for keymap in keymaps_dir.iterdir(): + if is_keymap_dir(keymap, c, json, additional_files): + keymap = keymap if fullpath else keymap.name + names.add(keymap) - kb_path = kb_path.parent + kb_path = kb_path.parent # Check community layouts as a fallback info = info_json(keyboard) - for community_parent in Path('layouts').glob('*/'): + community_parents = list(Path('layouts').glob('*/')) + if HAS_QMK_USERSPACE and (Path(QMK_USERSPACE) / "layouts").exists(): + community_parents.append(Path(QMK_USERSPACE) / "layouts") + + for community_parent in community_parents: for layout in info.get("community_layouts", []): cl_path = community_parent / layout if cl_path.is_dir(): @@ -657,7 +696,7 @@ def parse_keymap_c(keymap_file, use_cpp=True): Returns: a dictionary containing the parsed keymap """ - if keymap_file == '-': + if not isinstance(keymap_file, (Path, str)) or keymap_file == '-': if use_cpp: keymap_file = _c_preprocess(None, sys.stdin) else: |