diff options
Diffstat (limited to 'lib/python/qmk')
| -rw-r--r-- | lib/python/qmk/cli/__init__.py | 1 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/generate/keyboard_h.py | 69 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/generate/layouts.py | 84 | ||||
| -rw-r--r-- | lib/python/qmk/tests/test_cli_commands.py | 6 | 
4 files changed, 59 insertions, 101 deletions
| diff --git a/lib/python/qmk/cli/__init__.py b/lib/python/qmk/cli/__init__.py index 02561da1fb..cf5b5ad87e 100644 --- a/lib/python/qmk/cli/__init__.py +++ b/lib/python/qmk/cli/__init__.py @@ -56,7 +56,6 @@ subcommands = [      'qmk.cli.generate.info_json',      'qmk.cli.generate.keyboard_c',      'qmk.cli.generate.keyboard_h', -    'qmk.cli.generate.layouts',      'qmk.cli.generate.rgb_breathe_table',      'qmk.cli.generate.rules_mk',      'qmk.cli.generate.version_h', diff --git a/lib/python/qmk/cli/generate/keyboard_h.py b/lib/python/qmk/cli/generate/keyboard_h.py index 54ddb4cffd..910bd6a08d 100755 --- a/lib/python/qmk/cli/generate/keyboard_h.py +++ b/lib/python/qmk/cli/generate/keyboard_h.py @@ -1,33 +1,72 @@  """Used by the make system to generate keyboard.h from info.json.  """ +from pathlib import Path +  from milc import cli +from qmk.path import normpath  from qmk.info import info_json  from qmk.commands import dump_lines  from qmk.keyboard import keyboard_completer, keyboard_folder -from qmk.path import normpath -from qmk.constants import GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE +from qmk.constants import COL_LETTERS, ROW_LETTERS, GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE -def would_populate_layout_h(keyboard): -    """Detect if a given keyboard is doing data driven layouts +def _generate_layouts(keyboard): +    """Generates the layouts.h file.      """      # Build the info.json file      kb_info_json = info_json(keyboard) +    if 'matrix_size' not in kb_info_json: +        cli.log.error(f'{keyboard}: Invalid matrix config.') +        return [] + +    col_num = kb_info_json['matrix_size']['cols'] +    row_num = kb_info_json['matrix_size']['rows'] + +    lines = []      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!', keyboard, layout_name) +            cli.log.debug(f'{keyboard}/{layout_name}: No matrix data!')              continue -        return True +        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]) -    return False +            try: +                layout_matrix[row][col] = identifier +                layout_keys.append(identifier) +            except IndexError: +                key_name = key.get('label', identifier) +                cli.log.error(f'Matrix data out of bounds for layout {layout_name} at index {i} ({key_name}): [{row}, {col}]') +                return [] +        lines.append('') +        lines.append('#define %s(%s) {\\' % (layout_name, ', '.join(layout_keys))) +        rows = ', \\\n'.join(['\t {' + ', '.join(row) + '}' for row in layout_matrix]) +        rows += ' \\' +        lines.append(rows) +        lines.append('}') + +    for alias, target in kb_info_json.get('layout_aliases', {}).items(): +        lines.append('') +        lines.append(f'#ifndef {alias}') +        lines.append(f'#   define {alias} {target}') +        lines.append('#endif') + +    return lines + + +@cli.argument('-i', '--include', nargs='?', arg_only=True, help='Optional file to include')  @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.h for.') @@ -35,13 +74,23 @@ def would_populate_layout_h(keyboard):  def generate_keyboard_h(cli):      """Generates the keyboard.h file.      """ -    has_layout_h = would_populate_layout_h(cli.args.keyboard) +    keyboard_h = cli.args.include +    dd_layouts = _generate_layouts(cli.args.keyboard) +    valid_config = dd_layouts or keyboard_h      # Build the layouts.h file.      keyboard_h_lines = [GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE, '#pragma once', '#include "quantum.h"'] -    if not has_layout_h: -        keyboard_h_lines.append('#error("<keyboard>.h is only optional for data driven keyboards - kb.h == bad times")') +    keyboard_h_lines.append('') +    keyboard_h_lines.append('// Layout content') +    if dd_layouts: +        keyboard_h_lines.extend(dd_layouts) +    if keyboard_h: +        keyboard_h_lines.append(f'#include "{Path(keyboard_h).name}"') + +    # Protect against poorly configured keyboards +    if not valid_config: +        keyboard_h_lines.append('#error("<keyboard>.h is required unless your keyboard uses data-driven configuration. Please rename your keyboard\'s header file to <keyboard>.h")')      # Show the results      dump_lines(cli.args.output, keyboard_h_lines, cli.args.quiet) diff --git a/lib/python/qmk/cli/generate/layouts.py b/lib/python/qmk/cli/generate/layouts.py deleted file mode 100755 index 8336f36b50..0000000000 --- a/lib/python/qmk/cli/generate/layouts.py +++ /dev/null @@ -1,84 +0,0 @@ -"""Used by the make system to generate layouts.h from info.json. -""" -from milc import cli - -from qmk.constants import COL_LETTERS, ROW_LETTERS, GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE -from qmk.decorators import automagic_keyboard, automagic_keymap -from qmk.info import info_json -from qmk.keyboard import keyboard_completer, keyboard_folder -from qmk.path import is_keyboard, normpath -from qmk.commands import dump_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', type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate config.h for.') -@cli.subcommand('Used by the make system to generate layouts.h from info.json', hidden=True) -@automagic_keyboard -@automagic_keymap -def generate_layouts(cli): -    """Generates the layouts.h file. -    """ -    # Determine our keyboard(s) -    if not cli.config.generate_layouts.keyboard: -        cli.log.error('Missing parameter: --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 = [GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE, '#pragma once'] - -    if 'matrix_size' not in kb_info_json: -        cli.log.error('%s: Invalid matrix config.', cli.config.generate_layouts.keyboard) -        return False - -    col_num = kb_info_json['matrix_size']['cols'] -    row_num = kb_info_json['matrix_size']['rows'] - -    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('}') - -    for alias, target in kb_info_json.get('layout_aliases', {}).items(): -        layouts_h_lines.append('') -        layouts_h_lines.append(f'#ifndef {alias}') -        layouts_h_lines.append(f'#   define {alias} {target}') -        layouts_h_lines.append('#endif') - -    # Show the results -    dump_lines(cli.args.output, layouts_h_lines, cli.args.quiet) diff --git a/lib/python/qmk/tests/test_cli_commands.py b/lib/python/qmk/tests/test_cli_commands.py index 185abb5f21..c8c4e2f80c 100644 --- a/lib/python/qmk/tests/test_cli_commands.py +++ b/lib/python/qmk/tests/test_cli_commands.py @@ -288,12 +288,6 @@ def test_generate_version_h():      assert '#define QMK_VERSION' in result.stdout -def test_generate_layouts(): -    result = check_subcommand('generate-layouts', '-kb', 'handwired/pytest/basic') -    check_returncode(result) -    assert '#define LAYOUT_custom(k0A) {' in result.stdout - -  def test_format_json_keyboard():      result = check_subcommand('format-json', '--format', 'keyboard', 'lib/python/qmk/tests/minimal_info.json')      check_returncode(result) | 
