def resolve_keyboard(keyboard): cur_dir = Path('keyboards') rules = parse_rules_mk_file(cur_dir / keyboard / 'rules.mk') while 'DEFAULT_FOLDER' in rules and keyboard != rules['DEFAULT_FOLDER']: keyboard = rules['DEFAULT_FOLDER'] rules = parse_rules_mk_file(cur_dir / keyboard / 'rules.mk') return keyboard
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), 'layouts': {}, 'maintainer': 'qmk', } 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 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': {}, '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 rules_mk(keyboard): """Get a rules.mk for a keyboard Args: keyboard: name of the keyboard Returns: a dictionary representing the content of the entire rules.mk tree for a keyboard """ cur_dir = Path('keyboards') keyboard = Path(resolve_keyboard(keyboard)) rules = parse_rules_mk_file(cur_dir / keyboard / 'rules.mk') for i, dir in enumerate(keyboard.parts): cur_dir = cur_dir / dir rules = parse_rules_mk_file(cur_dir / 'rules.mk', rules) return rules
def rules_mk(keyboard): """Get a rules.mk for a keyboard Args: keyboard: name of the keyboard Returns: a dictionary representing the content of the entire rules.mk tree for a keyboard """ keyboard = Path(keyboard) cur_dir = Path('keyboards') rules = parse_rules_mk_file(cur_dir / keyboard / 'rules.mk') if 'DEFAULT_FOLDER' in rules: keyboard = Path(rules['DEFAULT_FOLDER']) for i, dir in enumerate(keyboard.parts): cur_dir = cur_dir / dir rules = parse_rules_mk_file(cur_dir / 'rules.mk', rules) return rules
def keyboard_folder(keyboard): """Returns the actual keyboard folder. This checks aliases and DEFAULT_FOLDER to resolve the actual path for a keyboard. """ aliases = json_load(Path('data/mappings/keyboard_aliases.json')) if keyboard in aliases: keyboard = aliases[keyboard].get('target', keyboard) rules_mk_file = Path(base_path, keyboard, 'rules.mk') if rules_mk_file.exists(): rules_mk = parse_rules_mk_file(rules_mk_file) keyboard = rules_mk.get('DEFAULT_FOLDER', keyboard) if not qmk.path.is_keyboard(keyboard): raise ValueError(f'Invalid keyboard: {keyboard}') return keyboard
def keymap_json(keyboard, keymap): """Generate the info.json data for a specific keymap. """ keymap_folder = locate_keymap(keyboard, keymap).parent # Files to scan keymap_config = keymap_folder / 'config.h' keymap_rules = keymap_folder / 'rules.mk' keymap_file = keymap_folder / 'keymap.json' # Build the info.json file kb_info_json = info_json(keyboard) # Merge in the data from keymap.json km_info_json = keymap_json_config(keyboard, keymap) if keymap_file.exists() else {} deep_update(kb_info_json, km_info_json) # Merge in the data from config.h, and rules.mk _extract_rules_mk(kb_info_json, parse_rules_mk_file(keymap_rules)) _extract_config_h(kb_info_json, parse_config_h_file(keymap_config)) return kb_info_json
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