def generate_config_h(cli): """Generates the info_config.h file. """ # Determine our keyboard/keymap if cli.args.keymap: km = locate_keymap(cli.args.keyboard, cli.args.keymap) km_json = json_load(km) validate(km_json, 'qmk.keymap.v1') kb_info_json = dotty(km_json.get('config', {})) else: kb_info_json = dotty(info_json(cli.args.keyboard)) # Build the info_config.h file. config_h_lines = [ GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE, '#pragma once' ] generate_config_items(kb_info_json, config_h_lines) generate_matrix_size(kb_info_json, config_h_lines) if 'matrix_pins' in kb_info_json: config_h_lines.append(matrix_pins(kb_info_json['matrix_pins'])) if 'split' in kb_info_json: generate_split_config(kb_info_json, config_h_lines) # Show the results dump_lines(cli.args.output, config_h_lines, cli.args.quiet)
def keymap_json_config(keyboard, keymap): """Extract keymap level config """ keymap_folder = locate_keymap(keyboard, keymap).parent km_info_json = parse_configurator_json(keymap_folder / 'keymap.json') return km_info_json.get('config', {})
def lint(cli): """Check keyboard and keymap for common mistakes. """ if not cli.config.lint.keyboard: cli.log.error('Missing required argument: --keyboard') cli.print_help() return False if not is_keyboard(cli.config.lint.keyboard): cli.log.error('No such keyboard: %s', cli.config.lint.keyboard) return False # Gather data about the keyboard. ok = True keyboard_path = keyboard(cli.config.lint.keyboard) keyboard_info = info_json(cli.config.lint.keyboard) readme_path = find_readme(cli.config.lint.keyboard) missing_readme_path = keyboard_path / 'readme.md' # Check for errors in the info.json if keyboard_info['parse_errors']: ok = False cli.log.error('Errors found when generating info.json.') if cli.config.lint.strict and keyboard_info['parse_warnings']: ok = False cli.log.error( 'Warnings found when generating info.json (Strict mode enabled.)') # Check for a readme.md and warn if it doesn't exist if not readme_path: ok = False cli.log.error('Missing %s', missing_readme_path) # Keymap specific checks if cli.config.lint.keymap: keymap_path = locate_keymap(cli.config.lint.keyboard, cli.config.lint.keymap) if not keymap_path: ok = False cli.log.error("Can't find %s keymap for %s keyboard.", cli.config.lint.keymap, cli.config.lint.keyboard) else: keymap_readme = keymap_path.parent / 'readme.md' if not keymap_readme.exists(): cli.log.warning('Missing %s', keymap_readme) if cli.config.lint.strict: ok = False # Check and report the overall status if ok: cli.log.info('Lint check passed!') return True cli.log.error('Lint check failed!') return False
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 keymap_check(kb, km): """Perform the keymap level checks. """ ok = True keymap_path = locate_keymap(kb, km) if not keymap_path: ok = False cli.log.error("%s: Can't find %s keymap.", kb, km) return ok
def generate_rules_mk(cli): """Generates a rules.mk file from info.json. """ # Determine our keyboard/keymap if cli.args.keymap: km = locate_keymap(cli.args.keyboard, cli.args.keymap) km_json = json_load(km) validate(km_json, 'qmk.keymap.v1') kb_info_json = dotty(km_json.get('config', {})) else: kb_info_json = dotty(info_json(cli.args.keyboard)) info_rules_map = json_load(Path('data/mappings/info_rules.json')) rules_mk_lines = [GPL2_HEADER_SH_LIKE, GENERATED_HEADER_SH_LIKE] # Iterate through the info_rules map to generate basic rules for rules_key, info_dict in info_rules_map.items(): new_entry = process_mapping_rule(kb_info_json, rules_key, info_dict) if new_entry: rules_mk_lines.append(new_entry) # Iterate through features to enable/disable them if 'features' in kb_info_json: 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}') # Set SPLIT_TRANSPORT, if needed if kb_info_json.get('split', {}).get('transport', {}).get('protocol') == 'custom': rules_mk_lines.append('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') else: rules_mk_lines.append('CUSTOM_MATRIX ?= yes') # Show the results dump_lines(cli.args.output, rules_mk_lines) if cli.args.output: if cli.args.quiet: if cli.args.escape: print(cli.args.output.as_posix().replace(' ', '\\ ')) else: print(cli.args.output) else: cli.log.info('Wrote rules.mk to %s.', cli.args.output)
def show_keymap(kb_info_json, title_caps=True): """Render the keymap in ascii art. """ keymap_path = locate_keymap(cli.config.info.keyboard, cli.config.info.keymap) if keymap_path and keymap_path.suffix == '.json': keymap_data = json.load(keymap_path.open(encoding='utf-8')) layout_name = keymap_data['layout'] layout_name = kb_info_json.get('layout_aliases', {}).get(layout_name, layout_name) # Resolve alias names for layer_num, layer in enumerate(keymap_data['layers']): if title_caps: cli.echo('{fg_cyan}Keymap %s Layer %s{fg_reset}:', cli.config.info.keymap, layer_num) else: cli.echo('{fg_cyan}keymap.%s.layer.%s{fg_reset}:', cli.config.info.keymap, layer_num)
def keymap_check(kb, km): """Perform the keymap level checks. """ ok = True keymap_path = locate_keymap(kb, km) if not keymap_path: ok = False cli.log.error("%s: Can't find %s keymap.", kb, km) return ok # Additional checks invalid_files = git_get_ignored_files(keymap_path.parent) for file in invalid_files: cli.log.error(f'{kb}/{km}: The file "{file}" should not exist!') ok = False return ok
def generate_config_h(cli): """Generates the info_config.h file. """ # Determine our keyboard/keymap if cli.args.keymap: km = locate_keymap(cli.args.keyboard, cli.args.keymap) km_json = json_load(km) validate(km_json, 'qmk.keymap.v1') kb_info_json = dotty(km_json.get('config', {})) else: kb_info_json = dotty(info_json(cli.args.keyboard)) # Build the info_config.h file. config_h_lines = [ '/* This file was generated by `qmk generate-config-h`. Do not edit or copy.', ' */', '', '#pragma once' ] generate_config_items(kb_info_json, config_h_lines) generate_matrix_size(kb_info_json, config_h_lines) if 'matrix_pins' in kb_info_json: config_h_lines.append(matrix_pins(kb_info_json['matrix_pins'])) if 'split' in kb_info_json: generate_split_config(kb_info_json, config_h_lines) # Show the results config_h = '\n'.join(config_h_lines) 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(config_h) if not cli.args.quiet: cli.log.info('Wrote info_config.h to %s.', cli.args.output) else: print(config_h)
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 show_keymap(kb_info_json, title_caps=True): """Render the keymap in ascii art. """ keymap_path = locate_keymap(cli.config.info.keyboard, cli.config.info.keymap) if keymap_path and keymap_path.suffix == '.json': if title_caps: cli.echo('{fg_blue}Keymap "%s"{fg_reset}:', cli.config.info.keymap) else: cli.echo('{fg_blue}keymap_%s{fg_reset}:', cli.config.info.keymap) keymap_data = json.load(keymap_path.open(encoding='utf-8')) layout_name = keymap_data['layout'] for layer_num, layer in enumerate(keymap_data['layers']): if title_caps: cli.echo('{fg_cyan}Layer %s{fg_reset}:', layer_num) else: cli.echo('{fg_cyan}layer_%s{fg_reset}:', layer_num) print( render_layout(kb_info_json['layouts'][layout_name]['layout'], cli.config.info.ascii, layer))
def generate_rules_mk(cli): """Generates a rules.mk file from info.json. """ # Determine our keyboard/keymap if cli.args.keymap: km = locate_keymap(cli.args.keyboard, cli.args.keymap) km_json = json_load(km) validate(km_json, 'qmk.keymap.v1') kb_info_json = dotty(km_json.get('config', {})) else: kb_info_json = dotty(info_json(cli.args.keyboard)) info_rules_map = json_load(Path('data/mappings/info_rules.json')) rules_mk_lines = [ '# This file was generated by `qmk generate-rules-mk`. Do not edit or copy.', '' ] # Iterate through the info_rules map to generate basic rules for rules_key, info_dict in info_rules_map.items(): new_entry = process_mapping_rule(kb_info_json, rules_key, info_dict) if new_entry: rules_mk_lines.append(new_entry) # Iterate through features to enable/disable them if 'features' in kb_info_json: for feature, enabled in kb_info_json['features'].items(): if feature == 'bootmagic_lite' and enabled: rules_mk_lines.append('BOOTMAGIC_ENABLE ?= lite') else: feature = feature.upper() enabled = 'yes' if enabled else 'no' rules_mk_lines.append(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') # 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') else: rules_mk_lines.append('CUSTOM_MATRIX ?= yes') # Show the results rules_mk = '\n'.join(rules_mk_lines) + '\n' 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(rules_mk) if cli.args.quiet: if cli.args.escape: print(cli.args.output.as_posix().replace(' ', '\\ ')) else: print(cli.args.output) else: cli.log.info('Wrote rules.mk to %s.', cli.args.output) else: print(rules_mk)