def info_json(keyboard): """Generate the info.json data for a specific keyboard. """ cur_dir = Path('keyboards') rules = parse_rules_mk_file(cur_dir / keyboard / 'rules.mk') if 'DEFAULT_FOLDER' in rules: keyboard = rules['DEFAULT_FOLDER'] rules = parse_rules_mk_file(cur_dir / keyboard / 'rules.mk', rules) info_data = { 'keyboard_name': str(keyboard), 'keyboard_folder': str(keyboard), 'keymaps': {}, 'layouts': {}, 'maintainer': 'qmk', } # Populate the list of JSON keymaps for keymap in list_keymaps(keyboard, c=False, fullpath=True): info_data['keymaps'][keymap.name] = { 'url': f'https://raw.githubusercontent.com/qmk/qmk_firmware/master/{keymap}/keymap.json' } # Populate layout data for layout_name, layout_json in _find_all_layouts(keyboard, rules).items(): if not layout_name.startswith('LAYOUT_kc'): info_data['layouts'][layout_name] = layout_json # Merge in the data from info.json, config.h, and rules.mk info_data = merge_info_jsons(keyboard, info_data) info_data = _extract_config_h(info_data) info_data = _extract_rules_mk(info_data) return info_data
def info_json(keyboard): """Generate the info.json data for a specific keyboard. """ cur_dir = Path('keyboards') rules = parse_rules_mk_file(cur_dir / keyboard / 'rules.mk') if 'DEFAULT_FOLDER' in rules: keyboard = rules['DEFAULT_FOLDER'] rules = parse_rules_mk_file(cur_dir / keyboard / 'rules.mk', rules) info_data = { 'keyboard_name': str(keyboard), 'keyboard_folder': str(keyboard), 'keymaps': {}, 'layouts': {}, 'parse_errors': [], 'parse_warnings': [], 'maintainer': 'qmk', } # Populate the list of JSON keymaps for keymap in list_keymaps(keyboard, c=False, fullpath=True): info_data['keymaps'][keymap.name] = {'url': f'https://raw.githubusercontent.com/qmk/qmk_firmware/master/{keymap}/keymap.json'} # Populate layout data layouts, aliases = _find_all_layouts(info_data, keyboard) if aliases: info_data['layout_aliases'] = aliases for layout_name, layout_json in layouts.items(): if not layout_name.startswith('LAYOUT_kc'): layout_json['c_macro'] = True info_data['layouts'][layout_name] = layout_json # Merge in the data from info.json, config.h, and rules.mk info_data = merge_info_jsons(keyboard, info_data) info_data = _extract_config_h(info_data) info_data = _extract_rules_mk(info_data) # Validate against the jsonschema try: keyboard_api_validate(info_data) except jsonschema.ValidationError as e: json_path = '.'.join([str(p) for p in e.absolute_path]) cli.log.error('Invalid API data: %s: %s: %s', keyboard, json_path, e.message) exit() # Make sure we have at least one layout if not info_data.get('layouts'): _log_error(info_data, 'No LAYOUTs defined! Need at least one layout defined in the keyboard.h or info.json.') # Make sure we supply layout macros for the community layouts we claim to support for layout in info_data.get('community_layouts', []): layout_name = 'LAYOUT_' + layout if layout_name not in info_data.get('layouts', {}) and layout_name not in info_data.get('layout_aliases', {}): _log_error(info_data, 'Claims to support community layout %s but no %s() macro found' % (layout, layout_name)) return info_data
def lint(cli): """Check keyboard and keymap for common mistakes. """ failed = [] # Determine our keyboard list if cli.args.all_kb: if cli.args.keyboard: cli.log.warning( 'Both --all-kb and --keyboard passed, --all-kb takes precedence.' ) keyboard_list = list_keyboards() elif not cli.config.lint.keyboard: cli.log.error('Missing required arguments: --keyboard or --all-kb') cli.print_help() return False else: keyboard_list = cli.config.lint.keyboard.split(',') # Lint each keyboard for kb in keyboard_list: if not is_keyboard(kb): cli.log.error('No such keyboard: %s', kb) continue # Determine keymaps to also check if cli.args.all_km: keymaps = list_keymaps(kb) elif cli.config.lint.keymap: keymaps = {cli.config.lint.keymap} else: keymaps = _list_defaultish_keymaps(kb) # Ensure that at least a 'default' keymap always exists keymaps.add('default') ok = True # keyboard level checks if not keyboard_check(kb): ok = False # Keymap specific checks for keymap in keymaps: if not keymap_check(kb, keymap): ok = False # Report status if not ok: failed.append(kb) # Check and report the overall status if failed: cli.log.error('Lint check failed for: %s', ', '.join(failed)) return False cli.log.info('Lint check passed!') return True
def _find_via_layout_macro(keyboard): keymap_layout = None if 'via' in list_keymaps(keyboard): keymap_path = locate_keymap(keyboard, 'via') if keymap_path.suffix == '.json': keymap_layout = parse_configurator_json(keymap_path)['layout'] else: keymap_layout = parse_keymap_c(keymap_path)['layers'][0]['layout'] return keymap_layout
def _list_defaultish_keymaps(kb): """Return default like keymaps for a given keyboard """ defaultish = ['ansi', 'iso', 'via'] keymaps = set() for x in list_keymaps(kb): if x in defaultish or x.startswith('default'): keymaps.add(x) return keymaps
def info_json(keyboard): """Generate the info.json data for a specific keyboard. """ cur_dir = Path('keyboards') root_rules_mk = parse_rules_mk_file(cur_dir / keyboard / 'rules.mk') if 'DEFAULT_FOLDER' in root_rules_mk: keyboard = root_rules_mk['DEFAULT_FOLDER'] info_data = { 'keyboard_name': str(keyboard), 'keyboard_folder': str(keyboard), 'keymaps': {}, 'layouts': {}, 'parse_errors': [], 'parse_warnings': [], 'maintainer': 'qmk', } # Populate the list of JSON keymaps for keymap in list_keymaps(keyboard, c=False, fullpath=True): info_data['keymaps'][keymap.name] = {'url': f'https://raw.githubusercontent.com/qmk/qmk_firmware/master/{keymap}/keymap.json'} # Populate layout data layouts, aliases = _search_keyboard_h(keyboard) if aliases: info_data['layout_aliases'] = aliases for layout_name, layout_json in layouts.items(): if not layout_name.startswith('LAYOUT_kc'): layout_json['c_macro'] = True info_data['layouts'][layout_name] = layout_json # Merge in the data from info.json, config.h, and rules.mk info_data = merge_info_jsons(keyboard, info_data) info_data = _extract_rules_mk(info_data) info_data = _extract_config_h(info_data) # Ensure that we have matrix row and column counts info_data = _matrix_size(info_data) # Validate against the jsonschema try: validate(info_data, 'qmk.api.keyboard.v1') except jsonschema.ValidationError as e: json_path = '.'.join([str(p) for p in e.absolute_path]) cli.log.error('Invalid API data: %s: %s: %s', keyboard, json_path, e.message) exit(1) # Make sure we have at least one layout if not info_data.get('layouts'): _find_missing_layouts(info_data, keyboard) if not info_data.get('layouts'): _log_error(info_data, 'No LAYOUTs defined! Need at least one layout defined in the keyboard.h or info.json.') # Filter out any non-existing community layouts for layout in info_data.get('community_layouts', []): if not _valid_community_layout(layout): # Ignore layout from future checks info_data['community_layouts'].remove(layout) _log_error(info_data, 'Claims to support a community layout that does not exist: %s' % (layout)) # Make sure we supply layout macros for the community layouts we claim to support for layout in info_data.get('community_layouts', []): layout_name = 'LAYOUT_' + layout if layout_name not in info_data.get('layouts', {}) and layout_name not in info_data.get('layout_aliases', {}): _log_error(info_data, 'Claims to support community layout %s but no %s() macro found' % (layout, layout_name)) # Check that the reported matrix size is consistent with the actual matrix size _check_matrix(info_data) # Remove newline characters from layout labels _remove_newlines_from_labels(layouts) return info_data
def info_json(keyboard): """Generate the info.json data for a specific keyboard. """ cur_dir = Path('keyboards') rules = parse_rules_mk_file(cur_dir / keyboard / 'rules.mk') if 'DEFAULT_FOLDER' in rules: keyboard = rules['DEFAULT_FOLDER'] rules = parse_rules_mk_file(cur_dir / keyboard / 'rules.mk', rules) info_data = { 'keyboard_name': str(keyboard), 'keyboard_folder': str(keyboard), 'keymaps': {}, 'layouts': {}, 'parse_errors': [], 'parse_warnings': [], 'maintainer': 'qmk', } # Populate the list of JSON keymaps for keymap in list_keymaps(keyboard, c=False, fullpath=True): info_data['keymaps'][keymap.name] = { 'url': f'https://raw.githubusercontent.com/qmk/qmk_firmware/master/{keymap}/keymap.json' } # Populate layout data for layout_name, layout_json in _find_all_layouts(info_data, keyboard).items(): if not layout_name.startswith('LAYOUT_kc'): layout_json['c_macro'] = True info_data['layouts'][layout_name] = layout_json # Merge in the data from info.json, config.h, and rules.mk info_data = merge_info_jsons(keyboard, info_data) info_data = _extract_config_h(info_data) info_data = _extract_rules_mk(info_data) # Validate against the jsonschema try: keyboard_api_validate(info_data) except jsonschema.ValidationError as e: json_path = '.'.join([str(p) for p in e.absolute_path]) cli.log.error('Invalid API data: %s: %s: %s', keyboard, json_path, e.message) print(dir(e)) exit() # Make sure we have at least one layout if not info_data.get('layouts'): _log_error( info_data, 'No LAYOUTs defined! Need at least one layout defined in the keyboard.h or info.json.' ) # Make sure we supply layout macros for the community layouts we claim to support # FIXME(skullydazed): This should be populated into info.json and read from there instead if 'LAYOUTS' in rules and info_data.get('layouts'): # Match these up against the supplied layouts supported_layouts = rules['LAYOUTS'].strip().split() for layout_name in sorted(info_data['layouts']): layout_name = layout_name[7:] if layout_name in supported_layouts: supported_layouts.remove(layout_name) if supported_layouts: for supported_layout in supported_layouts: _log_error( info_data, 'Claims to support community layout %s but no LAYOUT_%s() macro found' % (supported_layout, supported_layout)) return info_data