summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/labeler.yml1
-rw-r--r--.github/workflows/cli.yml1
-rw-r--r--Makefile6
-rwxr-xr-xbin/qmk58
-rw-r--r--build_keyboard.mk19
-rw-r--r--docs/cli_commands.md48
-rw-r--r--docs/contributing.md2
-rw-r--r--docs/de/cli.md19
-rw-r--r--docs/fr-fr/cli.md19
-rw-r--r--docs/hardware_keyboard_guidelines.md28
-rw-r--r--keyboards/dztech/dz65rgb/keymaps/jumper149/readme.md4
-rw-r--r--lib/python/qmk/cli/__init__.py1
-rw-r--r--lib/python/qmk/cli/console.py303
-rw-r--r--lib/python/qmk/cli/doctor/check.py1
-rwxr-xr-xlib/python/qmk/cli/format/python.py6
-rw-r--r--lib/python/qmk/cli/lint.py145
-rw-r--r--lib/python/qmk/cli/pytest.py2
-rw-r--r--lib/python/qmk/commands.py2
-rw-r--r--lib/python/qmk/tests/test_cli_commands.py2
-rw-r--r--shell.nix2
20 files changed, 159 insertions, 510 deletions
diff --git a/.github/labeler.yml b/.github/labeler.yml
index 53921f7f95..41b2475f67 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -22,7 +22,6 @@ keymap:
via:
- keyboards/**/keymaps/via/*
cli:
- - bin/qmk
- requirements.txt
- lib/python/**/*
python:
diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml
index 7a8dc8540f..3bf9741ac7 100644
--- a/.github/workflows/cli.yml
+++ b/.github/workflows/cli.yml
@@ -8,7 +8,6 @@ on:
pull_request:
paths:
- 'lib/python/**'
- - 'bin/qmk'
- 'requirements.txt'
- '.github/workflows/cli.yml'
diff --git a/Makefile b/Makefile
index bb2201e852..269be720c2 100644
--- a/Makefile
+++ b/Makefile
@@ -30,11 +30,7 @@ endif
endif
# Determine which qmk cli to use
-ifeq (,$(shell which qmk))
- QMK_BIN = bin/qmk
-else
- QMK_BIN = qmk
-endif
+QMK_BIN := qmk
# avoid 'Entering|Leaving directory' messages
MAKEFLAGS += --no-print-directory
diff --git a/bin/qmk b/bin/qmk
deleted file mode 100755
index 617f992826..0000000000
--- a/bin/qmk
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python3
-"""CLI wrapper for running QMK commands.
-"""
-import os
-import sys
-from pathlib import Path
-
-# Add the QMK python libs to our path
-script_dir = Path(os.path.realpath(__file__)).parent
-qmk_dir = script_dir.parent
-python_lib_dir = Path(qmk_dir / 'lib' / 'python').resolve()
-sys.path.append(str(python_lib_dir))
-
-# Setup the CLI
-import milc # noqa
-
-milc.EMOJI_LOGLEVELS['INFO'] = '{fg_blue}Ψ{style_reset_all}'
-
-
-@milc.cli.entrypoint('QMK Helper Script')
-def qmk_main(cli):
- """The function that gets run when no subcommand is provided.
- """
- cli.print_help()
-
-
-def main():
- """Setup our environment and then call the CLI entrypoint.
- """
- # Change to the root of our checkout
- os.environ['ORIG_CWD'] = os.getcwd()
- os.environ['DEPRECATED_BIN_QMK'] = '1'
- os.chdir(qmk_dir)
-
- print('Warning: The bin/qmk script is being deprecated. Please install the QMK CLI: python3 -m pip install qmk', file=sys.stderr)
-
- # Import the subcommands
- import milc.subcommand.config # noqa
- import qmk.cli # noqa
-
- # Execute
- return_code = milc.cli()
-
- if return_code is False:
- exit(1)
-
- elif return_code is not True and isinstance(return_code, int):
- if return_code < 0 or return_code > 255:
- milc.cli.log.error('Invalid return_code: %d', return_code)
- exit(255)
-
- exit(return_code)
-
- exit(0)
-
-
-if __name__ == '__main__':
- main()
diff --git a/build_keyboard.mk b/build_keyboard.mk
index 37fa6852f8..420643c3e7 100644
--- a/build_keyboard.mk
+++ b/build_keyboard.mk
@@ -115,6 +115,7 @@ include $(INFO_RULES_MK)
# Check for keymap.json first, so we can regenerate keymap.c
include build_json.mk
+# Pull in keymap level rules.mk
ifeq ("$(wildcard $(KEYMAP_PATH))", "")
# Look through the possible keymap folders until we find a matching keymap.c
ifneq ("$(wildcard $(MAIN_KEYMAP_PATH_5)/keymap.c)","")
@@ -345,6 +346,7 @@ ifeq ("$(USER_NAME)","")
endif
USER_PATH := users/$(USER_NAME)
+# Pull in user level rules.mk
-include $(USER_PATH)/rules.mk
ifneq ("$(wildcard $(USER_PATH)/config.h)","")
CONFIG_H += $(USER_PATH)/config.h
@@ -356,6 +358,23 @@ endif
# Disable features that a keyboard doesn't support
-include disable_features.mk
+# Pull in post_rules.mk files from all our subfolders
+ifneq ("$(wildcard $(KEYBOARD_PATH_1)/post_rules.mk)","")
+ include $(KEYBOARD_PATH_1)/post_rules.mk
+endif
+ifneq ("$(wildcard $(KEYBOARD_PATH_2)/post_rules.mk)","")
+ include $(KEYBOARD_PATH_2)/post_rules.mk
+endif
+ifneq ("$(wildcard $(KEYBOARD_PATH_3)/post_rules.mk)","")
+ include $(KEYBOARD_PATH_3)/post_rules.mk
+endif
+ifneq ("$(wildcard $(KEYBOARD_PATH_4)/post_rules.mk)","")
+ include $(KEYBOARD_PATH_4)/post_rules.mk
+endif
+ifneq ("$(wildcard $(KEYBOARD_PATH_5)/post_rules.mk)","")
+ include $(KEYBOARD_PATH_5)/post_rules.mk
+endif
+
ifneq ("$(wildcard $(KEYMAP_PATH)/config.h)","")
CONFIG_H += $(KEYMAP_PATH)/config.h
endif
diff --git a/docs/cli_commands.md b/docs/cli_commands.md
index 8fa7ad41dc..06568afb46 100644
--- a/docs/cli_commands.md
+++ b/docs/cli_commands.md
@@ -118,54 +118,6 @@ This command lets you configure the behavior of QMK. For the full `qmk config` d
qmk config [-ro] [config_token1] [config_token2] [...] [config_tokenN]
```
-## `qmk console`
-
-This command lets you connect to keyboard consoles to get debugging messages. It only works if your keyboard firmware has been compiled with `CONSOLE_ENABLE=yes`.
-
-**Usage**:
-
-```
-qmk console [-d <pid>:<vid>[:<index>]] [-l] [-n] [-t] [-w <seconds>]
-```
-
-**Examples**:
-
-Connect to all available keyboards and show their console messages:
-
-```
-qmk console
-```
-
-List all devices:
-
-```
-qmk console -l
-```
-
-Show only messages from clueboard/66/rev3 keyboards:
-
-```
-qmk console -d C1ED:2370
-```
-
-Show only messages from the second clueboard/66/rev3:
-
-```
-qmk console -d C1ED:2370:2
-```
-
-Show timestamps and VID:PID instead of names:
-
-```
-qmk console -n -t
-```
-
-Disable bootloader messages:
-
-```
-qmk console --no-bootloaders
-```
-
## `qmk doctor`
This command examines your environment and alerts you to potential build or flash problems. It can fix many of them if you want it to.
diff --git a/docs/contributing.md b/docs/contributing.md
index 1d68d22d9f..eb033d167f 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -105,7 +105,7 @@ enum my_keycodes {
Before opening a pull request, you can preview your changes if you have set up the development environment by running this command from the `qmk_firmware/` folder:
- ./bin/qmk docs
+ qmk docs
or if you only have Python 3 installed:
diff --git a/docs/de/cli.md b/docs/de/cli.md
index 7dc02d505b..259aeecf75 100644
--- a/docs/de/cli.md
+++ b/docs/de/cli.md
@@ -51,25 +51,6 @@ Wir suchen nach Freiwilligen, die ein `qmk`-Package für weitere Betriebssysteme
* Installiere mit einem [virtualenv](https://virtualenv.pypa.io/en/latest/).
* Weise den User an, die Umgebungs-Variable `QMK_HOME` zu setzen, um die Firmware-Quelle anders einzustellen als `~/qmk_firmware`.
-# Lokale CLI
-
-Wenn Du die globale CLI nicht verwenden möchtest, beinhaltet `qmk_firmware` auch eine lokale CLI. Du kannst sie hier finden: `qmk_firmware/bin/qmk`. Du kannst den `qmk`-Befehl aus irgendeinem Datei-Verzeichnis ausführen und es wird immer auf dieser Kopie von `qmk_firmware` arbeiten.
-
-**Beispiel**:
-
-```
-$ ~/qmk_firmware/bin/qmk hello
-Ψ Hello, World!
-```
-
-## Einschränkungen der lokalen CLI
-
-Hier ein Vergleich mit der globalen CLI:
-
-* Die lokale CLI unterstützt kein `qmk setup` oder `qmk clone`.
-* Die lokale CLI arbeitet immer innerhalb der selben `qmk_firmware`-Verzeichnisstruktur, auch wenn Du mehrere Repositories geklont hast.
-* Die lokale CLI läuft nicht in einer virtualenv. Daher ist es möglich, dass Abhängigkeiten (dependencies) miteinander in Konflikt kommen/stehen.
-
# CLI-Befehle
## `qmk compile`
diff --git a/docs/fr-fr/cli.md b/docs/fr-fr/cli.md
index bfa060f2ad..917a9315bc 100644
--- a/docs/fr-fr/cli.md
+++ b/docs/fr-fr/cli.md
@@ -48,25 +48,6 @@ Nous recherchons des gens pour créer et maintenir un paquet `qmk` pour plus de
* Installez en utilisant un virtualenv
* Expliquez à l'utilisateur de définir la variable d'environnement `QMK_Home` pour "check out" les sources du firmware à un autre endroit que `~/qmk_firmware`.
-# CLI locale
-
-Si vous ne voulez pas utiliser la CLI globale, il y a une CLI locale empaquetée avec `qmk_firmware`. Vous pouvez le trouver dans `qmk_firmware/bin/qmk`. Vous pouvez lancer la commande `qmk` depuis n'importe quel répertoire et elle fonctionnera toujours sur cette copie de `qmk_firmware`.
-
-**Exemple**:
-
-```
-$ ~/qmk_firmware/bin/qmk hello
-Ψ Hello, World!
-```
-
-## Limitations de la CLI locale
-
-Il y a quelques limitations à la CLI locale comparé à la globale:
-
-* La CLI locale ne supporte pas `qmk setup` ou `qmk clone`
-* La CLI locale n'opère pas sur le même arbre `qmk_firmware`, même si vous avez plusieurs dépôts clonés.
-* La CLI locale ne s'exécute pas dans un virtualenv, donc il y a des risques que des dépendances seront en conflit
-
# Les commandes CLI
## `qmk compile`
diff --git a/docs/hardware_keyboard_guidelines.md b/docs/hardware_keyboard_guidelines.md
index 7630b44e0c..17be7ee6aa 100644
--- a/docs/hardware_keyboard_guidelines.md
+++ b/docs/hardware_keyboard_guidelines.md
@@ -144,10 +144,38 @@ The `rules.mk` file can also be placed in a sub-folder, and its reading order is
* `keyboards/top_folder/sub_1/sub_2/sub_3/sub_4/rules.mk`
* `keyboards/top_folder/keymaps/a_keymap/rules.mk`
* `users/a_user_folder/rules.mk`
+ * `keyboards/top_folder/sub_1/sub_2/sub_3/sub_4/post_rules.mk`
+ * `keyboards/top_folder/sub_1/sub_2/sub_3/post_rules.mk`
+ * `keyboards/top_folder/sub_1/sub_2/post_rules.mk`
+ * `keyboards/top_folder/sub_1/post_rules.mk`
+* `keyboards/top_folder/post_rules.mk`
* `common_features.mk`
Many of the settings written in the `rules.mk` file are interpreted by `common_features.mk`, which sets the necessary source files and compiler options.
+The `post_rules.mk` file can interpret `features` of a keyboard-level before `common_features.mk`. For example, when your designed keyboard has the option to implement backlighting or underglow using rgblight.c, writing the following in the `post_rules.mk` makes it easier for the user to configure the `rules.mk`.
+
+* `keyboards/top_folder/keymaps/a_keymap/rules.mk`
+ ```makefile
+ # Please set the following according to the selection of the hardware implementation option.
+ RGBLED_OPTION_TYPE = backlight ## none, backlight or underglow
+ ```
+* `keyboards/top_folder/post_rules.mk`
+ ```makefile
+ ifeq ($(filter $(strip $(RGBLED_OPTION_TYPE))x, nonex backlightx underglowx x),)
+ $(error unknown RGBLED_OPTION_TYPE value "$(RGBLED_OPTION_TYPE)")
+ endif
+
+ ifeq ($(strip $(RGBLED_OPTION_TYPE)),backlight)
+ RGBLIGHT_ENABLE = yes
+ OPT_DEFS += -DRGBLED_NUM=30
+ endif
+ ifeq ($(strip $(RGBLED_OPTION_TYPE)),underglow)
+ RGBLIGHT_ENABLE = yes
+ OPT_DEFS += -DRGBLED_NUM=6
+ endif
+ ```
+
?> See `build_keyboard.mk` and `common_features.mk` for more details.
### `<keyboard_name.c>`
diff --git a/keyboards/dztech/dz65rgb/keymaps/jumper149/readme.md b/keyboards/dztech/dz65rgb/keymaps/jumper149/readme.md
index d872587317..9de86be2d1 100644
--- a/keyboards/dztech/dz65rgb/keymaps/jumper149/readme.md
+++ b/keyboards/dztech/dz65rgb/keymaps/jumper149/readme.md
@@ -3,13 +3,13 @@
Run commands in the root directory of this repository.
```
-./bin/qmk compile && sudo dfu-programmer atmega32u4 erase && sudo dfu-programmer atmega32u4 flash ./dztech_dz65rgb_v2_jumper149.hex && sudo dfu-programmer atmega32u4 reset
+qmk compile && sudo dfu-programmer atmega32u4 erase && sudo dfu-programmer atmega32u4 flash ./dztech_dz65rgb_v2_jumper149.hex && sudo dfu-programmer atmega32u4 reset
```
## build
```
-./bin/qmk compile
+qmk compile
```
## flash
diff --git a/lib/python/qmk/cli/__init__.py b/lib/python/qmk/cli/__init__.py
index f45e33240c..292dcbe812 100644
--- a/lib/python/qmk/cli/__init__.py
+++ b/lib/python/qmk/cli/__init__.py
@@ -35,7 +35,6 @@ subcommands = [
'qmk.cli.chibios.confmigrate',
'qmk.cli.clean',
'qmk.cli.compile',
- 'qmk.cli.console',
'qmk.cli.docs',
'qmk.cli.doctor',
'qmk.cli.fileformat',
diff --git a/lib/python/qmk/cli/console.py b/lib/python/qmk/cli/console.py
deleted file mode 100644
index 3c508160e3..0000000000
--- a/lib/python/qmk/cli/console.py
+++ /dev/null
@@ -1,303 +0,0 @@
-"""Acquire debugging information from usb hid devices
-
-cli implementation of https://www.pjrc.com/teensy/hid_listen.html
-"""
-from pathlib import Path
-from threading import Thread
-from time import sleep, strftime
-
-import hid
-import usb.core
-
-from milc import cli
-
-LOG_COLOR = {
- 'next': 0,
- 'colors': [
- '{fg_blue}',
- '{fg_cyan}',
- '{fg_green}',
- '{fg_magenta}',
- '{fg_red}',
- '{fg_yellow}',
- ],
-}
-
-KNOWN_BOOTLOADERS = {
- # VID , PID
- ('03EB', '2FEF'): 'atmel-dfu: ATmega16U2',
- ('03EB', '2FF0'): 'atmel-dfu: ATmega32U2',
- ('03EB', '2FF3'): 'atmel-dfu: ATmega16U4',
- ('03EB', '2FF4'): 'atmel-dfu: ATmega32U4',
- ('03EB', '2FF9'): 'atmel-dfu: AT90USB64',
- ('03EB', '2FFA'): 'atmel-dfu: AT90USB162',
- ('03EB', '2FFB'): 'atmel-dfu: AT90USB128',
- ('03EB', '6124'): 'Microchip SAM-BA',
- ('0483', 'DF11'): 'stm32-dfu: STM32 BOOTLOADER',
- ('16C0', '05DC'): 'USBasp: USBaspLoader',
- ('16C0', '05DF'): 'bootloadHID: HIDBoot',
- ('16C0', '0478'): 'halfkay: Teensy Halfkay',
- ('1B4F', '9203'): 'caterina: Pro Micro 3.3V',
- ('1B4F', '9205'): 'caterina: Pro Micro 5V',
- ('1B4F', '9207'): 'caterina: LilyPadUSB',
- ('1C11', 'B007'): 'kiibohd: Kiibohd DFU Bootloader',
- ('1EAF', '0003'): 'stm32duino: Maple 003',
- ('1FFB', '0101'): 'caterina: Polou A-Star 32U4 Bootloader',
- ('2341', '0036'): 'caterina: Arduino Leonardo',
- ('2341', '0037'): 'caterina: Arduino Micro',
- ('239A', '000C'): 'caterina: Adafruit Feather 32U4',
- ('239A', '000D'): 'caterina: Adafruit ItsyBitsy 32U4 3v',
- ('239A', '000E'): 'caterina: Adafruit ItsyBitsy 32U4 5v',
- ('2A03', '0036'): 'caterina: Arduino Leonardo',
- ('2A03', '0037'): 'caterina: Arduino Micro',
- ('314B', '0106'): 'apm32-dfu: APM32 DFU ISP Mode',
- ('03EB', '2067'): 'qmk-hid: HID Bootloader',
- ('03EB', '2045'): 'lufa-ms: LUFA Mass Storage Bootloader'
-}
-
-
-class MonitorDevice(object):
- def __init__(self, hid_device, numeric):
- self.hid_device = hid_device
- self.numeric = numeric
- self.device = hid.Device(path=hid_device['path'])
- self.current_line = ''
-
- cli.log.info('Console Connected: %(color)s%(manufacturer_string)s %(product_string)s{style_reset_all} (%(color)s%(vendor_id)04X:%(product_id)04X:%(index)d{style_reset_all})', hid_device)
-
- def read(self, size, encoding='ascii', timeout=1):
- """Read size bytes from the device.
- """
- return self.device.read(size, timeout).decode(encoding)
-
- def read_line(self):
- """Read from the device's console until we get a \n.
- """
- while '\n' not in self.current_line:
- self.current_line += self.read(32).replace('\x00', '')
-
- lines = self.current_line.split('\n', 1)
- self.current_line = lines[1]
-
- return lines[0]
-
- def run_forever(self):
- while True:
- try:
- message = {**self.hid_device, 'text': self.read_line()}
- identifier = (int2hex(message['vendor_id']), int2hex(message['product_id'])) if self.numeric else (message['manufacturer_string'], message['product_string'])
- message['identifier'] = ':'.join(identifier)
- message['ts'] = '{style_dim}{fg_green}%s{style_reset_all} ' % (strftime(cli.config.general.datetime_fmt),) if cli.args.timestamp else ''
-
- cli.echo('%(ts)s%(color)s%(identifier)s:%(index)d{style_reset_all}: %(text)s' % message)
-
- except hid.HIDException:
- break
-
-
-class FindDevices(object):
- def __init__(self, vid, pid, index, numeric):
- self.vid = vid
- self.pid = pid
- self.index = index
- self.numeric = numeric
-
- def run_forever(self):
- """Process messages from our queue in a loop.
- """
- live_devices = {}
- live_bootloaders = {}
-
- while True:
- try:
- for device in list(live_devices):
- if not live_devices[device]['thread'].is_alive():
- cli.log.info('Console Disconnected: %(color)s%(manufacturer_string)s %(product_string)s{style_reset_all} (%(color)s%(vendor_id)04X:%(product_id)04X:%(index)d{style_reset_all})', live_devices[device])
- del live_devices[device]
-
- for device in self.find_devices():
- if device['path'] not in live_devices:
- device['color'] = LOG_COLOR['colors'][LOG_COLOR['next']]
- LOG_COLOR['next'] = (LOG_COLOR['next'] + 1) % len(LOG_COLOR['colors'])
- live_devices[device['path']] = device
-
- try:
- monitor = MonitorDevice(device, self.numeric)
- device['thread'] = Thread(target=monitor.run_forever, daemon=True)
-
- device['thread'].start()
- except Exception as e:
- device['e'] = e
- device['e_name'] = e.__class__.__name__
- cli.log.error("Could not connect to %(color)s%(manufacturer_string)s %(product_string)s{style_reset_all} (%(color)s:%(vendor_id)04X:%(product_id)04X:%(index)d): %(e_name)s: %(e)s", device)
- if cli.config.general.verbose:
- cli.log.exception(e)
- del live_devices[device['path']]
-
- if cli.args.bootloaders:
- for device in self.find_bootloaders():
- if device.address in live_bootloaders:
- live_bootloaders[device.address]._qmk_found = True
- else:
- name = KNOWN_BOOTLOADERS[(int2hex(device.idVendor), int2hex(device.idProduct))]
- cli.log.info('Bootloader Connected: {style_bright}{fg_magenta}%s', name)
- device._qmk_found = True
- live_bootloaders[device.address] = device
-
- for device in list(live_bootloaders):
- if live_bootloaders[device]._qmk_found:
- live_bootloaders[device]._qmk_found = False
- else:
- name = KNOWN_BOOTLOADERS[(int2hex(live_bootloaders[device].idVendor), int2hex(live_bootloaders[device].idProduct))]
- cli.log.info('Bootloader Disconnected: {style_bright}{fg_magenta}%s', name)
- del live_bootloaders[device]
-
- sleep(.1)
-
- except KeyboardInterrupt:
- break
-
- def is_bootloader(self, hid_device):
- """Returns true if the device in question matches a known bootloader vid/pid.
- """
- return (int2hex(hid_device.idVendor), int2hex(hid_device.idProduct)) in KNOWN_BOOTLOADERS
-
- def is_console_hid(self, hid_device):
- """Returns true when the usage page indicates it's a teensy-style console.
- """
- return hid_device['usage_page'] == 0xFF31 and hid_device['usage'] == 0x0074
-
- def is_filtered_device(self, hid_device):
- """Returns True if the device should be included in the list of available consoles.
- """
- return int2hex(hid_device['vendor_id']) == self.vid and int2hex(hid_device['product_id']) == self.pid
-
- def find_devices_by_report(self, hid_devices):
- """Returns a list of available teensy-style consoles by doing a brute-force search.
-
- Some versions of linux don't report usage and usage_page. In that case we fallback to reading the report (possibly inaccurately) ourselves.
- """
- devices = []
-
- for device in hid_devices:
- path = device['path'].decode('utf-8')
-
- if path.startswith('/dev/hidraw'):
- number = path[11:]
- report = Path(f'/sys/class/hidraw/hidraw{number}/device/report_descriptor')
-
- if report.exists():
- rp = report.read_bytes()
-
- if rp[1] == 0x31 and rp[3] == 0x09:
- devices.append(device)
-
- return devices
-
- def find_bootloaders(self):
- """Returns a list of available bootloader devices.
- """
- return list(filter(self.is_bootloader, usb.core.find(find_all=True)))
-
- def find_devices(self):
- """Returns a list of available teensy-style consoles.
- """
- hid_devices = hid.enumerate()
- devices = list(filter(self.is_console_hid, hid_devices))
-
- if not devices:
- devices = self.find_devices_by_report(hid_devices)
-
- if self.vid and self.pid:
- devices = list(filter(self.is_filtered_device, devices))
-
- # Add index numbers
- device_index = {}
- for device in devices:
- id = ':'.join((int2hex(device['vendor_id']), int2hex(device['product_id'])))
-
- if id not in device_index:
- device_index[id] = 0
-
- device_index[id] += 1
- device['index'] = device_index[id]
-
- return devices
-
-
-def int2hex(number):
- """Returns a string representation of the number as hex.
- """
- return "%04X" % number
-
-
-def list_devices(device_finder):
- """Show the user a nicely formatted list of devices.
- """
- devices = device_finder.find_devices()
-
- if devices:
- cli.log.info('Available devices:')
- for dev in devices:
- color = LOG_COLOR['colors'][LOG_COLOR['next']]
- LOG_COLOR['next'] = (LOG_COLOR['next'] + 1) % len(LOG_COLOR['colors'])
- cli.log.info("\t%s%s:%s:%d{style_reset_all}\t%s %s", color, int2hex(dev['vendor_id']), int2hex(dev['product_id']), dev['index'], dev['manufacturer_string'], dev['product_string'])
-
- if cli.args.bootloaders:
- bootloaders = device_finder.find_bootloaders()
-
- if bootloaders:
- cli.log.info('Available Bootloaders:')
-
- for dev in bootloaders:
- cli.log.info("\t%s:%s\t%s", int2hex(dev.idVendor), int2hex(dev.idProduct), KNOWN_BOOTLOADERS[(int2hex(dev.idVendor), int2hex(dev.idProduct))])
-
-
-@cli.argument('--bootloaders', arg_only=True, default=True, action='store_boolean', help='displaying bootloaders.')
-@cli.argument('-d', '--device', help='Device to select - uses format <pid>:<vid>[:<index>].')
-@cli.argument('-l', '--list', arg_only=True, action='store_true', help='List available hid_listen devices.')
-@cli.argument('-n', '--numeric', arg_only=True, action='store_true', help='Show VID/PID instead of names.')
-@cli.argument('-t', '--timestamp', arg_only=True, action='store_true', help='Print the timestamp for received messages as well.')
-@cli.argument('-w', '--wait', type=int, default=1, help="How many seconds to wait between checks (Default: 1)")
-@cli.subcommand('Acquire debugging information from usb hid devices.', hidden=False if cli.config.user.developer else True)
-def console(cli):
- """Acquire debugging information from usb hid devices
- """
- vid = None
- pid = None
- index = 1
-
- if cli.config.console.device:
- device = cli.config.console.device.split(':')
-
- if len(device) == 2:
- vid, pid = device
-
- elif len(device) == 3:
- vid, pid, index = device
-
- if not index.isdigit():
- cli.log.error('Device index must be a number! Got "%s" instead.', index)
- exit(1)
-
- index = int(index)
-
- if index < 1:
- cli.log.error('Device index must be greater than 0! Got %s', index)
- exit(1)
-
- else:
- cli.log.error('Invalid format for device, expected "<pid>:<vid>[:<index>]" but got "%s".', cli.config.console.device)
- cli.print_help()
- exit(1)
-
- vid = vid.upper()
- pid = pid.upper()
-
- device_finder = FindDevices(vid, pid, index, cli.args.numeric)
-
- if cli.args.list:
- return list_devices(device_finder)
-
- print('Looking for devices...', flush=True)
- device_finder.run_forever()
diff --git a/lib/python/qmk/cli/doctor/check.py b/lib/python/qmk/cli/doctor/check.py
index 0807f41518..2d691b64b0 100644
--- a/lib/python/qmk/cli/doctor/check.py
+++ b/lib/python/qmk/cli/doctor/check.py
@@ -26,7 +26,6 @@ ESSENTIAL_BINARIES = {
'arm-none-eabi-gcc': {
'version_arg': '-dumpversion'
},
- 'bin/qmk': {},
}
diff --git a/lib/python/qmk/cli/format/python.py b/lib/python/qmk/cli/format/python.py
index 00612f97ec..b32a726401 100755
--- a/lib/python/qmk/cli/format/python.py
+++ b/lib/python/qmk/cli/format/python.py
@@ -11,15 +11,15 @@ def format_python(cli):
"""Format python code according to QMK's style.
"""
edit = '--diff' if cli.args.dry_run else '--in-place'
- yapf_cmd = ['yapf', '-vv', '--recursive', edit, 'bin/qmk', 'lib/python']
+ yapf_cmd = ['yapf', '-vv', '--recursive', edit, 'lib/python']
try:
cli.run(yapf_cmd, check=True, capture_output=False, stdin=DEVNULL)
- cli.log.info('Python code in `bin/qmk` and `lib/python` is correctly formatted.')
+ cli.log.info('Python code in `lib/python` is correctly formatted.')
return True
except CalledProcessError:
if cli.args.dry_run:
- cli.log.error('Python code in `bin/qmk` and `lib/python` incorrectly formatted!')
+ cli.log.error('Python code in `lib/python` is incorrectly formatted!')
else:
cli.log.error('Error formatting python code!')
diff --git a/lib/python/qmk/cli/lint.py b/lib/python/qmk/cli/lint.py
index 02b31fbc41..96593ed69b 100644
--- a/lib/python/qmk/cli/lint.py
+++ b/lib/python/qmk/cli/lint.py
@@ -1,72 +1,129 @@
"""Command to look over a keyboard/keymap and check for common mistakes.
"""
+from pathlib import Path
+
from milc import cli
from qmk.decorators import automagic_keyboard, automagic_keymap
from qmk.info import info_json
-from qmk.keyboard import find_readme, keyboard_completer
+from qmk.keyboard import keyboard_completer, list_keyboards
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', completer=keyboard_completer, help='The keyboard to check.')
-@cli.argument('-km', '--keymap', help='The keymap to check.')
+def keymap_check(kb, km):
+ """Perform the keymap level checks.
+ """
+ ok = True
+ keymap_path = locate_keymap(kb, km)
+
+ if not keymap_path:
+ ok = False
+ cli.log.error("%s: Can't find %s keymap.", kb, km)
+
+ return ok
+
+
+def rules_mk_assignment_only(keyboard_path):
+ """Check the keyboard-level rules.mk to ensure it only has assignments.
+ """
+ current_path = Path()
+ errors = []
+
+ for path_part in keyboard_path.parts:
+ current_path = current_path / path_part
+ rules_mk = current_path / 'rules.mk'
+
+ if rules_mk.exists():
+ continuation = None
+
+ for i, line in enumerate(rules_mk.open()):
+ line = line.strip()
+
+ if '#' in line:
+ line = line[:line.index('#')]
+
+ if continuation:
+ line = continuation + line
+ continuation = None
+
+ if line:
+ if line[-1] == '\\':
+ continuation = line[:-1]
+ continue
+
+ if line and '=' not in line:
+ errors.append(f'Non-assignment code on line +{i} {rules_mk}: {line}')
+
+ return errors
+
+
+@cli.argument('--strict', action='store_true', help='Treat warnings as errors')
+@cli.argument('-kb', '--keyboard', completer=keyboard_completer, help='Comma separated list of keyboards to check')
+@cli.argument('-km', '--keymap', help='The keymap to check')
+@cli.argument('--all-kb', action='store_true', arg_only=True, help='Check all keyboards')
@cli.subcommand('Check keyboard and keymap for common mistakes.')
@automagic_keyboard
@automagic_keymap
def lint(cli):
"""Check keyboard and keymap for common mistakes.
"""
- if not cli.config.lint.keyboard:
- cli.log.error('Missing required argument: --keyboard')
- cli.print_help()
- return False
+ failed = []
- if not is_keyboard(cli.config.lint.keyboard):
- cli.log.error('No such keyboard: %s', cli.config.lint.keyboard)
- return False
+ # Determine our keyboard list
+ if cli.args.all_kb:
+ if cli.args.keyboard:
+ cli.log.warning('Both --all-kb and --keyboard passed, --all-kb takes presidence.')
- # Gather data about the keyboard.
- ok = True
- keyboard_path = keyboard(cli.config.lint.keyboard)
- keyboard_info = info_json(cli.config.lint.keyboard)
- readme_path = find_readme(cli.config.lint.keyboard)
- missing_readme_path = keyboard_path / 'readme.md'
+ keyboard_list = list_keyboards()
+ elif not cli.config.lint.keyboard:
+ cli.log.error('Missing required arguments: --keyboard or --all-kb')
+ cli.print_help()
+ return False
+ else:
+ keyboard_list = cli.config.lint.keyboard.split(',')
- # Check for errors in the info.json
- if keyboard_info['parse_errors']:
- ok = False
- cli.log.error('Errors found when generating info.json.')
+ # Lint each keyboard
+ for kb in keyboard_list:
+ if not is_keyboard(kb):
+ cli.log.error('No such keyboard: %s', kb)
+ continue
- if cli.config.lint.strict and keyboard_info['parse_warnings']:
- ok = False
- cli.log.error('Warnings found when generating info.json (Strict mode enabled.)')
+ # Gather data about the keyboard.
+ ok = True
+ keyboard_path = keyboard(kb)
+ keyboard_info = info_json(kb)
- # Check for a readme.md and warn if it doesn't exist
- if not readme_path:
- ok = False
- cli.log.error('Missing %s', missing_readme_path)
+ # Check for errors in the info.json
+ if keyboard_info['parse_errors']:
+ ok = False
+ cli.log.error('%s: Errors found when generating info.json.', kb)
- # Keymap specific checks
- if cli.config.lint.keymap:
- keymap_path = locate_keymap(cli.config.lint.keyboard, cli.config.lint.keymap)
+ if cli.config.lint.strict and keyboard_info['parse_warnings']:
+ ok = False
+ cli.log.error('%s: Warnings found when generating info.json (Strict mode enabled.)', kb)
- if not keymap_path:
+ # Check the rules.mk file(s)
+ rules_mk_assignment_errors = rules_mk_assignment_only(keyboard_path)
+ if rules_mk_assignment_errors:
ok = False
- cli.log.error("Can't find %s keymap for %s keyboard.", cli.config.lint.keymap, cli.config.lint.keyboard)
- else:
- keymap_readme = keymap_path.parent / 'readme.md'
- if not keymap_readme.exists():
- cli.log.warning('Missing %s', keymap_readme)
+ cli.log.error('%s: Non-assignment code found in rules.mk. Move it to post_rules.mk instead.', kb)
+ for assignment_error in rules_mk_assignment_errors:
+ cli.log.error(assignment_error)
- if cli.config.lint.strict:
- ok = False
+ # Keymap specific checks
+ if cli.config.lint.keymap:
+ if not keymap_check(kb, cli.config.lint.keymap):
+ ok = False
+
+ # Report status
+ if not ok:
+ failed.append(kb)
# Check and report the overall status
- if ok:
- cli.log.info('Lint check passed!')
- return True
+ if failed:
+ cli.log.error('Lint check failed for: %s', ', '.join(failed))
+ return False
- cli.log.error('Lint check failed!')
- return False
+ cli.log.info('Lint check passed!')
+ return True
diff --git a/lib/python/qmk/cli/pytest.py b/lib/python/qmk/cli/pytest.py
index bdb336b9a7..a7f01a872a 100644
--- a/lib/python/qmk/cli/pytest.py
+++ b/lib/python/qmk/cli/pytest.py
@@ -12,6 +12,6 @@ def pytest(cli):
"""Run several linting/testing commands.
"""
nose2 = cli.run(['nose2', '-v'], capture_output=False, stdin=DEVNULL)
- flake8 = cli.run(['flake8', 'lib/python', 'bin/qmk'], capture_output=False, stdin=DEVNULL)
+ flake8 = cli.run(['flake8', 'lib/python'], capture_output=False, stdin=DEVNULL)
return flake8.returncode | nose2.returncode
diff --git a/lib/python/qmk/commands.py b/lib/python/qmk/commands.py
index 421453d837..01c23b2612 100644
--- a/lib/python/qmk/commands.py
+++ b/lib/python/qmk/commands.py
@@ -233,7 +233,7 @@ def compile_configurator_json(user_keymap, bootloader=None, parallel=1, **env_va
f'VERBOSE={verbose}',
f'COLOR={color}',
'SILENT=false',
- f'QMK_BIN={"bin/qmk" if "DEPRECATED_BIN_QMK" in os.environ else "qmk"}',
+ 'QMK_BIN="qmk"',
])
return make_command
diff --git a/lib/python/qmk/tests/test_cli_commands.py b/lib/python/qmk/tests/test_cli_commands.py
index b39fe5e46d..e4eaef899a 100644
--- a/lib/python/qmk/tests/test_cli_commands.py
+++ b/lib/python/qmk/tests/test_cli_commands.py
@@ -83,7 +83,7 @@ def test_hello():
def test_format_python():
result = check_subcommand('format-python', '--dry-run')
check_returncode(result)
- assert 'Python code in `bin/qmk` and `lib/python` is correctly formatted.' in result.stdout
+ assert 'Python code in `lib/python` is correctly formatted.' in result.stdout
def test_list_keyboards():
diff --git a/shell.nix b/shell.nix
index c36df032de..5023a3b0f7 100644
--- a/shell.nix
+++ b/shell.nix
@@ -14,7 +14,7 @@ let
projectDir = ./util/nix;
overrides = poetry2nix.overrides.withDefaults (self: super: {
qmk = super.qmk.overridePythonAttrs(old: {
- # Allow QMK CLI to run "bin/qmk" as a subprocess (the wrapper changes
+ # Allow QMK CLI to run "qmk" as a subprocess (the wrapper changes
# $PATH and breaks these invocations).
dontWrapPythonPrograms = true;
});