summaryrefslogtreecommitdiff
path: root/lib/python
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python')
-rw-r--r--lib/python/qmk/cli/c2json.py59
-rwxr-xr-xlib/python/qmk/cli/generate/config_h.py59
-rwxr-xr-xlib/python/qmk/cli/generate/keyboard_c.py27
-rw-r--r--lib/python/qmk/cli/generate/keycodes.py8
-rwxr-xr-xlib/python/qmk/cli/generate/rules_mk.py26
-rw-r--r--lib/python/qmk/info.py68
-rw-r--r--lib/python/qmk/keymap.py23
-rw-r--r--lib/python/qmk/path.py6
8 files changed, 150 insertions, 126 deletions
diff --git a/lib/python/qmk/cli/c2json.py b/lib/python/qmk/cli/c2json.py
index 7f6aca070a..f7f1f2ffba 100644
--- a/lib/python/qmk/cli/c2json.py
+++ b/lib/python/qmk/cli/c2json.py
@@ -1,45 +1,57 @@
"""Generate a keymap.json from a keymap.c file.
"""
+import re
import json
from argcomplete.completers import FilesCompleter
from milc import cli
-import qmk.keymap
import qmk.path
from qmk.json_encoders import InfoJSONEncoder
+from qmk.decorators import automagic_keyboard, automagic_keymap
from qmk.keyboard import keyboard_completer, keyboard_folder
+from qmk.keymap import locate_keymap, find_keymap_from_dir, generate_json, c2json as c2json_impl
from qmk.errors import CppError
+from qmk.commands import dump_lines
@cli.argument('--no-cpp', arg_only=True, action='store_false', help='Do not use \'cpp\' on keymap.c')
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
-@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, required=True, help='The keyboard\'s name')
-@cli.argument('-km', '--keymap', arg_only=True, required=True, help='The keymap\'s name')
-@cli.argument('filename', arg_only=True, completer=FilesCompleter('.c'), help='keymap.c file')
+@cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='The keyboard\'s name')
+@cli.argument('-km', '--keymap', help='The keymap\'s name')
+@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.c'), help='keymap.c file')
@cli.subcommand('Creates a keymap.json from a keymap.c file.')
+@automagic_keyboard
+@automagic_keymap
def c2json(cli):
"""Generate a keymap.json from a keymap.c file.
This command uses the `qmk.keymap` module to generate a keymap.json from a keymap.c file. The generated keymap is written to stdout, or to a file if -o is provided.
"""
- if cli.args.filename != '-':
- cli.args.filename = qmk.path.normpath(cli.args.filename)
+ filename = cli.args.filename
+ keyboard = cli.config.c2json.keyboard
+ keymap = cli.config.c2json.keymap
- # Error checking
- if not cli.args.filename.exists():
- cli.log.error('C file does not exist!')
- cli.print_usage()
- return False
+ if filename:
+ if not keyboard and not keymap:
+ # fallback to inferring keyboard/keymap from path
+ (keymap, found_type) = find_keymap_from_dir(filename)
+ if found_type == 'keymap_directory':
+ keyboard = re.search(fr"keyboards/(.+)/keymaps/{keymap}/.*", filename.as_posix()).group(1)
- # Environment processing
- if cli.args.output == ('-'):
- cli.args.output = None
+ elif keyboard and keymap:
+ if not filename:
+ # fallback to inferring keyboard/keymap from path
+ filename = locate_keymap(keyboard, keymap)
+
+ if not all((filename, keyboard, keymap)):
+ cli.log.error('You must supply keyboard and keymap, a path to a keymap.c within qmk_firmware, or absolute filename and keyboard and keymap')
+ cli.print_help()
+ return False
- # Parse the keymap.c
try:
- keymap_json = qmk.keymap.c2json(cli.args.keyboard, cli.args.keymap, cli.args.filename, use_cpp=cli.args.no_cpp)
+ keymap_json = c2json_impl(keyboard, keymap, filename, use_cpp=cli.args.no_cpp)
except CppError as e:
if cli.config.general.verbose:
cli.log.debug('The C pre-processor ran into a fatal error: %s', e)
@@ -48,19 +60,14 @@ def c2json(cli):
# Generate the keymap.json
try:
- keymap_json = qmk.keymap.generate_json(keymap_json['keymap'], keymap_json['keyboard'], keymap_json['layout'], keymap_json['layers'])
+ keymap_json = generate_json(keymap_json['keymap'], keymap_json['keyboard'], keymap_json['layout'], keymap_json['layers'])
except KeyError:
cli.log.error('Something went wrong. Try to use --no-cpp.')
return False
if cli.args.output:
- cli.args.output.parent.mkdir(parents=True, exist_ok=True)
- if cli.args.output.exists():
- cli.args.output.replace(cli.args.output.parent / (cli.args.output.name + '.bak'))
- cli.args.output.write_text(json.dumps(keymap_json, cls=InfoJSONEncoder, sort_keys=True))
-
- if not cli.args.quiet:
- cli.log.info('Wrote keymap to %s.', cli.args.output)
-
+ keymap_lines = [json.dumps(keymap_json, cls=InfoJSONEncoder, sort_keys=True)]
else:
- print(json.dumps(keymap_json))
+ keymap_lines = [json.dumps(keymap_json)]
+
+ dump_lines(cli.args.output, keymap_lines, cli.args.quiet)
diff --git a/lib/python/qmk/cli/generate/config_h.py b/lib/python/qmk/cli/generate/config_h.py
index 64d4db6ffe..00fb1d9585 100755
--- a/lib/python/qmk/cli/generate/config_h.py
+++ b/lib/python/qmk/cli/generate/config_h.py
@@ -15,7 +15,12 @@ from qmk.constants import GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE
def generate_define(define, value=None):
+ is_keymap = cli.args.filename
value = f' {value}' if value is not None else ''
+ if is_keymap:
+ return f"""
+#undef {define}
+#define {define}{value}"""
return f"""
#ifndef {define}
# define {define}{value}
@@ -67,6 +72,19 @@ def generate_matrix_size(kb_info_json, config_h_lines):
config_h_lines.append(generate_define('MATRIX_ROWS', kb_info_json['matrix_size']['rows']))
+def generate_matrix_masked(kb_info_json, config_h_lines):
+ """"Enable matrix mask if required"""
+ mask_required = False
+
+ if 'matrix_grid' in kb_info_json.get('dip_switch', {}):
+ mask_required = True
+ if 'matrix_grid' in kb_info_json.get('split', {}).get('handedness', {}):
+ mask_required = True
+
+ if mask_required:
+ config_h_lines.append(generate_define('MATRIX_MASKED'))
+
+
def generate_config_items(kb_info_json, config_h_lines):
"""Iterate through the info_config map to generate basic config values.
"""
@@ -75,9 +93,9 @@ def generate_config_items(kb_info_json, config_h_lines):
for config_key, info_dict in info_config_map.items():
info_key = info_dict['info_key']
key_type = info_dict.get('value_type', 'raw')
- to_config = info_dict.get('to_config', True)
+ to_c = info_dict.get('to_c', True)
- if not to_config:
+ if not to_c:
continue
try:
@@ -130,23 +148,11 @@ def generate_encoder_config(encoder_json, config_h_lines, postfix=''):
def generate_split_config(kb_info_json, config_h_lines):
"""Generate the config.h lines for split boards."""
- if 'primary' in kb_info_json['split']:
- if kb_info_json['split']['primary'] in ('left', 'right'):
- config_h_lines.append('')
- config_h_lines.append('#ifndef MASTER_LEFT')
- config_h_lines.append('# ifndef MASTER_RIGHT')
- if kb_info_json['split']['primary'] == 'left':
- config_h_lines.append('# define MASTER_LEFT')
- elif kb_info_json['split']['primary'] == 'right':
- config_h_lines.append('# define MASTER_RIGHT')
- config_h_lines.append('# endif // MASTER_RIGHT')
- config_h_lines.append('#endif // MASTER_LEFT')
- elif kb_info_json['split']['primary'] == 'pin':
- config_h_lines.append(generate_define('SPLIT_HAND_PIN'))
- elif kb_info_json['split']['primary'] == 'matrix_grid':
- config_h_lines.append(generate_define('SPLIT_HAND_MATRIX_GRID', f'{{ {",".join(kb_info_json["split"]["matrix_grid"])} }}'))
- elif kb_info_json['split']['primary'] == 'eeprom':
- config_h_lines.append(generate_define('EE_HANDS'))
+ if 'handedness' in kb_info_json['split']:
+ # TODO: change SPLIT_HAND_MATRIX_GRID to require brackets
+ handedness = kb_info_json['split']['handedness']
+ if 'matrix_grid' in handedness:
+ config_h_lines.append(generate_define('SPLIT_HAND_MATRIX_GRID', ', '.join(handedness['matrix_grid'])))
if 'protocol' in kb_info_json['split'].get('transport', {}):
if kb_info_json['split']['transport']['protocol'] == 'i2c':
@@ -159,10 +165,13 @@ def generate_split_config(kb_info_json, config_h_lines):
generate_encoder_config(kb_info_json['split']['encoder']['right'], config_h_lines, '_RIGHT')
-def generate_led_animations_config(led_feature_json, config_h_lines, prefix):
+def generate_led_animations_config(feature, led_feature_json, config_h_lines, enable_prefix, animation_prefix):
+ if 'animation' in led_feature_json.get('default', {}):
+ config_h_lines.append(generate_define(f'{feature.upper()}_DEFAULT_MODE', f'{animation_prefix}{led_feature_json["default"]["animation"].upper()}'))
+
for animation in led_feature_json.get('animations', {}):
if led_feature_json['animations'][animation]:
- config_h_lines.append(generate_define(f'{prefix}{animation.upper()}'))
+ config_h_lines.append(generate_define(f'{enable_prefix}{animation.upper()}'))
@cli.argument('filename', nargs='?', arg_only=True, type=FileType('r'), completer=FilesCompleter('.json'), help='A configurator export JSON to be compiled and flashed or a pre-compiled binary firmware file (bin/hex) to be flashed.')
@@ -191,6 +200,8 @@ def generate_config_h(cli):
generate_matrix_size(kb_info_json, config_h_lines)
+ generate_matrix_masked(kb_info_json, config_h_lines)
+
if 'matrix_pins' in kb_info_json:
config_h_lines.append(matrix_pins(kb_info_json['matrix_pins']))
@@ -201,13 +212,13 @@ def generate_config_h(cli):
generate_split_config(kb_info_json, config_h_lines)
if 'led_matrix' in kb_info_json:
- generate_led_animations_config(kb_info_json['led_matrix'], config_h_lines, 'ENABLE_LED_MATRIX_')
+ generate_led_animations_config('led_matrix', kb_info_json['led_matrix'], config_h_lines, 'ENABLE_LED_MATRIX_', 'LED_MATRIX_')
if 'rgb_matrix' in kb_info_json:
- generate_led_animations_config(kb_info_json['rgb_matrix'], config_h_lines, 'ENABLE_RGB_MATRIX_')
+ generate_led_animations_config('rgb_matrix', kb_info_json['rgb_matrix'], config_h_lines, 'ENABLE_RGB_MATRIX_', 'RGB_MATRIX_')
if 'rgblight' in kb_info_json:
- generate_led_animations_config(kb_info_json['rgblight'], config_h_lines, 'RGBLIGHT_EFFECT_')
+ generate_led_animations_config('rgblight', kb_info_json['rgblight'], config_h_lines, 'RGBLIGHT_EFFECT_', 'RGBLIGHT_MODE_')
# Show the results
dump_lines(cli.args.output, config_h_lines, cli.args.quiet)
diff --git a/lib/python/qmk/cli/generate/keyboard_c.py b/lib/python/qmk/cli/generate/keyboard_c.py
index 9004b41abb..f8a2372cf3 100755
--- a/lib/python/qmk/cli/generate/keyboard_c.py
+++ b/lib/python/qmk/cli/generate/keyboard_c.py
@@ -57,6 +57,32 @@ def _gen_led_config(info_data):
return lines
+def _gen_matrix_mask(info_data):
+ """Convert info.json content to matrix_mask
+ """
+ cols = info_data['matrix_size']['cols']
+ rows = info_data['matrix_size']['rows']
+
+ # Default mask to everything disabled
+ mask = [['0'] * cols for i in range(rows)]
+
+ # Mirror layout macros squashed on top of each other
+ for layout_data in info_data['layouts'].values():
+ for key_data in layout_data['layout']:
+ row, col = key_data['matrix']
+ mask[row][col] = '1'
+
+ lines = []
+ lines.append('#ifdef MATRIX_MASKED')
+ lines.append('__attribute__((weak)) const matrix_row_t matrix_mask[] = {')
+ for i in range(rows):
+ lines.append(f' 0b{"".join(reversed(mask[i]))},')
+ lines.append('};')
+ lines.append('#endif')
+
+ return lines
+
+
@cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, required=True, help='Keyboard to generate keyboard.c for.')
@@ -70,6 +96,7 @@ def generate_keyboard_c(cli):
keyboard_h_lines = [GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE, '#include QMK_KEYBOARD_H', '']
keyboard_h_lines.extend(_gen_led_config(kb_info_json))
+ keyboard_h_lines.extend(_gen_matrix_mask(kb_info_json))
# Show the results
dump_lines(cli.args.output, keyboard_h_lines, cli.args.quiet)
diff --git a/lib/python/qmk/cli/generate/keycodes.py b/lib/python/qmk/cli/generate/keycodes.py
index ed8b6827bd..719fced5d5 100644
--- a/lib/python/qmk/cli/generate/keycodes.py
+++ b/lib/python/qmk/cli/generate/keycodes.py
@@ -94,6 +94,14 @@ def _generate_helpers(lines, keycodes):
hi = keycodes["keycodes"][f'0x{codes[1]:04X}']['key']
lines.append(f'#define IS_{ _translate_group(group).upper() }_KEYCODE(code) ((code) >= {lo} && (code) <= {hi})')
+ lines.append('')
+ lines.append('// Switch statement Helpers')
+ for group, codes in temp.items():
+ lo = keycodes["keycodes"][f'0x{codes[0]:04X}']['key']
+ hi = keycodes["keycodes"][f'0x{codes[1]:04X}']['key']
+ name = f'{ _translate_group(group).upper() }_KEYCODE_RANGE'
+ lines.append(f'#define { name.ljust(35) } {lo} ... {hi}')
+
def _generate_aliases(lines, keycodes):
# Work around ChibiOS ch.h include guard
diff --git a/lib/python/qmk/cli/generate/rules_mk.py b/lib/python/qmk/cli/generate/rules_mk.py
index fc272da6c6..5291556109 100755
--- a/lib/python/qmk/cli/generate/rules_mk.py
+++ b/lib/python/qmk/cli/generate/rules_mk.py
@@ -14,6 +14,12 @@ from qmk.path import normpath, FileType
from qmk.constants import GPL2_HEADER_SH_LIKE, GENERATED_HEADER_SH_LIKE
+def generate_rule(rules_key, rules_value):
+ is_keymap = cli.args.filename
+ rule_assignment_operator = '=' if is_keymap else '?='
+ return f'{rules_key} {rule_assignment_operator} {rules_value}'
+
+
def process_mapping_rule(kb_info_json, rules_key, info_dict):
"""Return the rules.mk line(s) for a mapping rule.
"""
@@ -29,15 +35,15 @@ def process_mapping_rule(kb_info_json, rules_key, info_dict):
return None
if key_type in ['array', 'list']:
- return f'{rules_key} ?= {" ".join(rules_value)}'
+ return generate_rule(rules_key, " ".join(rules_value))
elif key_type == 'bool':
- return f'{rules_key} ?= {"yes" if rules_value else "no"}'
+ return generate_rule(rules_key, "yes" if rules_value else "no")
elif key_type == 'mapping':
- return '\n'.join([f'{key} ?= {value}' for key, value in rules_value.items()])
+ return '\n'.join([generate_rule(key, value) for key, value in rules_value.items()])
elif key_type == 'str':
- return f'{rules_key} ?= "{rules_value}"'
+ return generate_rule(rules_key, f'"{rules_value}"')
- return f'{rules_key} ?= {rules_value}'
+ return generate_rule(rules_key, rules_value)
@cli.argument('filename', nargs='?', arg_only=True, type=FileType('r'), completer=FilesCompleter('.json'), help='A configurator export JSON to be compiled and flashed or a pre-compiled binary firmware file (bin/hex) to be flashed.')
@@ -77,21 +83,21 @@ def generate_rules_mk(cli):
for feature, enabled in kb_info_json['features'].items():
feature = feature.upper()
enabled = 'yes' if enabled else 'no'
- rules_mk_lines.append(f'{feature}_ENABLE ?= {enabled}')
+ rules_mk_lines.append(generate_rule(f'{feature}_ENABLE', enabled))
# Set SPLIT_TRANSPORT, if needed
if kb_info_json.get('split', {}).get('transport', {}).get('protocol') == 'custom':
- rules_mk_lines.append('SPLIT_TRANSPORT ?= custom')
+ rules_mk_lines.append(generate_rule('SPLIT_TRANSPORT', 'custom'))
# Set CUSTOM_MATRIX, if needed
if kb_info_json.get('matrix_pins', {}).get('custom'):
if kb_info_json.get('matrix_pins', {}).get('custom_lite'):
- rules_mk_lines.append('CUSTOM_MATRIX ?= lite')
+ rules_mk_lines.append(generate_rule('CUSTOM_MATRIX', 'lite'))
else:
- rules_mk_lines.append('CUSTOM_MATRIX ?= yes')
+ rules_mk_lines.append(generate_rule('CUSTOM_MATRIX', 'yes'))
if converter:
- rules_mk_lines.append(f'CONVERT_TO ?= {converter}')
+ rules_mk_lines.append(generate_rule('CONVERT_TO', converter))
# Show the results
dump_lines(cli.args.output, rules_mk_lines)
diff --git a/lib/python/qmk/info.py b/lib/python/qmk/info.py
index 9c8521a2a3..fe829a724a 100644
--- a/lib/python/qmk/info.py
+++ b/lib/python/qmk/info.py
@@ -352,55 +352,12 @@ def _extract_secure_unlock(info_data, config_c):
info_data['secure']['unlock_sequence'] = unlock_array
-def _extract_split_main(info_data, config_c):
- """Populate data about the split configuration
- """
- # Figure out how the main half is determined
- if config_c.get('SPLIT_HAND_PIN') is True:
- if 'split' not in info_data:
- info_data['split'] = {}
-
- if 'main' in info_data['split']:
- _log_warning(info_data, 'Split main hand is specified in both config.h (SPLIT_HAND_PIN) and info.json (split.main) (Value: %s), the config.h value wins.' % info_data['split']['main'])
-
- info_data['split']['main'] = 'pin'
-
- if config_c.get('SPLIT_HAND_MATRIX_GRID'):
- if 'split' not in info_data:
- info_data['split'] = {}
-
- if 'main' in info_data['split']:
- _log_warning(info_data, 'Split main hand is specified in both config.h (SPLIT_HAND_MATRIX_GRID) and info.json (split.main) (Value: %s), the config.h value wins.' % info_data['split']['main'])
-
- info_data['split']['main'] = 'matrix_grid'
- info_data['split']['matrix_grid'] = _extract_pins(config_c['SPLIT_HAND_MATRIX_GRID'])
-
- if config_c.get('EE_HANDS') is True:
- if 'split' not in info_data:
- info_data['split'] = {}
-
- if 'main' in info_data['split']:
- _log_warning(info_data, 'Split main hand is specified in both config.h (EE_HANDS) and info.json (split.main) (Value: %s), the config.h value wins.' % info_data['split']['main'])
-
- info_data['split']['main'] = 'eeprom'
-
- if config_c.get('MASTER_RIGHT') is True:
- if 'split' not in info_data:
- info_data['split'] = {}
-
- if 'main' in info_data['split']:
- _log_warning(info_data, 'Split main hand is specified in both config.h (MASTER_RIGHT) and info.json (split.main) (Value: %s), the config.h value wins.' % info_data['split']['main'])
-
- info_data['split']['main'] = 'right'
-
- if config_c.get('MASTER_LEFT') is True:
- if 'split' not in info_data:
- info_data['split'] = {}
-
- if 'main' in info_data['split']:
- _log_warning(info_data, 'Split main hand is specified in both config.h (MASTER_LEFT) and info.json (split.main) (Value: %s), the config.h value wins.' % info_data['split']['main'])
-
- info_data['split']['main'] = 'left'
+def _extract_split_handedness(info_data, config_c):
+ # Migrate
+ split = info_data.get('split', {})
+ if 'matrix_grid' in split:
+ split['handedness'] = split.get('handedness', {})
+ split['handedness']['matrix_grid'] = split.pop('matrix_grid')
def _extract_split_transport(info_data, config_c):
@@ -428,6 +385,15 @@ def _extract_split_transport(info_data, config_c):
if 'protocol' not in info_data['split']['transport']:
info_data['split']['transport']['protocol'] = 'serial'
+ # Migrate
+ transport = info_data.get('split', {}).get('transport', {})
+ if 'sync_matrix_state' in transport:
+ transport['sync'] = transport.get('sync', {})
+ transport['sync']['matrix_state'] = transport.pop('sync_matrix_state')
+ if 'sync_modifiers' in transport:
+ transport['sync'] = transport.get('sync', {})
+ transport['sync']['modifiers'] = transport.pop('sync_modifiers')
+
def _extract_split_right_pins(info_data, config_c):
# Figure out the right half matrix pins
@@ -520,6 +486,8 @@ def _config_to_json(key_type, config_value):
return list(map(str.strip, config_value.split(',')))
elif key_type == 'bool':
+ if isinstance(config_value, bool):
+ return config_value
return config_value in true_values
elif key_type == 'hex':
@@ -583,7 +551,7 @@ def _extract_config_h(info_data, config_c):
_extract_matrix_info(info_data, config_c)
_extract_audio(info_data, config_c)
_extract_secure_unlock(info_data, config_c)
- _extract_split_main(info_data, config_c)
+ _extract_split_handedness(info_data, config_c)
_extract_split_transport(info_data, config_c)
_extract_split_right_pins(info_data, config_c)
_extract_encoders(info_data, config_c)
diff --git a/lib/python/qmk/keymap.py b/lib/python/qmk/keymap.py
index 11e8d39dad..281c53cfda 100644
--- a/lib/python/qmk/keymap.py
+++ b/lib/python/qmk/keymap.py
@@ -191,16 +191,15 @@ 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()
+ relative_path = qmk.path.under_qmk_firmware(*args)
- if relative_cwd and len(relative_cwd.parts) > 1:
+ 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_cwd.parts[0] == 'keyboards' and 'keymaps' in relative_cwd.parts:
- current_path = Path('/'.join(relative_cwd.parts[1:])) # Strip 'keyboards' from the front
+ 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':
@@ -209,13 +208,13 @@ def find_keymap_from_dir():
return current_path.name, 'keymap_directory'
# 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'
+ elif relative_path.parts[0] == 'layouts' and is_keymap_dir(relative_path):
+ return relative_path.name, 'layouts_directory'
# If we're in `qmk_firmware/users` guess the name from the userspace they're in
- elif relative_cwd.parts[0] == 'users':
+ elif relative_path.parts[0] == 'users':
# Guess the keymap name based on which userspace they're in
- return relative_cwd.parts[1], 'users_directory'
+ return relative_path.parts[1], 'users_directory'
return None, None
@@ -657,7 +656,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:
diff --git a/lib/python/qmk/path.py b/lib/python/qmk/path.py
index 9d248451b8..94582a05e0 100644
--- a/lib/python/qmk/path.py
+++ b/lib/python/qmk/path.py
@@ -19,13 +19,11 @@ def is_keyboard(keyboard_name):
return rules_mk.exists()
-def under_qmk_firmware():
+def under_qmk_firmware(path=Path(os.environ['ORIG_CWD'])):
"""Returns a Path object representing the relative path under qmk_firmware, or None.
"""
- cwd = Path(os.environ['ORIG_CWD'])
-
try:
- return cwd.relative_to(QMK_FIRMWARE)
+ return path.relative_to(QMK_FIRMWARE)
except ValueError:
return None