diff options
author | Zach White <skullydazed@gmail.com> | 2021-04-14 19:00:22 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-14 19:00:22 -0700 |
commit | 588bcdc8ca212b195a428fc43766a59a9252c08d (patch) | |
tree | 4867ef610b2178d51002063bd4913e806f771543 /lib/python/qmk | |
parent | b33e6793de6c5f5124ee88fb3eb62d8f54f74940 (diff) | |
download | qmk_firmware-588bcdc8ca212b195a428fc43766a59a9252c08d.tar.gz qmk_firmware-588bcdc8ca212b195a428fc43766a59a9252c08d.zip |
Add support for tab completion (#12411)
* Add support for tab completion
* make flake8 happy
* Add documentation
Diffstat (limited to 'lib/python/qmk')
-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 1349e68a9..f7df90811 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 | |||
4 | """ | 4 | """ |
5 | import sys | 5 | import sys |
6 | 6 | ||
7 | from milc import cli | 7 | from milc import cli, __VERSION__ |
8 | 8 | ||
9 | from . import c2json | 9 | from . import c2json |
10 | from . import cformat | 10 | from . import cformat |
@@ -47,5 +47,15 @@ from . import pytest | |||
47 | # void: 3.9 | 47 | # void: 3.9 |
48 | 48 | ||
49 | if sys.version_info[0] != 3 or sys.version_info[1] < 7: | 49 | if sys.version_info[0] != 3 or sys.version_info[1] < 7: |
50 | cli.log.error('Your Python is too old! Please upgrade to Python 3.7 or later.') | 50 | print('Error: Your Python is too old! Please upgrade to Python 3.7 or later.') |
51 | exit(127) | ||
52 | |||
53 | milc_version = __VERSION__.split('.') | ||
54 | |||
55 | if int(milc_version[0]) < 2 and int(milc_version[1]) < 3: | ||
56 | from pathlib import Path | ||
57 | |||
58 | requirements = Path('requirements.txt').resolve() | ||
59 | |||
60 | print(f'Your MILC library is too old! Please upgrade: python3 -m pip install -U -r {str(requirements)}') | ||
51 | exit(127) | 61 | exit(127) |
diff --git a/lib/python/qmk/cli/c2json.py b/lib/python/qmk/cli/c2json.py index 1fa833b64..e66b0a1b5 100644 --- a/lib/python/qmk/cli/c2json.py +++ b/lib/python/qmk/cli/c2json.py | |||
@@ -2,20 +2,21 @@ | |||
2 | """ | 2 | """ |
3 | import json | 3 | import json |
4 | 4 | ||
5 | from argcomplete.completers import FilesCompleter | ||
5 | from milc import cli | 6 | from milc import cli |
6 | 7 | ||
7 | import qmk.keymap | 8 | import qmk.keymap |
8 | import qmk.path | 9 | import qmk.path |
9 | from qmk.json_encoders import InfoJSONEncoder | 10 | from qmk.json_encoders import InfoJSONEncoder |
10 | from qmk.keyboard import keyboard_folder | 11 | from qmk.keyboard import keyboard_completer, keyboard_folder |
11 | 12 | ||
12 | 13 | ||
13 | @cli.argument('--no-cpp', arg_only=True, action='store_false', help='Do not use \'cpp\' on keymap.c') | 14 | @cli.argument('--no-cpp', arg_only=True, action='store_false', help='Do not use \'cpp\' on keymap.c') |
14 | @cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to') | 15 | @cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to') |
15 | @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") | 16 | @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") |
16 | @cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, required=True, help='The keyboard\'s name') | 17 | @cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, required=True, help='The keyboard\'s name') |
17 | @cli.argument('-km', '--keymap', arg_only=True, required=True, help='The keymap\'s name') | 18 | @cli.argument('-km', '--keymap', arg_only=True, required=True, help='The keymap\'s name') |
18 | @cli.argument('filename', arg_only=True, help='keymap.c file') | 19 | @cli.argument('filename', arg_only=True, completer=FilesCompleter('.c'), help='keymap.c file') |
19 | @cli.subcommand('Creates a keymap.json from a keymap.c file.') | 20 | @cli.subcommand('Creates a keymap.json from a keymap.c file.') |
20 | def c2json(cli): | 21 | def c2json(cli): |
21 | """Generate a keymap.json from a keymap.c file. | 22 | """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 c7e93b2ab..d0d3b3b0a 100644 --- a/lib/python/qmk/cli/cformat.py +++ b/lib/python/qmk/cli/cformat.py | |||
@@ -3,6 +3,7 @@ | |||
3 | import subprocess | 3 | import subprocess |
4 | from shutil import which | 4 | from shutil import which |
5 | 5 | ||
6 | from argcomplete.completers import FilesCompleter | ||
6 | from milc import cli | 7 | from milc import cli |
7 | 8 | ||
8 | from qmk.path import normpath | 9 | from qmk.path import normpath |
@@ -33,7 +34,7 @@ def cformat_run(files, all_files): | |||
33 | 34 | ||
34 | @cli.argument('-a', '--all-files', arg_only=True, action='store_true', help='Format all core files.') | 35 | @cli.argument('-a', '--all-files', arg_only=True, action='store_true', help='Format all core files.') |
35 | @cli.argument('-b', '--base-branch', default='origin/master', help='Branch to compare to diffs to.') | 36 | @cli.argument('-b', '--base-branch', default='origin/master', help='Branch to compare to diffs to.') |
36 | @cli.argument('files', nargs='*', arg_only=True, help='Filename(s) to format.') | 37 | @cli.argument('files', nargs='*', arg_only=True, completer=FilesCompleter('.c'), help='Filename(s) to format.') |
37 | @cli.subcommand("Format C code according to QMK's style.", hidden=False if cli.config.user.developer else True) | 38 | @cli.subcommand("Format C code according to QMK's style.", hidden=False if cli.config.user.developer else True) |
38 | def cformat(cli): | 39 | def cformat(cli): |
39 | """Format C code according to QMK's style. | 40 | """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 5793e9892..23ca4e00a 100755 --- a/lib/python/qmk/cli/compile.py +++ b/lib/python/qmk/cli/compile.py | |||
@@ -2,17 +2,19 @@ | |||
2 | 2 | ||
3 | You can compile a keymap already in the repo or using a QMK Configurator export. | 3 | You can compile a keymap already in the repo or using a QMK Configurator export. |
4 | """ | 4 | """ |
5 | from argcomplete.completers import FilesCompleter | ||
5 | from milc import cli | 6 | from milc import cli |
6 | 7 | ||
7 | import qmk.path | 8 | import qmk.path |
8 | from qmk.decorators import automagic_keyboard, automagic_keymap | 9 | from qmk.decorators import automagic_keyboard, automagic_keymap |
9 | from qmk.commands import compile_configurator_json, create_make_command, parse_configurator_json | 10 | from qmk.commands import compile_configurator_json, create_make_command, parse_configurator_json |
10 | from qmk.keyboard import keyboard_folder | 11 | from qmk.keyboard import keyboard_completer, keyboard_folder |
12 | from qmk.keymap import keymap_completer | ||
11 | 13 | ||
12 | 14 | ||
13 | @cli.argument('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), help='The configurator export to compile') | 15 | @cli.argument('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), completer=FilesCompleter('.json'), help='The configurator export to compile') |
14 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, help='The keyboard to build a firmware for. Ignored when a configurator export is supplied.') | 16 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='The keyboard to build a firmware for. Ignored when a configurator export is supplied.') |
15 | @cli.argument('-km', '--keymap', help='The keymap to build a firmware for. Ignored when a configurator export is supplied.') | 17 | @cli.argument('-km', '--keymap', completer=keymap_completer, help='The keymap to build a firmware for. Ignored when a configurator export is supplied.') |
16 | @cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the make command to be run.") | 18 | @cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the make command to be run.") |
17 | @cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs to run.") | 19 | @cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs to run.") |
18 | @cli.argument('-e', '--env', arg_only=True, action='append', default=[], help="Set a variable to be passed to make. May be passed multiple times.") | 20 | @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 c9273c3f9..1b6784061 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. | |||
4 | A bootloader must be specified. | 4 | A bootloader must be specified. |
5 | """ | 5 | """ |
6 | 6 | ||
7 | from argcomplete.completers import FilesCompleter | ||
7 | from milc import cli | 8 | from milc import cli |
8 | 9 | ||
9 | import qmk.path | 10 | import qmk.path |
10 | from qmk.decorators import automagic_keyboard, automagic_keymap | 11 | from qmk.decorators import automagic_keyboard, automagic_keymap |
11 | from qmk.commands import compile_configurator_json, create_make_command, parse_configurator_json | 12 | from qmk.commands import compile_configurator_json, create_make_command, parse_configurator_json |
12 | from qmk.keyboard import keyboard_folder | 13 | from qmk.keyboard import keyboard_completer, keyboard_folder |
13 | 14 | ||
14 | 15 | ||
15 | def print_bootloader_help(): | 16 | def print_bootloader_help(): |
@@ -30,11 +31,11 @@ def print_bootloader_help(): | |||
30 | cli.echo('For more info, visit https://docs.qmk.fm/#/flashing') | 31 | cli.echo('For more info, visit https://docs.qmk.fm/#/flashing') |
31 | 32 | ||
32 | 33 | ||
33 | @cli.argument('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), help='The configurator export JSON to compile.') | 34 | @cli.argument('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), completer=FilesCompleter('.json'), help='The configurator export JSON to compile.') |
34 | @cli.argument('-b', '--bootloaders', action='store_true', help='List the available bootloaders.') | 35 | @cli.argument('-b', '--bootloaders', action='store_true', help='List the available bootloaders.') |
35 | @cli.argument('-bl', '--bootloader', default='flash', help='The flash command, corresponding to qmk\'s make options of bootloaders.') | 36 | @cli.argument('-bl', '--bootloader', default='flash', help='The flash command, corresponding to qmk\'s make options of bootloaders.') |
36 | @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.') | 37 | @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.') |
37 | @cli.argument('-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.') | 38 | @cli.argument('-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.') |
38 | @cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the make command to be run.") | 39 | @cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't actually build, just show the make command to be run.") |
39 | @cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs to run.") | 40 | @cli.argument('-j', '--parallel', type=int, default=1, help="Set the number of parallel make jobs to run.") |
40 | @cli.argument('-e', '--env', arg_only=True, action='append', default=[], help="Set a variable to be passed to make. May be passed multiple times.") | 41 | @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 ccea6d7a0..54cd5b96a 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 | |||
8 | from qmk.decorators import automagic_keyboard, automagic_keymap | 8 | from qmk.decorators import automagic_keyboard, automagic_keymap |
9 | from qmk.info import info_json | 9 | from qmk.info import info_json |
10 | from qmk.json_schema import json_load | 10 | from qmk.json_schema import json_load |
11 | from qmk.keyboard import keyboard_folder | 11 | from qmk.keyboard import keyboard_completer, keyboard_folder |
12 | from qmk.path import is_keyboard, normpath | 12 | from qmk.path import is_keyboard, normpath |
13 | 13 | ||
14 | 14 | ||
@@ -75,7 +75,7 @@ def matrix_pins(matrix_pins): | |||
75 | 75 | ||
76 | @cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to') | 76 | @cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to') |
77 | @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") | 77 | @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") |
78 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to generate config.h for.') | 78 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate config.h for.') |
79 | @cli.subcommand('Used by the make system to generate info_config.h from info.json', hidden=True) | 79 | @cli.subcommand('Used by the make system to generate info_config.h from info.json', hidden=True) |
80 | @automagic_keyboard | 80 | @automagic_keyboard |
81 | @automagic_keymap | 81 | @automagic_keymap |
diff --git a/lib/python/qmk/cli/generate/dfu_header.py b/lib/python/qmk/cli/generate/dfu_header.py index 6f958b3a3..211ed9991 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 | |||
6 | from qmk.decorators import automagic_keyboard | 6 | from qmk.decorators import automagic_keyboard |
7 | from qmk.info import info_json | 7 | from qmk.info import info_json |
8 | from qmk.path import is_keyboard, normpath | 8 | from qmk.path import is_keyboard, normpath |
9 | from qmk.keyboard import keyboard_completer | ||
9 | 10 | ||
10 | 11 | ||
11 | @cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to') | 12 | @cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to') |
12 | @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") | 13 | @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") |
13 | @cli.argument('-kb', '--keyboard', help='Keyboard to generate LUFA Keyboard.h for.') | 14 | @cli.argument('-kb', '--keyboard', completer=keyboard_completer, help='Keyboard to generate LUFA Keyboard.h for.') |
14 | @cli.subcommand('Used by the make system to generate LUFA Keyboard.h from info.json', hidden=True) | 15 | @cli.subcommand('Used by the make system to generate LUFA Keyboard.h from info.json', hidden=True) |
15 | @automagic_keyboard | 16 | @automagic_keyboard |
16 | def generate_dfu_header(cli): | 17 | 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 1af7f0439..8931b68b6 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 | |||
11 | from qmk.info import info_json | 11 | from qmk.info import info_json |
12 | from qmk.json_encoders import InfoJSONEncoder | 12 | from qmk.json_encoders import InfoJSONEncoder |
13 | from qmk.json_schema import load_jsonschema | 13 | from qmk.json_schema import load_jsonschema |
14 | from qmk.keyboard import keyboard_folder | 14 | from qmk.keyboard import keyboard_completer, keyboard_folder |
15 | from qmk.path import is_keyboard | 15 | from qmk.path import is_keyboard |
16 | 16 | ||
17 | 17 | ||
@@ -41,7 +41,7 @@ def strip_info_json(kb_info_json): | |||
41 | return validator(kb_info_json) | 41 | return validator(kb_info_json) |
42 | 42 | ||
43 | 43 | ||
44 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to show info for.') | 44 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='Keyboard to show info for.') |
45 | @cli.argument('-km', '--keymap', help='Show the layers for a JSON keymap too.') | 45 | @cli.argument('-km', '--keymap', help='Show the layers for a JSON keymap too.') |
46 | @cli.subcommand('Generate an info.json file for a keyboard.', hidden=False if cli.config.user.developer else True) | 46 | @cli.subcommand('Generate an info.json file for a keyboard.', hidden=False if cli.config.user.developer else True) |
47 | @automagic_keyboard | 47 | @automagic_keyboard |
diff --git a/lib/python/qmk/cli/generate/layouts.py b/lib/python/qmk/cli/generate/layouts.py index 7b4394291..ad6946d6c 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 | |||
5 | from qmk.constants import COL_LETTERS, ROW_LETTERS | 5 | from qmk.constants import COL_LETTERS, ROW_LETTERS |
6 | from qmk.decorators import automagic_keyboard, automagic_keymap | 6 | from qmk.decorators import automagic_keyboard, automagic_keymap |
7 | from qmk.info import info_json | 7 | from qmk.info import info_json |
8 | from qmk.keyboard import keyboard_folder | 8 | from qmk.keyboard import keyboard_completer, keyboard_folder |
9 | from qmk.path import is_keyboard, normpath | 9 | from qmk.path import is_keyboard, normpath |
10 | 10 | ||
11 | usb_properties = { | 11 | usb_properties = { |
@@ -17,7 +17,7 @@ usb_properties = { | |||
17 | 17 | ||
18 | @cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to') | 18 | @cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to') |
19 | @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") | 19 | @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") |
20 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to generate config.h for.') | 20 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate config.h for.') |
21 | @cli.subcommand('Used by the make system to generate layouts.h from info.json', hidden=True) | 21 | @cli.subcommand('Used by the make system to generate layouts.h from info.json', hidden=True) |
22 | @automagic_keyboard | 22 | @automagic_keyboard |
23 | @automagic_keymap | 23 | @automagic_keymap |
diff --git a/lib/python/qmk/cli/generate/rules_mk.py b/lib/python/qmk/cli/generate/rules_mk.py index 91759d26c..41c94e16b 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 | |||
8 | from qmk.decorators import automagic_keyboard, automagic_keymap | 8 | from qmk.decorators import automagic_keyboard, automagic_keymap |
9 | from qmk.info import info_json | 9 | from qmk.info import info_json |
10 | from qmk.json_schema import json_load | 10 | from qmk.json_schema import json_load |
11 | from qmk.keyboard import keyboard_folder | 11 | from qmk.keyboard import keyboard_completer, keyboard_folder |
12 | from qmk.path import is_keyboard, normpath | 12 | from qmk.path import is_keyboard, normpath |
13 | 13 | ||
14 | 14 | ||
@@ -39,7 +39,7 @@ def process_mapping_rule(kb_info_json, rules_key, info_dict): | |||
39 | @cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to') | 39 | @cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to') |
40 | @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") | 40 | @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") |
41 | @cli.argument('-e', '--escape', arg_only=True, action='store_true', help="Escape spaces in quiet mode") | 41 | @cli.argument('-e', '--escape', arg_only=True, action='store_true', help="Escape spaces in quiet mode") |
42 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to generate config.h for.') | 42 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate config.h for.') |
43 | @cli.subcommand('Used by the make system to generate info_config.h from info.json', hidden=True) | 43 | @cli.subcommand('Used by the make system to generate info_config.h from info.json', hidden=True) |
44 | @automagic_keyboard | 44 | @automagic_keyboard |
45 | @automagic_keymap | 45 | @automagic_keymap |
diff --git a/lib/python/qmk/cli/info.py b/lib/python/qmk/cli/info.py index aac507c1a..572b305ca 100755 --- a/lib/python/qmk/cli/info.py +++ b/lib/python/qmk/cli/info.py | |||
@@ -10,7 +10,7 @@ from milc import cli | |||
10 | from qmk.json_encoders import InfoJSONEncoder | 10 | from qmk.json_encoders import InfoJSONEncoder |
11 | from qmk.constants import COL_LETTERS, ROW_LETTERS | 11 | from qmk.constants import COL_LETTERS, ROW_LETTERS |
12 | from qmk.decorators import automagic_keyboard, automagic_keymap | 12 | from qmk.decorators import automagic_keyboard, automagic_keymap |
13 | from qmk.keyboard import keyboard_folder, render_layouts, render_layout | 13 | from qmk.keyboard import keyboard_completer, keyboard_folder, render_layouts, render_layout |
14 | from qmk.keymap import locate_keymap | 14 | from qmk.keymap import locate_keymap |
15 | from qmk.info import info_json | 15 | from qmk.info import info_json |
16 | from qmk.path import is_keyboard | 16 | from qmk.path import is_keyboard |
@@ -124,7 +124,7 @@ def print_text_output(kb_info_json): | |||
124 | show_keymap(kb_info_json, False) | 124 | show_keymap(kb_info_json, False) |
125 | 125 | ||
126 | 126 | ||
127 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to show info for.') | 127 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='Keyboard to show info for.') |
128 | @cli.argument('-km', '--keymap', help='Show the layers for a JSON keymap too.') | 128 | @cli.argument('-km', '--keymap', help='Show the layers for a JSON keymap too.') |
129 | @cli.argument('-l', '--layouts', action='store_true', help='Render the layouts.') | 129 | @cli.argument('-l', '--layouts', action='store_true', help='Render the layouts.') |
130 | @cli.argument('-m', '--matrix', action='store_true', help='Render the layouts with matrix information.') | 130 | @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 5a2fb96c7..a90578c02 100755 --- a/lib/python/qmk/cli/json2c.py +++ b/lib/python/qmk/cli/json2c.py | |||
@@ -2,6 +2,7 @@ | |||
2 | """ | 2 | """ |
3 | import json | 3 | import json |
4 | 4 | ||
5 | from argcomplete.completers import FilesCompleter | ||
5 | from milc import cli | 6 | from milc import cli |
6 | 7 | ||
7 | import qmk.keymap | 8 | import qmk.keymap |
@@ -10,7 +11,7 @@ import qmk.path | |||
10 | 11 | ||
11 | @cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to') | 12 | @cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to') |
12 | @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") | 13 | @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") |
13 | @cli.argument('filename', type=qmk.path.FileType('r'), arg_only=True, help='Configurator JSON file') | 14 | @cli.argument('filename', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file') |
14 | @cli.subcommand('Creates a keymap.c from a QMK Configurator export.') | 15 | @cli.subcommand('Creates a keymap.c from a QMK Configurator export.') |
15 | def json2c(cli): | 16 | def json2c(cli): |
16 | """Generate a keymap.c from a configurator export. | 17 | """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 91499c9af..acb75ef4f 100755 --- a/lib/python/qmk/cli/kle2json.py +++ b/lib/python/qmk/cli/kle2json.py | |||
@@ -4,6 +4,7 @@ import json | |||
4 | import os | 4 | import os |
5 | from pathlib import Path | 5 | from pathlib import Path |
6 | 6 | ||
7 | from argcomplete.completers import FilesCompleter | ||
7 | from milc import cli | 8 | from milc import cli |
8 | from kle2xy import KLE2xy | 9 | from kle2xy import KLE2xy |
9 | 10 | ||
@@ -11,7 +12,7 @@ from qmk.converter import kle2qmk | |||
11 | from qmk.json_encoders import InfoJSONEncoder | 12 | from qmk.json_encoders import InfoJSONEncoder |
12 | 13 | ||
13 | 14 | ||
14 | @cli.argument('filename', help='The KLE raw txt to convert') | 15 | @cli.argument('filename', completer=FilesCompleter('.json'), help='The KLE raw txt to convert') |
15 | @cli.argument('-f', '--force', action='store_true', help='Flag to overwrite current info.json') | 16 | @cli.argument('-f', '--force', action='store_true', help='Flag to overwrite current info.json') |
16 | @cli.subcommand('Convert a KLE layout to a Configurator JSON', hidden=False if cli.config.user.developer else True) | 17 | @cli.subcommand('Convert a KLE layout to a Configurator JSON', hidden=False if cli.config.user.developer else True) |
17 | def kle2json(cli): | 18 | def kle2json(cli): |
diff --git a/lib/python/qmk/cli/lint.py b/lib/python/qmk/cli/lint.py index 74467021e..a164dba63 100644 --- a/lib/python/qmk/cli/lint.py +++ b/lib/python/qmk/cli/lint.py | |||
@@ -4,12 +4,13 @@ from milc import cli | |||
4 | 4 | ||
5 | from qmk.decorators import automagic_keyboard, automagic_keymap | 5 | from qmk.decorators import automagic_keyboard, automagic_keymap |
6 | from qmk.info import info_json | 6 | from qmk.info import info_json |
7 | from qmk.keyboard import keyboard_completer | ||
7 | from qmk.keymap import locate_keymap | 8 | from qmk.keymap import locate_keymap |
8 | from qmk.path import is_keyboard, keyboard | 9 | from qmk.path import is_keyboard, keyboard |
9 | 10 | ||
10 | 11 | ||
11 | @cli.argument('--strict', action='store_true', help='Treat warnings as errors.') | 12 | @cli.argument('--strict', action='store_true', help='Treat warnings as errors.') |
12 | @cli.argument('-kb', '--keyboard', help='The keyboard to check.') | 13 | @cli.argument('-kb', '--keyboard', completer=keyboard_completer, help='The keyboard to check.') |
13 | @cli.argument('-km', '--keymap', help='The keymap to check.') | 14 | @cli.argument('-km', '--keymap', help='The keymap to check.') |
14 | @cli.subcommand('Check keyboard and keymap for common mistakes.') | 15 | @cli.subcommand('Check keyboard and keymap for common mistakes.') |
15 | @automagic_keyboard | 16 | @automagic_keyboard |
diff --git a/lib/python/qmk/cli/list/keymaps.py b/lib/python/qmk/cli/list/keymaps.py index 7c0ad4399..d79ab75b5 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 | |||
4 | 4 | ||
5 | import qmk.keymap | 5 | import qmk.keymap |
6 | from qmk.decorators import automagic_keyboard | 6 | from qmk.decorators import automagic_keyboard |
7 | from qmk.keyboard import keyboard_folder | 7 | from qmk.keyboard import keyboard_completer, keyboard_folder |
8 | 8 | ||
9 | 9 | ||
10 | @cli.argument("-kb", "--keyboard", type=keyboard_folder, help="Specify keyboard name. Example: 1upkeyboards/1up60hse") | 10 | @cli.argument("-kb", "--keyboard", type=keyboard_folder, completer=keyboard_completer, help="Specify keyboard name. Example: 1upkeyboards/1up60hse") |
11 | @cli.subcommand("List the keymaps for a specific keyboard") | 11 | @cli.subcommand("List the keymaps for a specific keyboard") |
12 | @automagic_keyboard | 12 | @automagic_keyboard |
13 | def list_keymaps(cli): | 13 | def list_keymaps(cli): |
diff --git a/lib/python/qmk/cli/new/keymap.py b/lib/python/qmk/cli/new/keymap.py index ea98a287c..60cb743cb 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 | |||
5 | 5 | ||
6 | import qmk.path | 6 | import qmk.path |
7 | from qmk.decorators import automagic_keyboard, automagic_keymap | 7 | from qmk.decorators import automagic_keyboard, automagic_keymap |
8 | from qmk.keyboard import keyboard_folder | 8 | from qmk.keyboard import keyboard_completer, keyboard_folder |
9 | from milc import cli | 9 | from milc import cli |
10 | 10 | ||
11 | 11 | ||
12 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Specify keyboard name. Example: 1upkeyboards/1up60hse') | 12 | @cli.argument('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='Specify keyboard name. Example: 1upkeyboards/1up60hse') |
13 | @cli.argument('-km', '--keymap', help='Specify the name for the new keymap directory') | 13 | @cli.argument('-km', '--keymap', help='Specify the name for the new keymap directory') |
14 | @cli.subcommand('Creates a new keymap for the keyboard of your choosing') | 14 | @cli.subcommand('Creates a new keymap for the keyboard of your choosing') |
15 | @automagic_keyboard | 15 | @automagic_keyboard |
diff --git a/lib/python/qmk/decorators.py b/lib/python/qmk/decorators.py index 629402b09..8d43ae980 100644 --- a/lib/python/qmk/decorators.py +++ b/lib/python/qmk/decorators.py | |||
@@ -1,13 +1,12 @@ | |||
1 | """Helpful decorators that subcommands can use. | 1 | """Helpful decorators that subcommands can use. |
2 | """ | 2 | """ |
3 | import functools | 3 | import functools |
4 | from pathlib import Path | ||
5 | from time import monotonic | 4 | from time import monotonic |
6 | 5 | ||
7 | from milc import cli | 6 | from milc import cli |
8 | 7 | ||
9 | from qmk.keymap import is_keymap_dir | 8 | from qmk.keyboard import find_keyboard_from_dir |
10 | from qmk.path import is_keyboard, under_qmk_firmware | 9 | from qmk.keymap import find_keymap_from_dir |
11 | 10 | ||
12 | 11 | ||
13 | def automagic_keyboard(func): | 12 | def automagic_keyboard(func): |
@@ -17,27 +16,13 @@ def automagic_keyboard(func): | |||
17 | """ | 16 | """ |
18 | @functools.wraps(func) | 17 | @functools.wraps(func) |
19 | def wrapper(*args, **kwargs): | 18 | def wrapper(*args, **kwargs): |
20 | # Check to make sure their copy of MILC supports config_source | ||
21 | if not hasattr(cli, 'config_source'): | ||
22 | cli.log.error("This subcommand requires a newer version of the QMK CLI. Please upgrade using `pip3 install --upgrade qmk` or your package manager.") | ||
23 | exit(1) | ||
24 | |||
25 | # Ensure that `--keyboard` was not passed and CWD is under `qmk_firmware/keyboards` | 19 | # Ensure that `--keyboard` was not passed and CWD is under `qmk_firmware/keyboards` |
26 | if cli.config_source[cli._entrypoint.__name__]['keyboard'] != 'argument': | 20 | if cli.config_source[cli._entrypoint.__name__]['keyboard'] != 'argument': |
27 | relative_cwd = under_qmk_firmware() | 21 | keyboard = find_keyboard_from_dir() |
28 | |||
29 | if relative_cwd and len(relative_cwd.parts) > 1 and relative_cwd.parts[0] == 'keyboards': | ||
30 | # Attempt to extract the keyboard name from the current directory | ||
31 | current_path = Path('/'.join(relative_cwd.parts[1:])) | ||
32 | |||
33 | if 'keymaps' in current_path.parts: | ||
34 | # Strip current_path of anything after `keymaps` | ||
35 | keymap_index = len(current_path.parts) - current_path.parts.index('keymaps') - 1 | ||
36 | current_path = current_path.parents[keymap_index] | ||
37 | 22 | ||
38 | if is_keyboard(current_path): | 23 | if keyboard: |
39 | cli.config[cli._entrypoint.__name__]['keyboard'] = str(current_path) | 24 | cli.config[cli._entrypoint.__name__]['keyboard'] = keyboard |
40 | cli.config_source[cli._entrypoint.__name__]['keyboard'] = 'keyboard_directory' | 25 | cli.config_source[cli._entrypoint.__name__]['keyboard'] = 'keyboard_directory' |
41 | 26 | ||
42 | return func(*args, **kwargs) | 27 | return func(*args, **kwargs) |
43 | 28 | ||
@@ -51,36 +36,13 @@ def automagic_keymap(func): | |||
51 | """ | 36 | """ |
52 | @functools.wraps(func) | 37 | @functools.wraps(func) |
53 | def wrapper(*args, **kwargs): | 38 | def wrapper(*args, **kwargs): |
54 | # Check to make sure their copy of MILC supports config_source | ||
55 | if not hasattr(cli, 'config_source'): | ||
56 | cli.log.error("This subcommand requires a newer version of the QMK CLI. Please upgrade using `pip3 install --upgrade qmk` or your package manager.") | ||
57 | exit(1) | ||
58 | |||
59 | # Ensure that `--keymap` was not passed and that we're under `qmk_firmware` | 39 | # Ensure that `--keymap` was not passed and that we're under `qmk_firmware` |
60 | if cli.config_source[cli._entrypoint.__name__]['keymap'] != 'argument': | 40 | if cli.config_source[cli._entrypoint.__name__]['keymap'] != 'argument': |
61 | relative_cwd = under_qmk_firmware() | 41 | keymap_name, keymap_type = find_keymap_from_dir() |
62 | 42 | ||
63 | if relative_cwd and len(relative_cwd.parts) > 1: | 43 | if keymap_name: |
64 | # If we're in `qmk_firmware/keyboards` and `keymaps` is in our path, try to find the keyboard name. | 44 | cli.config[cli._entrypoint.__name__]['keymap'] = keymap_name |
65 | if relative_cwd.parts[0] == 'keyboards' and 'keymaps' in relative_cwd.parts: | 45 | cli.config_source[cli._entrypoint.__name__]['keymap'] = keymap_type |
66 | current_path = Path('/'.join(relative_cwd.parts[1:])) # Strip 'keyboards' from the front | ||
67 | |||
68 | if 'keymaps' in current_path.parts and current_path.name != 'keymaps': | ||
69 | while current_path.parent.name != 'keymaps': | ||
70 | current_path = current_path.parent | ||
71 | cli.config[cli._entrypoint.__name__]['keymap'] = current_path.name | ||
72 | cli.config_source[cli._entrypoint.__name__]['keymap'] = 'keymap_directory' | ||
73 | |||
74 | # If we're in `qmk_firmware/layouts` guess the name from the community keymap they're in | ||
75 | elif relative_cwd.parts[0] == 'layouts' and is_keymap_dir(relative_cwd): | ||
76 | cli.config[cli._entrypoint.__name__]['keymap'] = relative_cwd.name | ||
77 | cli.config_source[cli._entrypoint.__name__]['keymap'] = 'layouts_directory' | ||
78 | |||
79 | # If we're in `qmk_firmware/users` guess the name from the userspace they're in | ||
80 | elif relative_cwd.parts[0] == 'users': | ||
81 | # Guess the keymap name based on which userspace they're in | ||
82 | cli.config[cli._entrypoint.__name__]['keymap'] = relative_cwd.parts[1] | ||
83 | cli.config_source[cli._entrypoint.__name__]['keymap'] = 'users_directory' | ||
84 | 46 | ||
85 | return func(*args, **kwargs) | 47 | return func(*args, **kwargs) |
86 | 48 | ||
diff --git a/lib/python/qmk/keyboard.py b/lib/python/qmk/keyboard.py index 89f9346c4..0168d17ef 100644 --- a/lib/python/qmk/keyboard.py +++ b/lib/python/qmk/keyboard.py | |||
@@ -9,7 +9,7 @@ from glob import glob | |||
9 | from qmk.c_parse import parse_config_h_file | 9 | from qmk.c_parse import parse_config_h_file |
10 | from qmk.json_schema import json_load | 10 | from qmk.json_schema import json_load |
11 | from qmk.makefile import parse_rules_mk_file | 11 | from qmk.makefile import parse_rules_mk_file |
12 | from qmk.path import is_keyboard | 12 | from qmk.path import is_keyboard, under_qmk_firmware |
13 | 13 | ||
14 | BOX_DRAWING_CHARACTERS = { | 14 | BOX_DRAWING_CHARACTERS = { |
15 | "unicode": { | 15 | "unicode": { |
@@ -33,6 +33,24 @@ BOX_DRAWING_CHARACTERS = { | |||
33 | base_path = os.path.join(os.getcwd(), "keyboards") + os.path.sep | 33 | base_path = os.path.join(os.getcwd(), "keyboards") + os.path.sep |
34 | 34 | ||
35 | 35 | ||
36 | def find_keyboard_from_dir(): | ||
37 | """Returns a keyboard name based on the user's current directory. | ||
38 | """ | ||
39 | relative_cwd = under_qmk_firmware() | ||
40 | |||
41 | if relative_cwd and len(relative_cwd.parts) > 1 and relative_cwd.parts[0] == 'keyboards': | ||
42 | # Attempt to extract the keyboard name from the current directory | ||
43 | current_path = Path('/'.join(relative_cwd.parts[1:])) | ||
44 | |||
45 | if 'keymaps' in current_path.parts: | ||
46 | # Strip current_path of anything after `keymaps` | ||
47 | keymap_index = len(current_path.parts) - current_path.parts.index('keymaps') - 1 | ||
48 | current_path = current_path.parents[keymap_index] | ||
49 | |||
50 | if is_keyboard(current_path): | ||
51 | return str(current_path) | ||
52 | |||
53 | |||
36 | def keyboard_folder(keyboard): | 54 | def keyboard_folder(keyboard): |
37 | """Returns the actual keyboard folder. | 55 | """Returns the actual keyboard folder. |
38 | 56 | ||
@@ -61,6 +79,12 @@ def _find_name(path): | |||
61 | return path.replace(base_path, "").replace(os.path.sep + "rules.mk", "") | 79 | return path.replace(base_path, "").replace(os.path.sep + "rules.mk", "") |
62 | 80 | ||
63 | 81 | ||
82 | def keyboard_completer(prefix, action, parser, parsed_args): | ||
83 | """Returns a list of keyboards for tab completion. | ||
84 | """ | ||
85 | return list_keyboards() | ||
86 | |||
87 | |||
64 | def list_keyboards(): | 88 | def list_keyboards(): |
65 | """Returns a list of all keyboards. | 89 | """Returns a list of all keyboards. |
66 | """ | 90 | """ |
diff --git a/lib/python/qmk/keymap.py b/lib/python/qmk/keymap.py index d8495c38b..4ad9ffb59 100644 --- a/lib/python/qmk/keymap.py +++ b/lib/python/qmk/keymap.py | |||
@@ -1,19 +1,19 @@ | |||
1 | """Functions that help you work with QMK keymaps. | 1 | """Functions that help you work with QMK keymaps. |
2 | """ | 2 | """ |
3 | from pathlib import Path | ||
4 | import json | 3 | import json |
5 | import subprocess | 4 | import subprocess |
6 | import sys | 5 | import sys |
6 | from pathlib import Path | ||
7 | 7 | ||
8 | import argcomplete | ||
9 | from milc import cli | ||
8 | from pygments.lexers.c_cpp import CLexer | 10 | from pygments.lexers.c_cpp import CLexer |
9 | from pygments.token import Token | 11 | from pygments.token import Token |
10 | from pygments import lex | 12 | from pygments import lex |
11 | 13 | ||
12 | from milc import cli | ||
13 | |||
14 | from qmk.keyboard import rules_mk | ||
15 | import qmk.path | 14 | import qmk.path |
16 | import qmk.commands | 15 | import qmk.commands |
16 | from qmk.keyboard import find_keyboard_from_dir, rules_mk | ||
17 | 17 | ||
18 | # The `keymap.c` template to use when a keyboard doesn't have its own | 18 | # The `keymap.c` template to use when a keyboard doesn't have its own |
19 | DEFAULT_KEYMAP_C = """#include QMK_KEYBOARD_H | 19 | DEFAULT_KEYMAP_C = """#include QMK_KEYBOARD_H |
@@ -74,6 +74,54 @@ def _strip_any(keycode): | |||
74 | return keycode | 74 | return keycode |
75 | 75 | ||
76 | 76 | ||
77 | def find_keymap_from_dir(): | ||
78 | """Returns `(keymap_name, source)` for the directory we're currently in. | ||
79 | |||
80 | """ | ||
81 | relative_cwd = qmk.path.under_qmk_firmware() | ||
82 | |||
83 | if relative_cwd and len(relative_cwd.parts) > 1: | ||
84 | # If we're in `qmk_firmware/keyboards` and `keymaps` is in our path, try to find the keyboard name. | ||
85 | if relative_cwd.parts[0] == 'keyboards' and 'keymaps' in relative_cwd.parts: | ||
86 | current_path = Path('/'.join(relative_cwd.parts[1:])) # Strip 'keyboards' from the front | ||
87 | |||
88 | if 'keymaps' in current_path.parts and current_path.name != 'keymaps': | ||
89 | while current_path.parent.name != 'keymaps': | ||
90 | current_path = current_path.parent | ||
91 | |||
92 | return current_path.name, 'keymap_directory' | ||
93 | |||
94 | # If we're in `qmk_firmware/layouts` guess the name from the community keymap they're in | ||
95 | elif relative_cwd.parts[0] == 'layouts' and is_keymap_dir(relative_cwd): | ||
96 | return relative_cwd.name, 'layouts_directory' | ||
97 | |||
98 | # If we're in `qmk_firmware/users` guess the name from the userspace they're in | ||
99 | elif relative_cwd.parts[0] == 'users': | ||
100 | # Guess the keymap name based on which userspace they're in | ||
101 | return relative_cwd.parts[1], 'users_directory' | ||
102 | |||
103 | return None, None | ||
104 | |||
105 | |||
106 | def keymap_completer(prefix, action, parser, parsed_args): | ||
107 | """Returns a list of keymaps for tab completion. | ||
108 | """ | ||
109 | try: | ||
110 | if parsed_args.keyboard: | ||
111 | return list_keymaps(parsed_args.keyboard) | ||
112 | |||
113 | keyboard = find_keyboard_from_dir() | ||
114 | |||
115 | if keyboard: | ||
116 | return list_keymaps(keyboard) | ||
117 | |||
118 | except Exception as e: | ||
119 | argcomplete.warn(f'Error: {e.__class__.__name__}: {str(e)}') | ||
120 | return [] | ||
121 | |||
122 | return [] | ||
123 | |||
124 | |||
77 | def is_keymap_dir(keymap, c=True, json=True, additional_files=None): | 125 | def is_keymap_dir(keymap, c=True, json=True, additional_files=None): |
78 | """Return True if Path object `keymap` has a keymap file inside. | 126 | """Return True if Path object `keymap` has a keymap file inside. |
79 | 127 | ||