summaryrefslogtreecommitdiff
path: root/lib/python/qmk/cli/generate
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python/qmk/cli/generate')
-rwxr-xr-xlib/python/qmk/cli/generate/config_h.py143
-rwxr-xr-xlib/python/qmk/cli/generate/info_json.py40
-rwxr-xr-xlib/python/qmk/cli/generate/keyboard_h.py7
-rwxr-xr-xlib/python/qmk/cli/generate/rules_mk.py41
-rw-r--r--lib/python/qmk/cli/generate/version_h.py28
5 files changed, 182 insertions, 77 deletions
diff --git a/lib/python/qmk/cli/generate/config_h.py b/lib/python/qmk/cli/generate/config_h.py
index 54cd5b96a8..ca7e14fe6b 100755
--- a/lib/python/qmk/cli/generate/config_h.py
+++ b/lib/python/qmk/cli/generate/config_h.py
@@ -5,14 +5,14 @@ from pathlib import Path
from dotty_dict import dotty
from milc import cli
-from qmk.decorators import automagic_keyboard, automagic_keymap
from qmk.info import info_json
-from qmk.json_schema import json_load
+from qmk.json_schema import json_load, validate
from qmk.keyboard import keyboard_completer, keyboard_folder
-from qmk.path import is_keyboard, normpath
+from qmk.keymap import locate_keymap
+from qmk.path import normpath
-def direct_pins(direct_pins):
+def direct_pins(direct_pins, postfix):
"""Return the config.h lines that set the direct pins.
"""
rows = []
@@ -24,81 +24,60 @@ def direct_pins(direct_pins):
col_count = len(direct_pins[0])
row_count = len(direct_pins)
- return """
-#ifndef MATRIX_COLS
-# define MATRIX_COLS %s
-#endif // MATRIX_COLS
+ return f"""
+#ifndef MATRIX_COLS{postfix}
+# define MATRIX_COLS{postfix} {col_count}
+#endif // MATRIX_COLS{postfix}
-#ifndef MATRIX_ROWS
-# define MATRIX_ROWS %s
-#endif // MATRIX_ROWS
+#ifndef MATRIX_ROWS{postfix}
+# define MATRIX_ROWS{postfix} {row_count}
+#endif // MATRIX_ROWS{postfix}
-#ifndef DIRECT_PINS
-# define DIRECT_PINS {%s}
-#endif // DIRECT_PINS
-""" % (col_count, row_count, ','.join(rows))
+#ifndef DIRECT_PINS{postfix}
+# define DIRECT_PINS{postfix} {{ {", ".join(rows)} }}
+#endif // DIRECT_PINS{postfix}
+"""
-def pin_array(define, pins):
+def pin_array(define, pins, postfix):
"""Return the config.h lines that set a pin array.
"""
pin_num = len(pins)
pin_array = ', '.join(map(str, [pin or 'NO_PIN' for pin in pins]))
return f"""
-#ifndef {define}S
-# define {define}S {pin_num}
-#endif // {define}S
+#ifndef {define}S{postfix}
+# define {define}S{postfix} {pin_num}
+#endif // {define}S{postfix}
-#ifndef {define}_PINS
-# define {define}_PINS {{ {pin_array} }}
-#endif // {define}_PINS
+#ifndef {define}_PINS{postfix}
+# define {define}_PINS{postfix} {{ {pin_array} }}
+#endif // {define}_PINS{postfix}
"""
-def matrix_pins(matrix_pins):
+def matrix_pins(matrix_pins, postfix=''):
"""Add the matrix config to the config.h.
"""
pins = []
if 'direct' in matrix_pins:
- pins.append(direct_pins(matrix_pins['direct']))
+ pins.append(direct_pins(matrix_pins['direct'], postfix))
if 'cols' in matrix_pins:
- pins.append(pin_array('MATRIX_COL', matrix_pins['cols']))
+ pins.append(pin_array('MATRIX_COL', matrix_pins['cols'], postfix))
if 'rows' in matrix_pins:
- pins.append(pin_array('MATRIX_ROW', matrix_pins['rows']))
+ pins.append(pin_array('MATRIX_ROW', matrix_pins['rows'], postfix))
return '\n'.join(pins)
-@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 info_config.h from info.json', hidden=True)
-@automagic_keyboard
-@automagic_keymap
-def generate_config_h(cli):
- """Generates the info_config.h file.
+def generate_config_items(kb_info_json, config_h_lines):
+ """Iterate through the info_config map to generate basic config values.
"""
- # Determine our keyboard(s)
- if not cli.config.generate_config_h.keyboard:
- cli.log.error('Missing parameter: --keyboard')
- cli.subcommands['info'].print_help()
- return False
-
- if not is_keyboard(cli.config.generate_config_h.keyboard):
- cli.log.error('Invalid keyboard: "%s"', cli.config.generate_config_h.keyboard)
- return False
-
- # Build the info_config.h file.
- kb_info_json = dotty(info_json(cli.config.generate_config_h.keyboard))
info_config_map = json_load(Path('data/mappings/info_config.json'))
- config_h_lines = ['/* This file was generated by `qmk generate-config-h`. Do not edit or copy.' ' */', '', '#pragma once']
-
- # Iterate through the info_config map to generate basic things
for config_key, info_dict in info_config_map.items():
info_key = info_dict['info_key']
key_type = info_dict.get('value_type', 'str')
@@ -135,9 +114,75 @@ def generate_config_h(cli):
config_h_lines.append(f'# define {config_key} {config_value}')
config_h_lines.append(f'#endif // {config_key}')
+
+def generate_split_config(kb_info_json, config_h_lines):
+ """Generate the config.h lines for split boards."""
+ if 'primary' in kb_info_json['split']:
+ if kb_info_json['split']['primary'] in ('left', 'right'):
+ config_h_lines.append('')
+ config_h_lines.append('#ifndef MASTER_LEFT')
+ config_h_lines.append('# ifndef MASTER_RIGHT')
+ if kb_info_json['split']['primary'] == 'left':
+ config_h_lines.append('# define MASTER_LEFT')
+ elif kb_info_json['split']['primary'] == 'right':
+ config_h_lines.append('# define MASTER_RIGHT')
+ config_h_lines.append('# endif // MASTER_RIGHT')
+ config_h_lines.append('#endif // MASTER_LEFT')
+ elif kb_info_json['split']['primary'] == 'pin':
+ config_h_lines.append('')
+ config_h_lines.append('#ifndef SPLIT_HAND_PIN')
+ config_h_lines.append('# define SPLIT_HAND_PIN')
+ config_h_lines.append('#endif // SPLIT_HAND_PIN')
+ elif kb_info_json['split']['primary'] == 'matrix_grid':
+ config_h_lines.append('')
+ config_h_lines.append('#ifndef SPLIT_HAND_MATRIX_GRID')
+ config_h_lines.append('# define SPLIT_HAND_MATRIX_GRID {%s}' % (','.join(kb_info_json["split"]["matrix_grid"],)))
+ config_h_lines.append('#endif // SPLIT_HAND_MATRIX_GRID')
+ elif kb_info_json['split']['primary'] == 'eeprom':
+ config_h_lines.append('')
+ config_h_lines.append('#ifndef EE_HANDS')
+ config_h_lines.append('# define EE_HANDS')
+ config_h_lines.append('#endif // EE_HANDS')
+
+ if 'protocol' in kb_info_json['split'].get('transport', {}):
+ if kb_info_json['split']['transport']['protocol'] == 'i2c':
+ config_h_lines.append('')
+ config_h_lines.append('#ifndef USE_I2C')
+ config_h_lines.append('# define USE_I2C')
+ config_h_lines.append('#endif // USE_I2C')
+
+ if 'right' in kb_info_json['split'].get('matrix_pins', {}):
+ config_h_lines.append(matrix_pins(kb_info_json['split']['matrix_pins']['right'], '_RIGHT'))
+
+
+@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 config.h for.')
+@cli.argument('-km', '--keymap', arg_only=True, help='Keymap to generate config.h for.')
+@cli.subcommand('Used by the make system to generate info_config.h from info.json', hidden=True)
+def generate_config_h(cli):
+ """Generates the info_config.h file.
+ """
+ # Determine our keyboard/keymap
+ if cli.args.keymap:
+ km = locate_keymap(cli.args.keyboard, cli.args.keymap)
+ km_json = json_load(km)
+ validate(km_json, 'qmk.keymap.v1')
+ kb_info_json = dotty(km_json.get('config', {}))
+ else:
+ kb_info_json = dotty(info_json(cli.args.keyboard))
+
+ # Build the info_config.h file.
+ config_h_lines = ['/* This file was generated by `qmk generate-config-h`. Do not edit or copy.' ' */', '', '#pragma once']
+
+ generate_config_items(kb_info_json, config_h_lines)
+
if 'matrix_pins' in kb_info_json:
config_h_lines.append(matrix_pins(kb_info_json['matrix_pins']))
+ if 'split' in kb_info_json:
+ generate_split_config(kb_info_json, config_h_lines)
+
# Show the results
config_h = '\n'.join(config_h_lines)
diff --git a/lib/python/qmk/cli/generate/info_json.py b/lib/python/qmk/cli/generate/info_json.py
index 8931b68b6f..284d1a8510 100755
--- a/lib/python/qmk/cli/generate/info_json.py
+++ b/lib/python/qmk/cli/generate/info_json.py
@@ -4,15 +4,17 @@ Compile an info.json for a particular keyboard and pretty-print it.
"""
import json
-from jsonschema import Draft7Validator, validators
+from argcomplete.completers import FilesCompleter
+from jsonschema import Draft7Validator, RefResolver, validators
from milc import cli
+from pathlib import Path
from qmk.decorators import automagic_keyboard, automagic_keymap
from qmk.info import info_json
from qmk.json_encoders import InfoJSONEncoder
-from qmk.json_schema import load_jsonschema
+from qmk.json_schema import compile_schema_store
from qmk.keyboard import keyboard_completer, keyboard_folder
-from qmk.path import is_keyboard
+from qmk.path import is_keyboard, normpath
def pruning_validator(validator_class):
@@ -34,15 +36,19 @@ def pruning_validator(validator_class):
def strip_info_json(kb_info_json):
"""Remove the API-only properties from the info.json.
"""
+ schema_store = compile_schema_store()
pruning_draft_7_validator = pruning_validator(Draft7Validator)
- schema = load_jsonschema('keyboard')
- validator = pruning_draft_7_validator(schema).validate
+ schema = schema_store['qmk.keyboard.v1']
+ resolver = RefResolver.from_schema(schema_store['qmk.keyboard.v1'], store=schema_store)
+ validator = pruning_draft_7_validator(schema, resolver=resolver).validate
return validator(kb_info_json)
@cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='Keyboard to show info for.')
@cli.argument('-km', '--keymap', help='Show the layers for a JSON keymap too.')
+@cli.argument('-o', '--output', arg_only=True, completer=FilesCompleter, help='Write the output the specified file, overwriting if necessary.')
+@cli.argument('-ow', '--overwrite', arg_only=True, action='store_true', help='Overwrite the existing info.json. (Overrides the location of --output)')
@cli.subcommand('Generate an info.json file for a keyboard.', hidden=False if cli.config.user.developer else True)
@automagic_keyboard
@automagic_keymap
@@ -59,9 +65,29 @@ def generate_info_json(cli):
cli.log.error('Invalid keyboard: "%s"', cli.config.generate_info_json.keyboard)
return False
+ if cli.args.overwrite:
+ output_path = (Path('keyboards') / cli.config.generate_info_json.keyboard / 'info.json').resolve()
+
+ if cli.args.output:
+ cli.log.warning('Overwriting user supplied --output with %s', output_path)
+
+ cli.args.output = output_path
+
# Build the info.json file
kb_info_json = info_json(cli.config.generate_info_json.keyboard)
strip_info_json(kb_info_json)
+ info_json_text = json.dumps(kb_info_json, indent=4, cls=InfoJSONEncoder)
+
+ if cli.args.output:
+ # Write to a file
+ output_path = normpath(cli.args.output)
+
+ if output_path.exists():
+ cli.log.warning('Overwriting output file %s', output_path)
+
+ output_path.write_text(info_json_text + '\n')
+ cli.log.info('Wrote info.json to %s.', output_path)
- # Display the results
- print(json.dumps(kb_info_json, indent=2, cls=InfoJSONEncoder))
+ else:
+ # Display the results
+ print(info_json_text)
diff --git a/lib/python/qmk/cli/generate/keyboard_h.py b/lib/python/qmk/cli/generate/keyboard_h.py
index 22500dbc91..c9d7f549b3 100755
--- a/lib/python/qmk/cli/generate/keyboard_h.py
+++ b/lib/python/qmk/cli/generate/keyboard_h.py
@@ -2,7 +2,6 @@
"""
from milc import cli
-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 normpath
@@ -29,14 +28,12 @@ def would_populate_layout_h(keyboard):
@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, required=True, help='Keyboard to generate keyboard.h for.')
+@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, required=True, help='Keyboard to generate keyboard.h for.')
@cli.subcommand('Used by the make system to generate keyboard.h from info.json', hidden=True)
-@automagic_keyboard
-@automagic_keymap
def generate_keyboard_h(cli):
"""Generates the keyboard.h file.
"""
- has_layout_h = would_populate_layout_h(cli.config.generate_keyboard_h.keyboard)
+ has_layout_h = would_populate_layout_h(cli.args.keyboard)
# Build the layouts.h file.
keyboard_h_lines = ['/* This file was generated by `qmk generate-keyboard-h`. Do not edit or copy.' ' */', '', '#pragma once', '#include "quantum.h"']
diff --git a/lib/python/qmk/cli/generate/rules_mk.py b/lib/python/qmk/cli/generate/rules_mk.py
index 41c94e16b5..cdf17dfbcb 100755
--- a/lib/python/qmk/cli/generate/rules_mk.py
+++ b/lib/python/qmk/cli/generate/rules_mk.py
@@ -5,11 +5,11 @@ from pathlib import Path
from dotty_dict import dotty
from milc import cli
-from qmk.decorators import automagic_keyboard, automagic_keymap
from qmk.info import info_json
-from qmk.json_schema import json_load
+from qmk.json_schema import json_load, validate
from qmk.keyboard import keyboard_completer, keyboard_folder
-from qmk.path import is_keyboard, normpath
+from qmk.keymap import locate_keymap
+from qmk.path import normpath
def process_mapping_rule(kb_info_json, rules_key, info_dict):
@@ -39,23 +39,21 @@ def process_mapping_rule(kb_info_json, rules_key, info_dict):
@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('-e', '--escape', arg_only=True, action='store_true', help="Escape spaces in quiet mode")
-@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 info_config.h from info.json', hidden=True)
-@automagic_keyboard
-@automagic_keymap
+@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, required=True, help='Keyboard to generate rules.mk for.')
+@cli.argument('-km', '--keymap', arg_only=True, help='Keymap to generate rules.mk for.')
+@cli.subcommand('Used by the make system to generate rules.mk from info.json', hidden=True)
def generate_rules_mk(cli):
"""Generates a rules.mk file from info.json.
"""
- if not cli.config.generate_rules_mk.keyboard:
- cli.log.error('Missing parameter: --keyboard')
- cli.subcommands['info'].print_help()
- return False
-
- if not is_keyboard(cli.config.generate_rules_mk.keyboard):
- cli.log.error('Invalid keyboard: "%s"', cli.config.generate_rules_mk.keyboard)
- return False
+ # Determine our keyboard/keymap
+ if cli.args.keymap:
+ km = locate_keymap(cli.args.keyboard, cli.args.keymap)
+ km_json = json_load(km)
+ validate(km_json, 'qmk.keymap.v1')
+ kb_info_json = dotty(km_json.get('config', {}))
+ else:
+ kb_info_json = dotty(info_json(cli.args.keyboard))
- kb_info_json = dotty(info_json(cli.config.generate_rules_mk.keyboard))
info_rules_map = json_load(Path('data/mappings/info_rules.json'))
rules_mk_lines = ['# This file was generated by `qmk generate-rules-mk`. Do not edit or copy.', '']
@@ -76,6 +74,17 @@ def generate_rules_mk(cli):
enabled = 'yes' if enabled else 'no'
rules_mk_lines.append(f'{feature}_ENABLE ?= {enabled}')
+ # Set SPLIT_TRANSPORT, if needed
+ if kb_info_json.get('split', {}).get('transport', {}).get('protocol') == 'custom':
+ rules_mk_lines.append('SPLIT_TRANSPORT ?= custom')
+
+ # Set CUSTOM_MATRIX, if needed
+ if kb_info_json.get('matrix_pins', {}).get('custom'):
+ if kb_info_json.get('matrix_pins', {}).get('custom_lite'):
+ rules_mk_lines.append('CUSTOM_MATRIX ?= lite')
+ else:
+ rules_mk_lines.append('CUSTOM_MATRIX ?= yes')
+
# Show the results
rules_mk = '\n'.join(rules_mk_lines) + '\n'
diff --git a/lib/python/qmk/cli/generate/version_h.py b/lib/python/qmk/cli/generate/version_h.py
new file mode 100644
index 0000000000..b8e52588c4
--- /dev/null
+++ b/lib/python/qmk/cli/generate/version_h.py
@@ -0,0 +1,28 @@
+"""Used by the make system to generate version.h for use in code.
+"""
+from milc import cli
+
+from qmk.commands import create_version_h
+from qmk.path import normpath
+
+
+@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('--skip-git', arg_only=True, action='store_true', help='Skip Git operations')
+@cli.argument('--skip-all', arg_only=True, action='store_true', help='Use placeholder values for all defines (implies --skip-git)')
+@cli.subcommand('Used by the make system to generate version.h for use in code', hidden=True)
+def generate_version_h(cli):
+ """Generates the version.h file.
+ """
+ if cli.args.skip_all:
+ cli.args.skip_git = True
+
+ version_h = create_version_h(cli.args.skip_git, cli.args.skip_all)
+
+ if cli.args.output:
+ cli.args.output.write_text(version_h)
+
+ if not cli.args.quiet:
+ cli.log.info('Wrote version.h to %s.', cli.args.output)
+ else:
+ print(version_h)