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.

75 lines
2.8 KiB

  1. """Convert raw KLE to JSON
  2. """
  3. import json
  4. import os
  5. from pathlib import Path
  6. from decimal import Decimal
  7. from collections import OrderedDict
  8. from milc import cli
  9. from kle2xy import KLE2xy
  10. from qmk.converter import kle2qmk
  11. class CustomJSONEncoder(json.JSONEncoder):
  12. def default(self, obj):
  13. try:
  14. if isinstance(obj, Decimal):
  15. if obj % 2 in (Decimal(0), Decimal(1)):
  16. return int(obj)
  17. return float(obj)
  18. except TypeError:
  19. pass
  20. return json.JSONEncoder.default(self, obj)
  21. @cli.argument('filename', help='The KLE raw txt to convert')
  22. @cli.argument('-f', '--force', action='store_true', help='Flag to overwrite current info.json')
  23. @cli.subcommand('Convert a KLE layout to a Configurator JSON')
  24. def kle2json(cli):
  25. """Convert a KLE layout to QMK's layout format.
  26. """ # If filename is a path
  27. if cli.args.filename.startswith("/") or cli.args.filename.startswith("./"):
  28. file_path = Path(cli.args.filename)
  29. # Otherwise assume it is a file name
  30. else:
  31. file_path = Path(os.environ['ORIG_CWD'], cli.args.filename)
  32. # Check for valid file_path for more graceful failure
  33. if not file_path.exists():
  34. return cli.log.error('File {fg_cyan}%s{style_reset_all} was not found.', str(file_path))
  35. out_path = file_path.parent
  36. raw_code = file_path.open().read()
  37. # Check if info.json exists, allow overwrite with force
  38. if Path(out_path, "info.json").exists() and not cli.args.force:
  39. cli.log.error('File {fg_cyan}%s/info.json{style_reset_all} already exists, use -f or --force to overwrite.', str(out_path))
  40. return False
  41. try:
  42. # Convert KLE raw to x/y coordinates (using kle2xy package from skullydazed)
  43. kle = KLE2xy(raw_code)
  44. except Exception as e:
  45. cli.log.error('Could not parse KLE raw data: %s', raw_code)
  46. cli.log.exception(e)
  47. # FIXME: This should be better
  48. return cli.log.error('Could not parse KLE raw data.')
  49. keyboard = OrderedDict(
  50. keyboard_name=kle.name,
  51. url='',
  52. maintainer='qmk',
  53. width=kle.columns,
  54. height=kle.rows,
  55. layouts={'LAYOUT': {
  56. 'layout': 'LAYOUT_JSON_HERE'
  57. }},
  58. )
  59. # Initialize keyboard with json encoded from ordered dict
  60. keyboard = json.dumps(keyboard, indent=4, separators=(', ', ': '), sort_keys=False, cls=CustomJSONEncoder)
  61. # Initialize layout with kle2qmk from converter module
  62. layout = json.dumps(kle2qmk(kle), separators=(', ', ':'), cls=CustomJSONEncoder)
  63. # Replace layout in keyboard json
  64. keyboard = keyboard.replace('"LAYOUT_JSON_HERE"', layout)
  65. # Write our info.json
  66. file = open(str(out_path) + "/info.json", "w")
  67. file.write(keyboard)
  68. file.close()
  69. cli.log.info('Wrote out {fg_cyan}%s/info.json', str(out_path))