def generate_config_h(cli): """Generates the info_config.h file. """ # Determine our keyboard(s) if not cli.config.generate_config_h.keyboard: cli.log.error('Missing paramater: --keyboard') cli.subcommands['info'].print_help() return False if not is_keyboard(cli.config.generate_config_h.keyboard): cli.log.error('Invalid keyboard: "%s"', cli.config.generate_config_h.keyboard) return False # Build the info.json file kb_info_json = info_json(cli.config.generate_config_h.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'] if 'debounce' in kb_info_json: config_h_lines.append(debounce(kb_info_json['debounce'])) if 'diode_direction' in kb_info_json: config_h_lines.append(diode_direction(kb_info_json['diode_direction'])) if 'indicators' in kb_info_json: config_h_lines.append(indicators(kb_info_json['indicators'])) if 'keyboard_name' in kb_info_json: config_h_lines.append(keyboard_name(kb_info_json['keyboard_name'])) if 'layout_aliases' in kb_info_json: config_h_lines.append(layout_aliases(kb_info_json['layout_aliases'])) if 'manufacturer' in kb_info_json: config_h_lines.append(manufacturer(kb_info_json['manufacturer'])) if 'rgblight' in kb_info_json: config_h_lines.append(rgblight(kb_info_json['rgblight'])) if 'matrix_pins' in kb_info_json: config_h_lines.append(matrix_pins(kb_info_json['matrix_pins'])) if 'usb' in kb_info_json: config_h_lines.append(usb_properties(kb_info_json['usb'])) # 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.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 wrapper(*args, **kwargs): # Check to make sure their copy of MILC supports config_source if not hasattr(cli, 'config_source'): cli.log.error( "This subcommand requires a newer version of the QMK CLI. Please upgrade using `pip3 install --upgrade qmk` or your package manager." ) exit(1) # Ensure that `--keyboard` was not passed and CWD is under `qmk_firmware/keyboards` if cli.config_source[ cli._entrypoint.__name__]['keyboard'] != 'argument': relative_cwd = under_qmk_firmware() if relative_cwd and len( relative_cwd.parts ) > 1 and relative_cwd.parts[0] == 'keyboards': # Attempt to extract the keyboard name from the current directory current_path = Path('/'.join(relative_cwd.parts[1:])) if 'keymaps' in current_path.parts: # Strip current_path of anything after `keymaps` keymap_index = len( current_path.parts) - current_path.parts.index( 'keymaps') - 1 current_path = current_path.parents[keymap_index] if is_keyboard(current_path): cli.config[cli._entrypoint.__name__]['keyboard'] = str( current_path) cli.config_source[cli._entrypoint.__name__][ 'keyboard'] = 'keyboard_directory' return func(*args, **kwargs)
def info(cli): """Compile an info.json for a particular keyboard and pretty-print it. """ # Determine our keyboard(s) if not cli.config.info.keyboard: cli.log.error('Missing parameter: --keyboard') cli.subcommands['info'].print_help() return False if not is_keyboard(cli.config.info.keyboard): cli.log.error('Invalid keyboard: "%s"', cli.config.info.keyboard) return False # Build the info.json file kb_info_json = info_json(cli.config.info.keyboard) # Output in the requested format if cli.args.format == 'json': print(json.dumps(kb_info_json, cls=InfoJSONEncoder)) elif cli.args.format == 'text': print_text_output(kb_info_json) elif cli.args.format == 'friendly': print_friendly_output(kb_info_json) else: cli.log.error('Unknown format: %s', cli.args.format) return False
def generate_dfu_header(cli): """Generates the Keyboard.h file. """ # Determine our keyboard(s) if not cli.config.generate_dfu_header.keyboard: cli.log.error('Missing parameter: --keyboard') cli.subcommands['info'].print_help() return False if not is_keyboard(cli.config.generate_dfu_header.keyboard): cli.log.error('Invalid keyboard: "%s"', cli.config.generate_dfu_header.keyboard) return False # Build the Keyboard.h file. kb_info_json = dotty(info_json(cli.config.generate_dfu_header.keyboard)) keyboard_h_lines = [GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE, '#pragma once'] keyboard_h_lines.append(f'#define MANUFACTURER {kb_info_json["manufacturer"]}') keyboard_h_lines.append(f'#define PRODUCT {kb_info_json["keyboard_name"]} Bootloader') # Optional if 'qmk_lufa_bootloader.esc_output' in kb_info_json: keyboard_h_lines.append(f'#define QMK_ESC_OUTPUT {kb_info_json["qmk_lufa_bootloader.esc_output"]}') if 'qmk_lufa_bootloader.esc_input' in kb_info_json: keyboard_h_lines.append(f'#define QMK_ESC_INPUT {kb_info_json["qmk_lufa_bootloader.esc_input"]}') if 'qmk_lufa_bootloader.led' in kb_info_json: keyboard_h_lines.append(f'#define QMK_LED {kb_info_json["qmk_lufa_bootloader.led"]}') if 'qmk_lufa_bootloader.speaker' in kb_info_json: keyboard_h_lines.append(f'#define QMK_SPEAKER {kb_info_json["qmk_lufa_bootloader.speaker"]}') # Show the results dump_lines(cli.args.output, keyboard_h_lines, cli.args.quiet)
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 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 generate_dfu_header(cli): """Generates the Keyboard.h file. """ # Determine our keyboard(s) if not cli.config.generate_dfu_header.keyboard: cli.log.error('Missing parameter: --keyboard') cli.subcommands['info'].print_help() return False if not is_keyboard(cli.config.generate_dfu_header.keyboard): cli.log.error('Invalid keyboard: "%s"', cli.config.generate_dfu_header.keyboard) return False # Build the Keyboard.h file. kb_info_json = dotty(info_json(cli.config.generate_dfu_header.keyboard)) keyboard_h_lines = [ '/* This file was generated by `qmk generate-dfu-header`. Do not edit or copy.', ' */', '', '#pragma once' ] keyboard_h_lines.append( f'#define MANUFACTURER {kb_info_json["manufacturer"]}') keyboard_h_lines.append( f'#define PRODUCT {kb_info_json["keyboard_name"]} Bootloader') # Optional if 'qmk_lufa_bootloader.esc_output' in kb_info_json: keyboard_h_lines.append( f'#define QMK_ESC_OUTPUT {kb_info_json["qmk_lufa_bootloader.esc_output"]}' ) if 'qmk_lufa_bootloader.esc_input' in kb_info_json: keyboard_h_lines.append( f'#define QMK_ESC_INPUT {kb_info_json["qmk_lufa_bootloader.esc_input"]}' ) if 'qmk_lufa_bootloader.led' in kb_info_json: keyboard_h_lines.append( f'#define QMK_LED {kb_info_json["qmk_lufa_bootloader.led"]}') if 'qmk_lufa_bootloader.speaker' in kb_info_json: keyboard_h_lines.append( f'#define QMK_SPEAKER {kb_info_json["qmk_lufa_bootloader.speaker"]}' ) # Show the results keyboard_h = '\n'.join(keyboard_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(keyboard_h) if not cli.args.quiet: cli.log.info('Wrote Keyboard.h to %s.', cli.args.output) else: print(keyboard_h)
def list_keymaps(cli): """List the keymaps for a specific keyboard """ if not is_keyboard(cli.config.list_keymaps.keyboard): cli.log.error('Keyboard %s does not exist!', cli.config.list_keymaps.keyboard) exit(1) for name in qmk.keymap.list_keymaps(cli.config.list_keymaps.keyboard): print(name)
def generate_rules_mk(cli): """Generates a rules.mk file from info.json. """ if not cli.config.generate_rules_mk.keyboard: cli.log.error('Missing parameter: --keyboard') cli.subcommands['info'].print_help() return False if not is_keyboard(cli.config.generate_rules_mk.keyboard): cli.log.error('Invalid keyboard: "%s"', cli.config.generate_rules_mk.keyboard) return False kb_info_json = dotty(info_json(cli.config.generate_rules_mk.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}') # 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)
def info(cli): """Compile an info.json for a particular keyboard and pretty-print it. """ # Determine our keyboard(s) if not cli.config.info.keyboard: cli.log.error('Missing parameter: --keyboard') cli.subcommands['info'].print_help() return False if not is_keyboard(cli.config.info.keyboard): cli.log.error('Invalid keyboard: "%s"', cli.config.info.keyboard) return False if bool(cli.args.rules_mk): print_parsed_rules_mk(cli.config.info.keyboard) return False # default keymap stored in config file should be ignored if cli.config_source.info.keymap == 'config_file': cli.config_source.info.keymap = None # Build the info.json file if cli.config.info.keymap: kb_info_json = keymap_json(cli.config.info.keyboard, cli.config.info.keymap) else: kb_info_json = info_json(cli.config.info.keyboard) # Output in the requested format if cli.args.format == 'json': print(json.dumps(kb_info_json, cls=InfoJSONEncoder)) return True elif cli.args.format == 'text': print_dotted_output(kb_info_json) title_caps = False elif cli.args.format == 'friendly': print_friendly_output(kb_info_json) title_caps = True else: cli.log.error('Unknown format: %s', cli.args.format) return False # Output requested extras if cli.config.info.layouts: show_layouts(kb_info_json, title_caps) if cli.config.info.matrix: show_matrix(kb_info_json, title_caps) if cli.config.info.keymap: show_keymap(kb_info_json, title_caps)
def find_keyboard_from_dir(): """Returns a keyboard name based on the user's current directory. """ relative_cwd = under_qmk_firmware() if relative_cwd and len( relative_cwd.parts) > 1 and relative_cwd.parts[0] == 'keyboards': # Attempt to extract the keyboard name from the current directory current_path = Path('/'.join(relative_cwd.parts[1:])) if 'keymaps' in current_path.parts: # Strip current_path of anything after `keymaps` keymap_index = len( current_path.parts) - current_path.parts.index('keymaps') - 1 current_path = current_path.parents[keymap_index] if is_keyboard(current_path): return str(current_path)
def generate_info_json(cli): """Generate an info.json file for a keyboard """ # Determine our keyboard(s) if not cli.config.generate_info_json.keyboard: cli.log.error('Missing parameter: --keyboard') cli.subcommands['info'].print_help() return False if not is_keyboard(cli.config.generate_info_json.keyboard): cli.log.error('Invalid keyboard: "%s"', cli.config.generate_info_json.keyboard) return False # Build the info.json file kb_info_json = info_json(cli.config.generate_info_json.keyboard) strip_info_json(kb_info_json) # Display the results print(json.dumps(kb_info_json, indent=2, cls=InfoJSONEncoder))
def generate_info_json(cli): """Generate an info.json file for a keyboard """ # Determine our keyboard(s) if not cli.config.generate_info_json.keyboard: cli.log.error('Missing parameter: --keyboard') cli.subcommands['info'].print_help() return False if not is_keyboard(cli.config.generate_info_json.keyboard): cli.log.error('Invalid keyboard: "%s"', cli.config.generate_info_json.keyboard) return False if cli.args.overwrite: output_path = (Path('keyboards') / cli.config.generate_info_json.keyboard / 'info.json').resolve() if cli.args.output: cli.log.warning('Overwriting user supplied --output with %s', output_path) cli.args.output = output_path # Build the info.json file kb_info_json = info_json(cli.config.generate_info_json.keyboard) strip_info_json(kb_info_json) info_json_text = json.dumps(kb_info_json, indent=4, cls=InfoJSONEncoder) if cli.args.output: # Write to a file output_path = normpath(cli.args.output) if output_path.exists(): cli.log.warning('Overwriting output file %s', output_path) output_path.write_text(info_json_text + '\n') cli.log.info('Wrote info.json to %s.', output_path) else: # Display the results print(info_json_text)
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 is_keyboard(keyboard): raise ValueError(f'Invalid keyboard: {keyboard}') return keyboard
def generate_layouts(cli): """Generates the layouts.h file. """ # Determine our keyboard(s) if not cli.config.generate_layouts.keyboard: cli.log.error('Missing paramater: --keyboard') cli.subcommands['info'].print_help() return False if not is_keyboard(cli.config.generate_layouts.keyboard): cli.log.error('Invalid keyboard: "%s"', cli.config.generate_layouts.keyboard) return False # Build the info.json file kb_info_json = info_json(cli.config.generate_layouts.keyboard) # Build the layouts.h file. layouts_h_lines = [ '/* This file was generated by `qmk generate-layouts`. Do not edit or copy.' ' */', '', '#pragma once' ] if 'matrix_pins' in kb_info_json: if 'direct' in kb_info_json['matrix_pins']: col_num = len(kb_info_json['matrix_pins']['direct'][0]) row_num = len(kb_info_json['matrix_pins']['direct']) elif 'cols' in kb_info_json['matrix_pins'] and 'rows' in kb_info_json[ 'matrix_pins']: col_num = len(kb_info_json['matrix_pins']['cols']) row_num = len(kb_info_json['matrix_pins']['rows']) else: cli.log.error('%s: Invalid matrix config.', cli.config.generate_layouts.keyboard) return False for layout_name in kb_info_json['layouts']: if kb_info_json['layouts'][layout_name]['c_macro']: continue if 'matrix' not in kb_info_json['layouts'][layout_name]['layout'][0]: cli.log.debug('%s/%s: No matrix data!', cli.config.generate_layouts.keyboard, layout_name) continue layout_keys = [] layout_matrix = [['KC_NO' for i in range(col_num)] for i in range(row_num)] for i, key in enumerate( kb_info_json['layouts'][layout_name]['layout']): row = key['matrix'][0] col = key['matrix'][1] identifier = 'k%s%s' % (ROW_LETTERS[row], COL_LETTERS[col]) try: layout_matrix[row][col] = identifier layout_keys.append(identifier) except IndexError: key_name = key.get('label', identifier) cli.log.error( 'Matrix data out of bounds for layout %s at index %s (%s): %s, %s', layout_name, i, key_name, row, col) return False layouts_h_lines.append('') layouts_h_lines.append('#define %s(%s) {\\' % (layout_name, ', '.join(layout_keys))) rows = ', \\\n'.join( ['\t {' + ', '.join(row) + '}' for row in layout_matrix]) rows += ' \\' layouts_h_lines.append(rows) layouts_h_lines.append('}') # Show the results layouts_h = '\n'.join(layouts_h_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.name + '.bak') cli.args.output.write_text(layouts_h) if not cli.args.quiet: cli.log.info('Wrote info_config.h to %s.', cli.args.output) else: print(layouts_h)
def info(cli): """Compile an info.json for a particular keyboard and pretty-print it. """ # Determine our keyboard(s) if not is_keyboard(cli.config.info.keyboard): cli.log.error('Invalid keyboard: %s!', cli.config.info.keyboard) exit(1) # Build the info.json file kb_info_json = info_json(cli.config.info.keyboard) # Output in the requested format if cli.args.format == 'json': print(json.dumps(kb_info_json)) exit() if cli.args.format == 'text': for key in sorted(kb_info_json): if key == 'layouts': cli.echo('{fg_blue}layouts{fg_reset}: %s', ', '.join(sorted(kb_info_json['layouts'].keys()))) else: cli.echo('{fg_blue}%s{fg_reset}: %s', key, kb_info_json[key]) if cli.config.info.layouts: show_layouts(kb_info_json, False) if cli.config.info.matrix: show_matrix(kb_info_json, False) if cli.config_source.info.keymap and cli.config_source.info.keymap != 'config_file': show_keymap(kb_info_json, False) elif cli.args.format == 'friendly': cli.echo('{fg_blue}Keyboard Name{fg_reset}: %s', kb_info_json.get('keyboard_name', 'Unknown')) cli.echo('{fg_blue}Manufacturer{fg_reset}: %s', kb_info_json.get('manufacturer', 'Unknown')) if 'url' in kb_info_json: cli.echo('{fg_blue}Website{fg_reset}: %s', kb_info_json['url']) if kb_info_json.get('maintainer') == 'qmk': cli.echo('{fg_blue}Maintainer{fg_reset}: QMK Community') else: cli.echo('{fg_blue}Maintainer{fg_reset}: %s', kb_info_json.get('maintainer', 'qmk')) cli.echo('{fg_blue}Keyboard Folder{fg_reset}: %s', kb_info_json.get('keyboard_folder', 'Unknown')) cli.echo('{fg_blue}Layouts{fg_reset}: %s', ', '.join(sorted(kb_info_json['layouts'].keys()))) if 'width' in kb_info_json and 'height' in kb_info_json: cli.echo('{fg_blue}Size{fg_reset}: %s x %s' % (kb_info_json['width'], kb_info_json['height'])) cli.echo('{fg_blue}Processor{fg_reset}: %s', kb_info_json.get('processor', 'Unknown')) cli.echo('{fg_blue}Bootloader{fg_reset}: %s', kb_info_json.get('bootloader', 'Unknown')) if cli.config.info.layouts: show_layouts(kb_info_json, True) if cli.config.info.matrix: show_matrix(kb_info_json, True) if cli.config_source.info.keymap and cli.config_source.info.keymap != 'config_file': show_keymap(kb_info_json, True) else: cli.log.error('Unknown format: %s', cli.args.format)
def find_keyboard_keymap(): """Returns `(keyboard_name, keymap_name)` based on the user's current environment. This determines the keyboard and keymap name using the following precedence order: * Command line flags (--keyboard and --keymap) * Current working directory * `keyboards/<keyboard_name>` * `keyboards/<keyboard_name>/keymaps/<keymap_name>` * `layouts/**/<keymap_name>` * `users/<keymap_name>` * Configuration * cli.config.<subcommand>.keyboard * cli.config.<subcommand>.keymap """ # Check to make sure their copy of MILC supports config_source if not hasattr(cli, 'config_source'): cli.log.error( "Your QMK CLI is out of date. Please upgrade using pip3 or your package manager." ) exit(1) # State variables relative_cwd = under_qmk_firmware() keyboard_name = "" keymap_name = "" # If the keyboard or keymap are passed as arguments use that in preference to anything else if cli.config_source[cli._entrypoint.__name__]['keyboard'] == 'argument': keyboard_name = cli.config[cli._entrypoint.__name__]['keyboard'] if cli.config_source[cli._entrypoint.__name__]['keymap'] == 'argument': keymap_name = cli.config[cli._entrypoint.__name__]['keymap'] if not keyboard_name or not keymap_name: # If we don't have a keyboard_name and keymap_name from arguments try to derive one or both if relative_cwd and relative_cwd.parts and relative_cwd.parts[ 0] == 'keyboards': # Try to determine the keyboard and/or keymap name current_path = Path('/'.join(relative_cwd.parts[1:])) if current_path.parts[-2] == 'keymaps': if not keymap_name: keymap_name = current_path.parts[-1] if not keyboard_name: keyboard_name = '/'.join(current_path.parts[:-2]) elif not keyboard_name and is_keyboard(current_path): keyboard_name = str(current_path) elif relative_cwd and relative_cwd.parts and relative_cwd.parts[ 0] == 'layouts': # Try to determine the keymap name from the community layout if is_keymap_dir(relative_cwd) and not keymap_name: keymap_name = relative_cwd.name elif relative_cwd and relative_cwd.parts and relative_cwd.parts[ 0] == 'users': # Try to determine the keymap name based on which userspace they're in if not keymap_name and len(relative_cwd.parts) > 1: keymap_name = relative_cwd.parts[1] # If we still don't have a keyboard and keymap check the config if not keyboard_name and cli.config[cli._entrypoint.__name__]['keyboard']: keyboard_name = cli.config[cli._entrypoint.__name__]['keyboard'] if not keymap_name and cli.config[cli._entrypoint.__name__]['keymap']: keymap_name = cli.config[cli._entrypoint.__name__]['keymap'] return (keyboard_name, keymap_name)
def generate_rules_mk(cli): """Generates a rules.mk file from info.json. """ # Determine our keyboard(s) if not cli.config.generate_rules_mk.keyboard: cli.log.error('Missing paramater: --keyboard') cli.subcommands['info'].print_help() return False if not is_keyboard(cli.config.generate_rules_mk.keyboard): cli.log.error('Invalid keyboard: "%s"', cli.config.generate_rules_mk.keyboard) return False # Build the info.json file kb_info_json = info_json(cli.config.generate_rules_mk.keyboard) rules_mk_lines = [ '# This file was generated by `qmk generate-rules-mk`. Do not edit or copy.', '' ] # Bring in settings for info_key, rule_key in info_to_rules.items(): if info_key in kb_info_json: rules_mk_lines.append(f'{rule_key} ?= {kb_info_json[info_key]}') # Find features that should be enabled 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 the LED driver if 'led_matrix' in kb_info_json and 'driver' in kb_info_json['led_matrix']: driver = kb_info_json['led_matrix']['driver'] rules_mk_lines.append(f'LED_MATRIX_DRIVER ?= {driver}') # Add community layouts if 'community_layouts' in kb_info_json: rules_mk_lines.append( f'LAYOUTS ?= {" ".join(kb_info_json["community_layouts"])}') # 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.name + '.bak') cli.args.output.write_text(rules_mk) if cli.args.quiet: print(cli.args.output) else: cli.log.info('Wrote info_config.h to %s.', cli.args.output) else: print(rules_mk)
def generate_config_h(cli): """Generates the info_config.h file. """ # Determine our keyboard(s) if not cli.config.generate_config_h.keyboard: cli.log.error('Missing parameter: --keyboard') cli.subcommands['info'].print_help() return False if not is_keyboard(cli.config.generate_config_h.keyboard): cli.log.error('Invalid keyboard: "%s"', cli.config.generate_config_h.keyboard) return False # Build the info_config.h file. kb_info_json = dotty(info_json(cli.config.generate_config_h.keyboard)) info_config_map = json_load(Path('data/mappings/info_config.json')) config_h_lines = [ '/* This file was generated by `qmk generate-config-h`. Do not edit or copy.' ' */', '', '#pragma once' ] # Iterate through the info_config map to generate basic things for config_key, info_dict in info_config_map.items(): info_key = info_dict['info_key'] key_type = info_dict.get('value_type', 'str') to_config = info_dict.get('to_config', True) if not to_config: continue try: config_value = kb_info_json[info_key] except KeyError: continue if key_type.startswith('array'): config_h_lines.append('') config_h_lines.append(f'#ifndef {config_key}') config_h_lines.append( f'# define {config_key} {{ {", ".join(map(str, config_value))} }}' ) config_h_lines.append(f'#endif // {config_key}') elif key_type == 'bool': if config_value: config_h_lines.append('') config_h_lines.append(f'#ifndef {config_key}') config_h_lines.append(f'# define {config_key}') config_h_lines.append(f'#endif // {config_key}') elif key_type == 'mapping': for key, value in config_value.items(): config_h_lines.append('') config_h_lines.append(f'#ifndef {key}') config_h_lines.append(f'# define {key} {value}') config_h_lines.append(f'#endif // {key}') else: config_h_lines.append('') config_h_lines.append(f'#ifndef {config_key}') config_h_lines.append(f'# define {config_key} {config_value}') config_h_lines.append(f'#endif // {config_key}') if 'matrix_pins' in kb_info_json: config_h_lines.append(matrix_pins(kb_info_json['matrix_pins'])) # 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 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 presidence.') 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 # Gather data about the keyboard. ok = True keyboard_path = keyboard(kb) keyboard_info = info_json(kb) # Check for errors in the info.json if keyboard_info['parse_errors']: ok = False cli.log.error('%s: Errors found when generating info.json.', kb) if cli.config.lint.strict and keyboard_info['parse_warnings']: ok = False cli.log.error('%s: Warnings found when generating info.json (Strict mode enabled.)', kb) # Check the rules.mk file(s) rules_mk_assignment_errors = rules_mk_assignment_only(keyboard_path) if rules_mk_assignment_errors: ok = False cli.log.error('%s: Non-assignment code found in rules.mk. Move it to post_rules.mk instead.', kb) for assignment_error in rules_mk_assignment_errors: cli.log.error(assignment_error) # Keymap specific checks if cli.config.lint.keymap: if not keymap_check(kb, cli.config.lint.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