kle2json.py 2.8 KB

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