Add support for tab completion (#12411)
* Add support for tab completion * make flake8 happy * Add documentation
This commit is contained in:
		
							parent
							
								
									b33e6793de
								
							
						
					
					
						commit
						588bcdc8ca
					
				
					 23 changed files with 168 additions and 85 deletions
				
			
		| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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")
 | 
			
		||||
@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, required=True, help='The keyboard\'s name')
 | 
			
		||||
@cli.argument('-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')
 | 
			
		||||
@cli.argument('filename', arg_only=True, help='keymap.c file')
 | 
			
		||||
@cli.argument('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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.')
 | 
			
		||||
@cli.argument('files', nargs='*', arg_only=True, help='Filename(s) to format.')
 | 
			
		||||
@cli.argument('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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@cli.argument('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), help='The configurator export to compile')
 | 
			
		||||
@cli.argument('-kb', '--keyboard', type=keyboard_folder, help='The keyboard to build a firmware for. Ignored when a configurator export is supplied.')
 | 
			
		||||
@cli.argument('-km', '--keymap', help='The keymap to build a firmware for. Ignored when a configurator export is supplied.')
 | 
			
		||||
@cli.argument('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), completer=FilesCompleter('.json'), help='The configurator export to compile')
 | 
			
		||||
@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.')
 | 
			
		||||
@cli.argument('-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.")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@cli.argument('filename', nargs='?', arg_only=True, type=qmk.path.FileType('r'), help='The configurator export JSON to compile.')
 | 
			
		||||
@cli.argument('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.')
 | 
			
		||||
@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.')
 | 
			
		||||
@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.')
 | 
			
		||||
@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.")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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")
 | 
			
		||||
@cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to generate config.h for.')
 | 
			
		||||
@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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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")
 | 
			
		||||
@cli.argument('-kb', '--keyboard', help='Keyboard to generate LUFA Keyboard.h for.')
 | 
			
		||||
@cli.argument('-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):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to show info for.')
 | 
			
		||||
@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.subcommand('Generate an info.json file for a keyboard.', hidden=False if cli.config.user.developer else True)
 | 
			
		||||
@automagic_keyboard
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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")
 | 
			
		||||
@cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to generate config.h for.')
 | 
			
		||||
@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 layouts.h from info.json', hidden=True)
 | 
			
		||||
@automagic_keyboard
 | 
			
		||||
@automagic_keymap
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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")
 | 
			
		||||
@cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to generate config.h for.')
 | 
			
		||||
@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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Keyboard to show info for.')
 | 
			
		||||
@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('-l', '--layouts', action='store_true', help='Render the layouts.')
 | 
			
		||||
@cli.argument('-m', '--matrix', action='store_true', help='Render the layouts with matrix information.')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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")
 | 
			
		||||
@cli.argument('filename', type=qmk.path.FileType('r'), arg_only=True, help='Configurator JSON file')
 | 
			
		||||
@cli.argument('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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@cli.argument('filename', help='The KLE raw txt to convert')
 | 
			
		||||
@cli.argument('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):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.')
 | 
			
		||||
@cli.argument('-kb', '--keyboard', help='The keyboard to check.')
 | 
			
		||||
@cli.argument('-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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@cli.argument("-kb", "--keyboard", type=keyboard_folder, help="Specify keyboard name. Example: 1upkeyboards/1up60hse")
 | 
			
		||||
@cli.argument("-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):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@cli.argument('-kb', '--keyboard', type=keyboard_folder, help='Specify keyboard name. Example: 1upkeyboards/1up60hse')
 | 
			
		||||
@cli.argument('-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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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()
 | 
			
		||||
            keyboard = find_keyboard_from_dir()
 | 
			
		||||
 | 
			
		||||
            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):
 | 
			
		||||
                    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()
 | 
			
		||||
            keymap_name, keymap_type = find_keymap_from_dir()
 | 
			
		||||
 | 
			
		||||
            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'
 | 
			
		||||
            if keymap_name:
 | 
			
		||||
                cli.config[cli._entrypoint.__name__]['keymap'] = keymap_name
 | 
			
		||||
                cli.config_source[cli._entrypoint.__name__]['keymap'] = keymap_type
 | 
			
		||||
 | 
			
		||||
        return func(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
    """
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue