diff options
Diffstat (limited to 'lib/python')
| -rw-r--r-- | lib/python/qmk/cli/__init__.py | 14 | ||||
| -rw-r--r-- | lib/python/qmk/cli/c2json.py | 7 | ||||
| -rw-r--r-- | lib/python/qmk/cli/cformat.py | 3 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/compile.py | 10 | ||||
| -rw-r--r-- | lib/python/qmk/cli/flash.py | 7 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/generate/config_h.py | 4 | ||||
| -rw-r--r-- | lib/python/qmk/cli/generate/dfu_header.py | 3 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/generate/info_json.py | 4 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/generate/layouts.py | 4 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/generate/rules_mk.py | 4 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/info.py | 4 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/json2c.py | 3 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/kle2json.py | 3 | ||||
| -rw-r--r-- | lib/python/qmk/cli/lint.py | 3 | ||||
| -rw-r--r-- | lib/python/qmk/cli/list/keymaps.py | 4 | ||||
| -rwxr-xr-x | lib/python/qmk/cli/new/keymap.py | 4 | ||||
| -rw-r--r-- | lib/python/qmk/decorators.py | 60 | ||||
| -rw-r--r-- | lib/python/qmk/keyboard.py | 26 | ||||
| -rw-r--r-- | lib/python/qmk/keymap.py | 56 | 
19 files changed, 138 insertions, 85 deletions
| diff --git a/lib/python/qmk/cli/__init__.py b/lib/python/qmk/cli/__init__.py index 1349e68a9b..f7df908119 100644 --- a/lib/python/qmk/cli/__init__.py +++ b/lib/python/qmk/cli/__init__.py @@ -4,7 +4,7 @@ We list each subcommand here explicitly because all the reliable ways of searchi  """  import sys -from milc import cli +from milc import cli, __VERSION__  from . import c2json  from . import cformat @@ -47,5 +47,15 @@ from . import pytest  # void: 3.9  if sys.version_info[0] != 3 or sys.version_info[1] < 7: -    cli.log.error('Your Python is too old! Please upgrade to Python 3.7 or later.') +    print('Error: Your Python is too old! Please upgrade to Python 3.7 or later.') +    exit(127) + +milc_version = __VERSION__.split('.') + +if int(milc_version[0]) < 2 and int(milc_version[1]) < 3: +    from pathlib import Path + +    requirements = Path('requirements.txt').resolve() + +    print(f'Your MILC library is too old! Please upgrade: python3 -m pip install -U -r {str(requirements)}')      exit(127) diff --git a/lib/python/qmk/cli/c2json.py b/lib/python/qmk/cli/c2json.py index 1fa833b647..e66b0a1b58 100644 --- a/lib/python/qmk/cli/c2json.py +++ b/lib/python/qmk/cli/c2json.py @@ -2,20 +2,21 @@  """  import json +from argcomplete.completers import FilesCompleter  from milc import cli  import qmk.keymap  import qmk.path  from qmk.json_encoders import InfoJSONEncoder -from qmk.keyboard import keyboard_folder +from qmk.keyboard import keyboard_completer, keyboard_folder  @cli.argument('--no-cpp', arg_only=True, action='store_false', help='Do not use \'cpp\' on keymap.c')  @cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')  @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") [email protected]('-kb', '--keyboard', arg_only=True, type=keyboard_folder, required=True, help='The keyboard\'s name') [email protected]('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, required=True, help='The keyboard\'s name')  @cli.argument('-km', '--keymap', arg_only=True, required=True, help='The keymap\'s name') [email protected]('filename', arg_only=True, help='keymap.c file') [email protected]('filename', arg_only=True, completer=FilesCompleter('.c'), help='keymap.c file')  @cli.subcommand('Creates a keymap.json from a keymap.c file.')  def c2json(cli):      """Generate a keymap.json from a keymap.c file. diff --git a/lib/python/qmk/cli/cformat.py b/lib/python/qmk/cli/cformat.py index c7e93b2ab6..d0d3b3b0a3 100644 --- a/lib/python/qmk/cli/cformat.py +++ b/lib/python/qmk/cli/cformat.py @@ -3,6 +3,7 @@  import subprocess  from shutil import which +from argcomplete.completers import FilesCompleter  from milc import cli  from qmk.path import normpath @@ -33,7 +34,7 @@ def cformat_run(files, all_files):  @cli.argument('-a', '--all-files', arg_only=True, action='store_true', help='Format all core files.')  @cli.argument('-b', '--base-branch', default='origin/master', help='Branch to compare to diffs to.') [email protected]('files', nargs='*', arg_only=True, help='Filename(s) to format.') [email protected]('files', nargs='*', arg_only=True, completer=FilesCompleter('.c'), help='Filename(s) to format.')  @cli.subcommand("Format C code according to QMK's style.", hidden=False if cli.config.user.developer else True)  def cformat(cli):      """Format C code according to QMK's style. diff --git a/lib/python/qmk/cli/compile.py b/lib/python/qmk/cli/compile.py index 5793e98928..23ca4e00a6 100755 --- a/lib/python/qmk/cli/compile.py +++ b/lib/python/qmk/cli/compile.py @@ -2,17 +2,19 @@  You can compile a keymap already in the repo or using a QMK Configurator export.  """ +from argcomplete.completers import FilesCompleter  from milc import cli  import qmk.path  from qmk.decorators import automagic_keyboard, automagic_keymap  from qmk.commands import compile_configurator_json, create_make_command, parse_configurator_json -from qmk.keyboard import keyboard_folder +from qmk.keyboard import keyboard_completer, keyboard_folder +from qmk.keymap import keymap_completer [email protected]('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), help='The configurator export to compile') [email protected]('-kb', '--keyboard', type=keyboard_folder, help='The keyboard to build a firmware for. Ignored when a configurator export is supplied.') [email protected]('-km', '--keymap', help='The keymap to build a firmware for. Ignored when a configurator export is supplied.') [email protected]('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), completer=FilesCompleter('.json'), help='The configurator export to compile') [email protected]('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='The keyboard to build a firmware for. Ignored when a configurator export is supplied.') [email protected]('-km', '--keymap', completer=keymap_completer, help='The keymap to build a firmware for. Ignored when a configurator export is supplied.')  @cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the make command to be run.")  @cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs to run.")  @cli.argument('-e', '--env', arg_only=True, action='append', default=[], help="Set a variable to be passed to make. May be passed multiple times.") diff --git a/lib/python/qmk/cli/flash.py b/lib/python/qmk/cli/flash.py index c9273c3f98..1b67840616 100644 --- a/lib/python/qmk/cli/flash.py +++ b/lib/python/qmk/cli/flash.py @@ -4,12 +4,13 @@ You can compile a keymap already in the repo or using a QMK Configurator export.  A bootloader must be specified.  """ +from argcomplete.completers import FilesCompleter  from milc import cli  import qmk.path  from qmk.decorators import automagic_keyboard, automagic_keymap  from qmk.commands import compile_configurator_json, create_make_command, parse_configurator_json -from qmk.keyboard import keyboard_folder +from qmk.keyboard import keyboard_completer, keyboard_folder  def print_bootloader_help(): @@ -30,11 +31,11 @@ def print_bootloader_help():      cli.echo('For more info, visit https://docs.qmk.fm/#/flashing') [email protected]('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), help='The configurator export JSON to compile.') [email protected]('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), completer=FilesCompleter('.json'), help='The configurator export JSON to compile.')  @cli.argument('-b', '--bootloaders', action='store_true', help='List the available bootloaders.')  @cli.argument('-bl', '--bootloader', default='flash', help='The flash command, corresponding to qmk\'s make options of bootloaders.')  @cli.argument('-km', '--keymap', help='The keymap to build a firmware for. Use this if you dont have a configurator file. Ignored when a configurator file is supplied.') [email protected]('-kb', '--keyboard', type=keyboard_folder, help='The keyboard to build a firmware for. Use this if you dont have a configurator file. Ignored when a configurator file is supplied.') [email protected]('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='The keyboard to build a firmware for. Use this if you dont have a configurator file. Ignored when a configurator file is supplied.')  @cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the make command to be run.")  @cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs to run.")  @cli.argument('-e', '--env', arg_only=True, action='append', default=[], help="Set a variable to be passed to make. May be passed multiple times.") diff --git a/lib/python/qmk/cli/generate/config_h.py b/lib/python/qmk/cli/generate/config_h.py index ccea6d7a05..54cd5b96a8 100755 --- a/lib/python/qmk/cli/generate/config_h.py +++ b/lib/python/qmk/cli/generate/config_h.py @@ -8,7 +8,7 @@ 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.keyboard import keyboard_folder +from qmk.keyboard import keyboard_completer, keyboard_folder  from qmk.path import is_keyboard, normpath @@ -75,7 +75,7 @@ def matrix_pins(matrix_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") [email protected]('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to generate config.h for.') [email protected]('-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 diff --git a/lib/python/qmk/cli/generate/dfu_header.py b/lib/python/qmk/cli/generate/dfu_header.py index 6f958b3a3d..211ed9991a 100644 --- a/lib/python/qmk/cli/generate/dfu_header.py +++ b/lib/python/qmk/cli/generate/dfu_header.py @@ -6,11 +6,12 @@ from milc import cli  from qmk.decorators import automagic_keyboard  from qmk.info import info_json  from qmk.path import is_keyboard, normpath +from qmk.keyboard import keyboard_completer  @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") [email protected]('-kb', '--keyboard', help='Keyboard to generate LUFA Keyboard.h for.') [email protected]('-kb', '--keyboard', completer=keyboard_completer, help='Keyboard to generate LUFA Keyboard.h for.')  @cli.subcommand('Used by the make system to generate LUFA Keyboard.h from info.json', hidden=True)  @automagic_keyboard  def generate_dfu_header(cli): diff --git a/lib/python/qmk/cli/generate/info_json.py b/lib/python/qmk/cli/generate/info_json.py index 1af7f04392..8931b68b6f 100755 --- a/lib/python/qmk/cli/generate/info_json.py +++ b/lib/python/qmk/cli/generate/info_json.py @@ -11,7 +11,7 @@ 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.keyboard import keyboard_folder +from qmk.keyboard import keyboard_completer, keyboard_folder  from qmk.path import is_keyboard @@ -41,7 +41,7 @@ def strip_info_json(kb_info_json):      return validator(kb_info_json) [email protected]('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to show info for.') [email protected]('-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.subcommand('Generate an info.json file for a keyboard.', hidden=False if cli.config.user.developer else True)  @automagic_keyboard diff --git a/lib/python/qmk/cli/generate/layouts.py b/lib/python/qmk/cli/generate/layouts.py index 7b4394291f..ad6946d6cf 100755 --- a/lib/python/qmk/cli/generate/layouts.py +++ b/lib/python/qmk/cli/generate/layouts.py @@ -5,7 +5,7 @@ from milc import cli  from qmk.constants import COL_LETTERS, ROW_LETTERS  from qmk.decorators import automagic_keyboard, automagic_keymap  from qmk.info import info_json -from qmk.keyboard import keyboard_folder +from qmk.keyboard import keyboard_completer, keyboard_folder  from qmk.path import is_keyboard, normpath  usb_properties = { @@ -17,7 +17,7 @@ usb_properties = {  @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") [email protected]('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to generate config.h for.') [email protected]('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate config.h for.')  @cli.subcommand('Used by the make system to generate layouts.h from info.json', hidden=True)  @automagic_keyboard  @automagic_keymap diff --git a/lib/python/qmk/cli/generate/rules_mk.py b/lib/python/qmk/cli/generate/rules_mk.py index 91759d26c6..41c94e16b5 100755 --- a/lib/python/qmk/cli/generate/rules_mk.py +++ b/lib/python/qmk/cli/generate/rules_mk.py @@ -8,7 +8,7 @@ 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.keyboard import keyboard_folder +from qmk.keyboard import keyboard_completer, keyboard_folder  from qmk.path import is_keyboard, normpath @@ -39,7 +39,7 @@ 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") [email protected]('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to generate config.h for.') [email protected]('-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 diff --git a/lib/python/qmk/cli/info.py b/lib/python/qmk/cli/info.py index aac507c1a5..572b305cac 100755 --- a/lib/python/qmk/cli/info.py +++ b/lib/python/qmk/cli/info.py @@ -10,7 +10,7 @@ from milc import cli  from qmk.json_encoders import InfoJSONEncoder  from qmk.constants import COL_LETTERS, ROW_LETTERS  from qmk.decorators import automagic_keyboard, automagic_keymap -from qmk.keyboard import keyboard_folder, render_layouts, render_layout +from qmk.keyboard import keyboard_completer, keyboard_folder, render_layouts, render_layout  from qmk.keymap import locate_keymap  from qmk.info import info_json  from qmk.path import is_keyboard @@ -124,7 +124,7 @@ def print_text_output(kb_info_json):          show_keymap(kb_info_json, False) [email protected]('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to show info for.') [email protected]('-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('-l', '--layouts', action='store_true', help='Render the layouts.')  @cli.argument('-m', '--matrix', action='store_true', help='Render the layouts with matrix information.') diff --git a/lib/python/qmk/cli/json2c.py b/lib/python/qmk/cli/json2c.py index 5a2fb96c78..a90578c021 100755 --- a/lib/python/qmk/cli/json2c.py +++ b/lib/python/qmk/cli/json2c.py @@ -2,6 +2,7 @@  """  import json +from argcomplete.completers import FilesCompleter  from milc import cli  import qmk.keymap @@ -10,7 +11,7 @@ import qmk.path  @cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')  @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") [email protected]('filename', type=qmk.path.FileType('r'), arg_only=True, help='Configurator JSON file') [email protected]('filename', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file')  @cli.subcommand('Creates a keymap.c from a QMK Configurator export.')  def json2c(cli):      """Generate a keymap.c from a configurator export. diff --git a/lib/python/qmk/cli/kle2json.py b/lib/python/qmk/cli/kle2json.py index 91499c9af3..acb75ef4fd 100755 --- a/lib/python/qmk/cli/kle2json.py +++ b/lib/python/qmk/cli/kle2json.py @@ -4,6 +4,7 @@ import json  import os  from pathlib import Path +from argcomplete.completers import FilesCompleter  from milc import cli  from kle2xy import KLE2xy @@ -11,7 +12,7 @@ from qmk.converter import kle2qmk  from qmk.json_encoders import InfoJSONEncoder [email protected]('filename', help='The KLE raw txt to convert') [email protected]('filename', completer=FilesCompleter('.json'), help='The KLE raw txt to convert')  @cli.argument('-f', '--force', action='store_true', help='Flag to overwrite current info.json')  @cli.subcommand('Convert a KLE layout to a Configurator JSON', hidden=False if cli.config.user.developer else True)  def kle2json(cli): diff --git a/lib/python/qmk/cli/lint.py b/lib/python/qmk/cli/lint.py index 74467021e0..a164dba632 100644 --- a/lib/python/qmk/cli/lint.py +++ b/lib/python/qmk/cli/lint.py @@ -4,12 +4,13 @@ from milc import cli  from qmk.decorators import automagic_keyboard, automagic_keymap  from qmk.info import info_json +from qmk.keyboard import keyboard_completer  from qmk.keymap import locate_keymap  from qmk.path import is_keyboard, keyboard  @cli.argument('--strict', action='store_true', help='Treat warnings as errors.') [email protected]('-kb', '--keyboard', help='The keyboard to check.') [email protected]('-kb', '--keyboard', completer=keyboard_completer, help='The keyboard to check.')  @cli.argument('-km', '--keymap', help='The keymap to check.')  @cli.subcommand('Check keyboard and keymap for common mistakes.')  @automagic_keyboard diff --git a/lib/python/qmk/cli/list/keymaps.py b/lib/python/qmk/cli/list/keymaps.py index 7c0ad43997..d79ab75b58 100644 --- a/lib/python/qmk/cli/list/keymaps.py +++ b/lib/python/qmk/cli/list/keymaps.py @@ -4,10 +4,10 @@ from milc import cli  import qmk.keymap  from qmk.decorators import automagic_keyboard -from qmk.keyboard import keyboard_folder +from qmk.keyboard import keyboard_completer, keyboard_folder [email protected]("-kb", "--keyboard", type=keyboard_folder, help="Specify keyboard name. Example: 1upkeyboards/1up60hse") [email protected]("-kb", "--keyboard", type=keyboard_folder, completer=keyboard_completer, help="Specify keyboard name. Example: 1upkeyboards/1up60hse")  @cli.subcommand("List the keymaps for a specific keyboard")  @automagic_keyboard  def list_keymaps(cli): diff --git a/lib/python/qmk/cli/new/keymap.py b/lib/python/qmk/cli/new/keymap.py index ea98a287c1..60cb743cb6 100755 --- a/lib/python/qmk/cli/new/keymap.py +++ b/lib/python/qmk/cli/new/keymap.py @@ -5,11 +5,11 @@ from pathlib import Path  import qmk.path  from qmk.decorators import automagic_keyboard, automagic_keymap -from qmk.keyboard import keyboard_folder +from qmk.keyboard import keyboard_completer, keyboard_folder  from milc import cli [email protected]('-kb', '--keyboard', type=keyboard_folder, help='Specify keyboard name. Example: 1upkeyboards/1up60hse') [email protected]('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='Specify keyboard name. Example: 1upkeyboards/1up60hse')  @cli.argument('-km', '--keymap', help='Specify the name for the new keymap directory')  @cli.subcommand('Creates a new keymap for the keyboard of your choosing')  @automagic_keyboard diff --git a/lib/python/qmk/decorators.py b/lib/python/qmk/decorators.py index 629402b095..8d43ae980f 100644 --- a/lib/python/qmk/decorators.py +++ b/lib/python/qmk/decorators.py @@ -1,13 +1,12 @@  """Helpful decorators that subcommands can use.  """  import functools -from pathlib import Path  from time import monotonic  from milc import cli -from qmk.keymap import is_keymap_dir -from qmk.path import is_keyboard, under_qmk_firmware +from qmk.keyboard import find_keyboard_from_dir +from qmk.keymap import find_keymap_from_dir  def automagic_keyboard(func): @@ -17,27 +16,13 @@ def automagic_keyboard(func):      """      @functools.wraps(func)      def wrapper(*args, **kwargs): -        # Check to make sure their copy of MILC supports config_source -        if not hasattr(cli, 'config_source'): -            cli.log.error("This subcommand requires a newer version of the QMK CLI. Please upgrade using `pip3 install --upgrade qmk` or your package manager.") -            exit(1) -          # Ensure that `--keyboard` was not passed and CWD is under `qmk_firmware/keyboards`          if cli.config_source[cli._entrypoint.__name__]['keyboard'] != 'argument': -            relative_cwd = under_qmk_firmware() - -            if relative_cwd and len(relative_cwd.parts) > 1 and relative_cwd.parts[0] == 'keyboards': -                # Attempt to extract the keyboard name from the current directory -                current_path = Path('/'.join(relative_cwd.parts[1:])) - -                if 'keymaps' in current_path.parts: -                    # Strip current_path of anything after `keymaps` -                    keymap_index = len(current_path.parts) - current_path.parts.index('keymaps') - 1 -                    current_path = current_path.parents[keymap_index] +            keyboard = find_keyboard_from_dir() -                if is_keyboard(current_path): -                    cli.config[cli._entrypoint.__name__]['keyboard'] = str(current_path) -                    cli.config_source[cli._entrypoint.__name__]['keyboard'] = 'keyboard_directory' +            if keyboard: +                cli.config[cli._entrypoint.__name__]['keyboard'] = keyboard +                cli.config_source[cli._entrypoint.__name__]['keyboard'] = 'keyboard_directory'          return func(*args, **kwargs) @@ -51,36 +36,13 @@ def automagic_keymap(func):      """      @functools.wraps(func)      def wrapper(*args, **kwargs): -        # Check to make sure their copy of MILC supports config_source -        if not hasattr(cli, 'config_source'): -            cli.log.error("This subcommand requires a newer version of the QMK CLI. Please upgrade using `pip3 install --upgrade qmk` or your package manager.") -            exit(1) -          # Ensure that `--keymap` was not passed and that we're under `qmk_firmware`          if cli.config_source[cli._entrypoint.__name__]['keymap'] != 'argument': -            relative_cwd = under_qmk_firmware() - -            if relative_cwd and len(relative_cwd.parts) > 1: -                # If we're in `qmk_firmware/keyboards` and `keymaps` is in our path, try to find the keyboard name. -                if relative_cwd.parts[0] == 'keyboards' and 'keymaps' in relative_cwd.parts: -                    current_path = Path('/'.join(relative_cwd.parts[1:]))  # Strip 'keyboards' from the front - -                    if 'keymaps' in current_path.parts and current_path.name != 'keymaps': -                        while current_path.parent.name != 'keymaps': -                            current_path = current_path.parent -                        cli.config[cli._entrypoint.__name__]['keymap'] = current_path.name -                        cli.config_source[cli._entrypoint.__name__]['keymap'] = 'keymap_directory' - -                # If we're in `qmk_firmware/layouts` guess the name from the community keymap they're in -                elif relative_cwd.parts[0] == 'layouts' and is_keymap_dir(relative_cwd): -                    cli.config[cli._entrypoint.__name__]['keymap'] = relative_cwd.name -                    cli.config_source[cli._entrypoint.__name__]['keymap'] = 'layouts_directory' - -                # If we're in `qmk_firmware/users` guess the name from the userspace they're in -                elif relative_cwd.parts[0] == 'users': -                    # Guess the keymap name based on which userspace they're in -                    cli.config[cli._entrypoint.__name__]['keymap'] = relative_cwd.parts[1] -                    cli.config_source[cli._entrypoint.__name__]['keymap'] = 'users_directory' +            keymap_name, keymap_type = find_keymap_from_dir() + +            if keymap_name: +                cli.config[cli._entrypoint.__name__]['keymap'] = keymap_name +                cli.config_source[cli._entrypoint.__name__]['keymap'] = keymap_type          return func(*args, **kwargs) diff --git a/lib/python/qmk/keyboard.py b/lib/python/qmk/keyboard.py index 89f9346c40..0168d17ef3 100644 --- a/lib/python/qmk/keyboard.py +++ b/lib/python/qmk/keyboard.py @@ -9,7 +9,7 @@ from glob import glob  from qmk.c_parse import parse_config_h_file  from qmk.json_schema import json_load  from qmk.makefile import parse_rules_mk_file -from qmk.path import is_keyboard +from qmk.path import is_keyboard, under_qmk_firmware  BOX_DRAWING_CHARACTERS = {      "unicode": { @@ -33,6 +33,24 @@ BOX_DRAWING_CHARACTERS = {  base_path = os.path.join(os.getcwd(), "keyboards") + os.path.sep +def find_keyboard_from_dir(): +    """Returns a keyboard name based on the user's current directory. +    """ +    relative_cwd = under_qmk_firmware() + +    if relative_cwd and len(relative_cwd.parts) > 1 and relative_cwd.parts[0] == 'keyboards': +        # Attempt to extract the keyboard name from the current directory +        current_path = Path('/'.join(relative_cwd.parts[1:])) + +        if 'keymaps' in current_path.parts: +            # Strip current_path of anything after `keymaps` +            keymap_index = len(current_path.parts) - current_path.parts.index('keymaps') - 1 +            current_path = current_path.parents[keymap_index] + +        if is_keyboard(current_path): +            return str(current_path) + +  def keyboard_folder(keyboard):      """Returns the actual keyboard folder. @@ -61,6 +79,12 @@ def _find_name(path):      return path.replace(base_path, "").replace(os.path.sep + "rules.mk", "") +def keyboard_completer(prefix, action, parser, parsed_args): +    """Returns a list of keyboards for tab completion. +    """ +    return list_keyboards() + +  def list_keyboards():      """Returns a list of all keyboards.      """ diff --git a/lib/python/qmk/keymap.py b/lib/python/qmk/keymap.py index d8495c38bc..4ad9ffb591 100644 --- a/lib/python/qmk/keymap.py +++ b/lib/python/qmk/keymap.py @@ -1,19 +1,19 @@  """Functions that help you work with QMK keymaps.  """ -from pathlib import Path  import json  import subprocess  import sys +from pathlib import Path +import argcomplete +from milc import cli  from pygments.lexers.c_cpp import CLexer  from pygments.token import Token  from pygments import lex -from milc import cli - -from qmk.keyboard import rules_mk  import qmk.path  import qmk.commands +from qmk.keyboard import find_keyboard_from_dir, rules_mk  # The `keymap.c` template to use when a keyboard doesn't have its own  DEFAULT_KEYMAP_C = """#include QMK_KEYBOARD_H @@ -74,6 +74,54 @@ def _strip_any(keycode):      return keycode +def find_keymap_from_dir(): +    """Returns `(keymap_name, source)` for the directory we're currently in. + +    """ +    relative_cwd = qmk.path.under_qmk_firmware() + +    if relative_cwd and len(relative_cwd.parts) > 1: +        # If we're in `qmk_firmware/keyboards` and `keymaps` is in our path, try to find the keyboard name. +        if relative_cwd.parts[0] == 'keyboards' and 'keymaps' in relative_cwd.parts: +            current_path = Path('/'.join(relative_cwd.parts[1:]))  # Strip 'keyboards' from the front + +            if 'keymaps' in current_path.parts and current_path.name != 'keymaps': +                while current_path.parent.name != 'keymaps': +                    current_path = current_path.parent + +                return current_path.name, 'keymap_directory' + +        # If we're in `qmk_firmware/layouts` guess the name from the community keymap they're in +        elif relative_cwd.parts[0] == 'layouts' and is_keymap_dir(relative_cwd): +            return relative_cwd.name, 'layouts_directory' + +        # If we're in `qmk_firmware/users` guess the name from the userspace they're in +        elif relative_cwd.parts[0] == 'users': +            # Guess the keymap name based on which userspace they're in +            return relative_cwd.parts[1], 'users_directory' + +    return None, None + + +def keymap_completer(prefix, action, parser, parsed_args): +    """Returns a list of keymaps for tab completion. +    """ +    try: +        if parsed_args.keyboard: +            return list_keymaps(parsed_args.keyboard) + +        keyboard = find_keyboard_from_dir() + +        if keyboard: +            return list_keymaps(keyboard) + +    except Exception as e: +        argcomplete.warn(f'Error: {e.__class__.__name__}: {str(e)}') +        return [] + +    return [] + +  def is_keymap_dir(keymap, c=True, json=True, additional_files=None):      """Return True if Path object `keymap` has a keymap file inside. | 
