You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
4.1 KiB

  1. """Used by the make system to generate layouts.h from info.json.
  2. """
  3. from milc import cli
  4. from qmk.constants import COL_LETTERS, ROW_LETTERS
  5. from qmk.decorators import automagic_keyboard, automagic_keymap
  6. from qmk.info import info_json
  7. from qmk.keyboard import keyboard_completer, keyboard_folder
  8. from qmk.path import is_keyboard, normpath
  9. usb_properties = {
  10. 'vid': 'VENDOR_ID',
  11. 'pid': 'PRODUCT_ID',
  12. 'device_ver': 'DEVICE_VER',
  13. }
  14. @cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to')
  15. @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
  16. @cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate config.h for.')
  17. @cli.subcommand('Used by the make system to generate layouts.h from info.json', hidden=True)
  18. @automagic_keyboard
  19. @automagic_keymap
  20. def generate_layouts(cli):
  21. """Generates the layouts.h file.
  22. """
  23. # Determine our keyboard(s)
  24. if not cli.config.generate_layouts.keyboard:
  25. cli.log.error('Missing parameter: --keyboard')
  26. cli.subcommands['info'].print_help()
  27. return False
  28. if not is_keyboard(cli.config.generate_layouts.keyboard):
  29. cli.log.error('Invalid keyboard: "%s"', cli.config.generate_layouts.keyboard)
  30. return False
  31. # Build the info.json file
  32. kb_info_json = info_json(cli.config.generate_layouts.keyboard)
  33. # Build the layouts.h file.
  34. layouts_h_lines = ['/* This file was generated by `qmk generate-layouts`. Do not edit or copy.' ' */', '', '#pragma once']
  35. if 'matrix_pins' in kb_info_json:
  36. if 'direct' in kb_info_json['matrix_pins']:
  37. col_num = len(kb_info_json['matrix_pins']['direct'][0])
  38. row_num = len(kb_info_json['matrix_pins']['direct'])
  39. elif 'cols' in kb_info_json['matrix_pins'] and 'rows' in kb_info_json['matrix_pins']:
  40. col_num = len(kb_info_json['matrix_pins']['cols'])
  41. row_num = len(kb_info_json['matrix_pins']['rows'])
  42. else:
  43. cli.log.error('%s: Invalid matrix config.', cli.config.generate_layouts.keyboard)
  44. return False
  45. for layout_name in kb_info_json['layouts']:
  46. if kb_info_json['layouts'][layout_name]['c_macro']:
  47. continue
  48. if 'matrix' not in kb_info_json['layouts'][layout_name]['layout'][0]:
  49. cli.log.debug('%s/%s: No matrix data!', cli.config.generate_layouts.keyboard, layout_name)
  50. continue
  51. layout_keys = []
  52. layout_matrix = [['KC_NO' for i in range(col_num)] for i in range(row_num)]
  53. for i, key in enumerate(kb_info_json['layouts'][layout_name]['layout']):
  54. row = key['matrix'][0]
  55. col = key['matrix'][1]
  56. identifier = 'k%s%s' % (ROW_LETTERS[row], COL_LETTERS[col])
  57. try:
  58. layout_matrix[row][col] = identifier
  59. layout_keys.append(identifier)
  60. except IndexError:
  61. key_name = key.get('label', identifier)
  62. cli.log.error('Matrix data out of bounds for layout %s at index %s (%s): %s, %s', layout_name, i, key_name, row, col)
  63. return False
  64. layouts_h_lines.append('')
  65. layouts_h_lines.append('#define %s(%s) {\\' % (layout_name, ', '.join(layout_keys)))
  66. rows = ', \\\n'.join(['\t {' + ', '.join(row) + '}' for row in layout_matrix])
  67. rows += ' \\'
  68. layouts_h_lines.append(rows)
  69. layouts_h_lines.append('}')
  70. for alias, target in kb_info_json.get('layout_aliases', {}).items():
  71. layouts_h_lines.append('')
  72. layouts_h_lines.append('#define %s %s' % (alias, target))
  73. # Show the results
  74. layouts_h = '\n'.join(layouts_h_lines) + '\n'
  75. if cli.args.output:
  76. cli.args.output.parent.mkdir(parents=True, exist_ok=True)
  77. if cli.args.output.exists():
  78. cli.args.output.replace(cli.args.output.parent / (cli.args.output.name + '.bak'))
  79. cli.args.output.write_text(layouts_h)
  80. if not cli.args.quiet:
  81. cli.log.info('Wrote info_config.h to %s.', cli.args.output)
  82. else:
  83. print(layouts_h)