diff options
Diffstat (limited to 'lib/python')
| -rwxr-xr-x | lib/python/qmk/cli/generate/api.py | 9 | ||||
| -rw-r--r-- | lib/python/qmk/cli/generate/keycodes.py | 54 | ||||
| -rw-r--r-- | lib/python/qmk/keycodes.py | 73 | 
3 files changed, 117 insertions, 19 deletions
| diff --git a/lib/python/qmk/cli/generate/api.py b/lib/python/qmk/cli/generate/api.py index 8650a36b84..dd4830f543 100755 --- a/lib/python/qmk/cli/generate/api.py +++ b/lib/python/qmk/cli/generate/api.py @@ -11,7 +11,7 @@ from qmk.info import info_json  from qmk.json_encoders import InfoJSONEncoder  from qmk.json_schema import json_load  from qmk.keyboard import find_readme, list_keyboards -from qmk.keycodes import load_spec, list_versions +from qmk.keycodes import load_spec, list_versions, list_languages  DATA_PATH = Path('data')  TEMPLATE_PATH = DATA_PATH / 'templates/api/' @@ -44,6 +44,13 @@ def _resolve_keycode_specs(output_folder):          output_file = output_folder / f'constants/keycodes_{version}.json'          output_file.write_text(json.dumps(overall, indent=4), encoding='utf-8') +    for lang in list_languages(): +        for version in list_versions(lang): +            overall = load_spec(version, lang) + +            output_file = output_folder / f'constants/keycodes_{lang}_{version}.json' +            output_file.write_text(json.dumps(overall, indent=4), encoding='utf-8') +      # Purge files consumed by 'load_spec'      shutil.rmtree(output_folder / 'constants/keycodes/') diff --git a/lib/python/qmk/cli/generate/keycodes.py b/lib/python/qmk/cli/generate/keycodes.py index 29b7db3c80..cf80689708 100644 --- a/lib/python/qmk/cli/generate/keycodes.py +++ b/lib/python/qmk/cli/generate/keycodes.py @@ -8,6 +8,24 @@ from qmk.path import normpath  from qmk.keycodes import load_spec +def _render_key(key): +    width = 7 +    if 'S(' in key: +        width += len('S()') +    if 'A(' in key: +        width += len('A()') +    if 'RCTL(' in key: +        width += len('RCTL()') +    if 'ALGR(' in key: +        width += len('ALGR()') +    return key.ljust(width) + + +def _render_label(label): +    label = label.replace("\\", "(backslash)") +    return label + +  def _generate_ranges(lines, keycodes):      lines.append('')      lines.append('enum qk_keycode_ranges {') @@ -67,6 +85,22 @@ def _generate_helpers(lines, keycodes):          lines.append(f'#define IS_{ group.upper() }_KEYCODE(code) ((code) >= {lo} && (code) <= {hi})') +def _generate_aliases(lines, keycodes): +    lines.append('') +    lines.append('// Aliases') +    for key, value in keycodes["aliases"].items(): +        define = _render_key(value.get("key")) +        val = _render_key(key) +        label = _render_label(value.get("label")) + +        lines.append(f'#define {define} {val} // {label}') + +    lines.append('') +    for key, value in keycodes["aliases"].items(): +        for alias in value.get("aliases", []): +            lines.append(f'#define {alias} {value.get("key")}') + +  @cli.argument('-v', '--version', arg_only=True, required=True, help='Version of keycodes to generate.')  @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") @@ -86,3 +120,23 @@ def generate_keycodes(cli):      # Show the results      dump_lines(cli.args.output, keycodes_h_lines, cli.args.quiet) + + [email protected]('-v', '--version', arg_only=True, required=True, help='Version of keycodes to generate.') [email protected]('-l', '--lang', arg_only=True, required=True, help='Language of keycodes to generate.') [email protected]('-o', '--output', arg_only=True, type=normpath, help='File to write to') [email protected]('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") [email protected]('Used by the make system to generate keymap_{lang}.h from keycodes_{lang}_{version}.json', hidden=True) +def generate_keycode_extras(cli): +    """Generates the header file. +    """ + +    # Build the header file. +    keycodes_h_lines = [GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE, '#pragma once', '#include "keymap.h"', '// clang-format off'] + +    keycodes = load_spec(cli.args.version, cli.args.lang) + +    _generate_aliases(keycodes_h_lines, keycodes) + +    # Show the results +    dump_lines(cli.args.output, keycodes_h_lines, cli.args.quiet) diff --git a/lib/python/qmk/keycodes.py b/lib/python/qmk/keycodes.py index cf1ee0767a..600163bab9 100644 --- a/lib/python/qmk/keycodes.py +++ b/lib/python/qmk/keycodes.py @@ -2,7 +2,42 @@ from pathlib import Path  from qmk.json_schema import deep_update, json_load, validate -CONSTANTS_PATH = Path('data/constants/keycodes/') +CONSTANTS_PATH = Path('data/constants/') +KEYCODES_PATH = CONSTANTS_PATH / 'keycodes' +EXTRAS_PATH = KEYCODES_PATH / 'extras' + + +def _find_versions(path, prefix): +    ret = [] +    for file in path.glob(f'{prefix}_[0-9].[0-9].[0-9].hjson'): +        ret.append(file.stem.split('_')[-1]) + +    ret.sort(reverse=True) +    return ret + + +def _load_fragments(path, prefix, version): +    file = path / f'{prefix}_{version}.hjson' +    if not file.exists(): +        raise ValueError(f'Requested keycode spec ({prefix}:{version}) is invalid!') + +    # Load base +    spec = json_load(file) + +    # Merge in fragments +    fragments = path.glob(f'{prefix}_{version}_*.hjson') +    for file in fragments: +        deep_update(spec, json_load(file)) + +    return spec + + +def _search_path(lang=None): +    return EXTRAS_PATH if lang else KEYCODES_PATH + + +def _search_prefix(lang=None): +    return f'keycodes_{lang}' if lang else 'keycodes'  def _validate(spec): @@ -19,26 +54,20 @@ def _validate(spec):          raise ValueError(f'Keycode spec contains duplicate keycodes! ({",".join(duplicates)})') -def load_spec(version): +def load_spec(version, lang=None):      """Build keycode data from the requested spec file      """      if version == 'latest': -        version = list_versions()[0] +        version = list_versions(lang)[0] -    file = CONSTANTS_PATH / f'keycodes_{version}.hjson' -    if not file.exists(): -        raise ValueError(f'Requested keycode spec ({version}) is invalid!') +    path = _search_path(lang) +    prefix = _search_prefix(lang)      # Load base -    spec = json_load(file) - -    # Merge in fragments -    fragments = CONSTANTS_PATH.glob(f'keycodes_{version}_*.hjson') -    for file in fragments: -        deep_update(spec, json_load(file)) +    spec = _load_fragments(path, prefix, version)      # Sort? -    spec['keycodes'] = dict(sorted(spec['keycodes'].items())) +    spec['keycodes'] = dict(sorted(spec.get('keycodes', {}).items()))      # Validate?      _validate(spec) @@ -46,12 +75,20 @@ def load_spec(version):      return spec -def list_versions(): +def list_versions(lang=None):      """Return available versions - sorted newest first      """ -    ret = [] -    for file in CONSTANTS_PATH.glob('keycodes_[0-9].[0-9].[0-9].hjson'): -        ret.append(file.stem.split('_')[1]) +    path = _search_path(lang) +    prefix = _search_prefix(lang) + +    return _find_versions(path, prefix) + + +def list_languages(): +    """Return available languages +    """ +    ret = set() +    for file in EXTRAS_PATH.glob('keycodes_*_[0-9].[0-9].[0-9].hjson'): +        ret.add(file.stem.split('_')[1]) -    ret.sort(reverse=True)      return ret | 
