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.

100 lines
2.6 KiB

  1. """Functions that help you work with QMK keymaps.
  2. """
  3. import json
  4. import logging
  5. import os
  6. from traceback import format_exc
  7. import qmk.path
  8. from qmk.errors import NoSuchKeyboardError
  9. # The `keymap.c` template to use when a keyboard doesn't have its own
  10. DEFAULT_KEYMAP_C = """#include QMK_KEYBOARD_H
  11. /* THIS FILE WAS GENERATED!
  12. *
  13. * This file was generated by qmk-compile-json. You may or may not want to
  14. * edit it directly.
  15. */
  16. const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  17. __KEYMAP_GOES_HERE__
  18. };
  19. """
  20. def template(keyboard):
  21. """Returns the `keymap.c` template for a keyboard.
  22. If a template exists in `keyboards/<keyboard>/templates/keymap.c` that
  23. text will be used instead of `DEFAULT_KEYMAP_C`.
  24. Args:
  25. keyboard
  26. The keyboard to return a template for.
  27. """
  28. template_name = 'keyboards/%s/templates/keymap.c' % keyboard
  29. if os.path.exists(template_name):
  30. with open(template_name, 'r') as fd:
  31. return fd.read()
  32. return DEFAULT_KEYMAP_C
  33. def generate(keyboard, layout, layers):
  34. """Returns a keymap.c for the specified keyboard, layout, and layers.
  35. Args:
  36. keyboard
  37. The name of the keyboard
  38. layout
  39. The LAYOUT macro this keymap uses.
  40. layers
  41. An array of arrays describing the keymap. Each item in the inner array should be a string that is a valid QMK keycode.
  42. """
  43. layer_txt = []
  44. for layer_num, layer in enumerate(layers):
  45. if layer_num != 0:
  46. layer_txt[-1] = layer_txt[-1] + ','
  47. layer_keys = ', '.join(layer)
  48. layer_txt.append('\t[%s] = %s(%s)' % (layer_num, layout, layer_keys))
  49. keymap = '\n'.join(layer_txt)
  50. keymap_c = template(keyboard)
  51. return keymap_c.replace('__KEYMAP_GOES_HERE__', keymap)
  52. def write(keyboard, keymap, layout, layers):
  53. """Generate the `keymap.c` and write it to disk.
  54. Returns the filename written to.
  55. Args:
  56. keyboard
  57. The name of the keyboard
  58. keymap
  59. The name of the keymap
  60. layout
  61. The LAYOUT macro this keymap uses.
  62. layers
  63. An array of arrays describing the keymap. Each item in the inner array should be a string that is a valid QMK keycode.
  64. """
  65. keymap_c = generate(keyboard, layout, layers)
  66. keymap_path = qmk.path.keymap(keyboard)
  67. keymap_dir = os.path.join(keymap_path, keymap)
  68. keymap_file = os.path.join(keymap_dir, 'keymap.c')
  69. if not os.path.exists(keymap_dir):
  70. os.makedirs(keymap_dir)
  71. with open(keymap_file, 'w') as keymap_fd:
  72. keymap_fd.write(keymap_c)
  73. return keymap_file