From 2e279f1b889a59156f30524cc83358f64ee53287 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Tue, 8 Feb 2022 19:03:30 +0000 Subject: [PATCH] Initial pass at data driven new-keyboard subcommand (#12795) * Initial pass at a data driven keyboard subcommand * format * lint * Handle bootloader now its mandatory --- data/templates/avr/config.h | 134 -------- data/templates/avr/rules.mk | 18 -- data/templates/base/%(KEYBOARD)s.c | 4 - data/templates/base/%(KEYBOARD)s.h | 22 -- data/templates/base/info.json | 17 - data/templates/base/keymaps/default/keymap.c | 22 -- data/templates/base/keymaps/default/readme.md | 1 - data/templates/keyboard/info.json | 24 ++ data/templates/{avr => keyboard}/readme.md | 10 +- data/templates/keyboard/rules.mk | 1 + data/templates/ps2avrgb/config.h | 124 ------- data/templates/ps2avrgb/readme.md | 28 -- data/templates/ps2avrgb/rules.mk | 17 - docs/cli_commands.md | 2 +- lib/python/qmk/cli/new/keyboard.py | 303 ++++++++++++------ lib/python/qmk/path.py | 2 +- util/new_keyboard.sh | 181 ----------- util/new_keymap.sh | 40 --- 18 files changed, 242 insertions(+), 708 deletions(-) delete mode 100644 data/templates/avr/config.h delete mode 100644 data/templates/avr/rules.mk delete mode 100644 data/templates/base/%(KEYBOARD)s.c delete mode 100644 data/templates/base/%(KEYBOARD)s.h delete mode 100644 data/templates/base/info.json delete mode 100644 data/templates/base/keymaps/default/keymap.c delete mode 100644 data/templates/base/keymaps/default/readme.md create mode 100644 data/templates/keyboard/info.json rename data/templates/{avr => keyboard}/readme.md (82%) create mode 100644 data/templates/keyboard/rules.mk delete mode 100644 data/templates/ps2avrgb/config.h delete mode 100644 data/templates/ps2avrgb/readme.md delete mode 100644 data/templates/ps2avrgb/rules.mk delete mode 100755 util/new_keyboard.sh delete mode 100755 util/new_keymap.sh diff --git a/data/templates/avr/config.h b/data/templates/avr/config.h deleted file mode 100644 index 97f7bb6fad1..00000000000 --- a/data/templates/avr/config.h +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright %(YEAR)s %(YOUR_NAME)s (@%(USER_NAME)s) -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "config_common.h" - -/* USB Device descriptor parameter */ -#define VENDOR_ID 0xFEED -#define PRODUCT_ID 0x0000 -#define DEVICE_VER 0x0001 -#define MANUFACTURER %(USER_NAME)s -#define PRODUCT %(KEYBOARD)s - -/* key matrix size */ -#define MATRIX_ROWS 2 -#define MATRIX_COLS 3 - -/* - * Keyboard Matrix Assignments - * - * Change this to how you wired your keyboard - * COLS: AVR pins used for columns, left to right - * ROWS: AVR pins used for rows, top to bottom - * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode) - * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode) - * - */ -#define MATRIX_ROW_PINS { D0, D5 } -#define MATRIX_COL_PINS { F1, F0, B0 } -#define UNUSED_PINS - -/* COL2ROW, ROW2COL */ -#define DIODE_DIRECTION COL2ROW - -/* - * Split Keyboard specific options, make sure you have 'SPLIT_KEYBOARD = yes' in your rules.mk, and define SOFT_SERIAL_PIN. - */ -#define SOFT_SERIAL_PIN D0 // or D1, D2, D3, E6 - -//#define LED_NUM_LOCK_PIN B0 -//#define LED_CAPS_LOCK_PIN B1 -//#define LED_SCROLL_LOCK_PIN B2 -//#define LED_COMPOSE_PIN B3 -//#define LED_KANA_PIN B4 - -//#define BACKLIGHT_PIN B7 -//#define BACKLIGHT_LEVELS 3 -//#define BACKLIGHT_BREATHING - -//#define RGB_DI_PIN E2 -//#ifdef RGB_DI_PIN -//# define RGBLED_NUM 16 -//# define RGBLIGHT_HUE_STEP 8 -//# define RGBLIGHT_SAT_STEP 8 -//# define RGBLIGHT_VAL_STEP 8 -//# define RGBLIGHT_LIMIT_VAL 255 /* The maximum brightness level */ -//# define RGBLIGHT_SLEEP /* If defined, the RGB lighting will be switched off when the host goes to sleep */ -/*== all animations enable ==*/ -//# define RGBLIGHT_ANIMATIONS -/*== or choose animations ==*/ -//# define RGBLIGHT_EFFECT_BREATHING -//# define RGBLIGHT_EFFECT_RAINBOW_MOOD -//# define RGBLIGHT_EFFECT_RAINBOW_SWIRL -//# define RGBLIGHT_EFFECT_SNAKE -//# define RGBLIGHT_EFFECT_KNIGHT -//# define RGBLIGHT_EFFECT_CHRISTMAS -//# define RGBLIGHT_EFFECT_STATIC_GRADIENT -//# define RGBLIGHT_EFFECT_RGB_TEST -//# define RGBLIGHT_EFFECT_ALTERNATING -/*== customize breathing effect ==*/ -/*==== (DEFAULT) use fixed table instead of exp() and sin() ====*/ -//# define RGBLIGHT_BREATHE_TABLE_SIZE 256 // 256(default) or 128 or 64 -/*==== use exp() and sin() ====*/ -//# define RGBLIGHT_EFFECT_BREATHE_CENTER 1.85 // 1 to 2.7 -//# define RGBLIGHT_EFFECT_BREATHE_MAX 255 // 0 to 255 -//#endif - -/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ -#define DEBOUNCE 5 - -/* define if matrix has ghost (lacks anti-ghosting diodes) */ -//#define MATRIX_HAS_GHOST - -/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ -#define LOCKING_SUPPORT_ENABLE -/* Locking resynchronize hack */ -#define LOCKING_RESYNC_ENABLE - -/* If defined, GRAVE_ESC will always act as ESC when CTRL is held. - * This is useful for the Windows task manager shortcut (ctrl+shift+esc). - */ -//#define GRAVE_ESC_CTRL_OVERRIDE - -/* - * Force NKRO - * - * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved - * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the - * makefile for this to work.) - * - * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N) - * until the next keyboard reset. - * - * NKRO may prevent your keystrokes from being detected in the BIOS, but it is - * fully operational during normal computer usage. - * - * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N) - * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by - * bootmagic, NKRO mode will always be enabled until it is toggled again during a - * power-up. - * - */ -//#define FORCE_NKRO - -/* - * Feature disable options - * These options are also useful to firmware size reduction. - */ - -/* disable debug print */ -//#define NO_DEBUG - -/* disable print */ -//#define NO_PRINT - -/* disable action features */ -//#define NO_ACTION_LAYER -//#define NO_ACTION_TAPPING -//#define NO_ACTION_ONESHOT - -/* Bootmagic Lite key configuration */ -//#define BOOTMAGIC_LITE_ROW 0 -//#define BOOTMAGIC_LITE_COLUMN 0 diff --git a/data/templates/avr/rules.mk b/data/templates/avr/rules.mk deleted file mode 100644 index 1275531ef6d..00000000000 --- a/data/templates/avr/rules.mk +++ /dev/null @@ -1,18 +0,0 @@ -# MCU name -MCU = atmega32u4 - -# Bootloader selection -BOOTLOADER = atmel-dfu - -# Build Options -# change yes to no to disable -# -BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite -MOUSEKEY_ENABLE = yes # Mouse keys -EXTRAKEY_ENABLE = yes # Audio control and System control -CONSOLE_ENABLE = no # Console for debug -COMMAND_ENABLE = no # Commands for debug and configuration -NKRO_ENABLE = no # Enable N-Key Rollover -BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality -RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow -AUDIO_ENABLE = no # Audio output diff --git a/data/templates/base/%(KEYBOARD)s.c b/data/templates/base/%(KEYBOARD)s.c deleted file mode 100644 index 0c509aff658..00000000000 --- a/data/templates/base/%(KEYBOARD)s.c +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright %(YEAR)s %(YOUR_NAME)s (@%(USER_NAME)s) -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "%(KEYBOARD)s.h" diff --git a/data/templates/base/%(KEYBOARD)s.h b/data/templates/base/%(KEYBOARD)s.h deleted file mode 100644 index 3e8ca3912dc..00000000000 --- a/data/templates/base/%(KEYBOARD)s.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright %(YEAR)s %(YOUR_NAME)s (@%(USER_NAME)s) -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "quantum.h" - -/* This is a shortcut to help you visually see your layout. - * - * The first section contains all of the arguments representing the physical - * layout of the board and position of the keys. - * - * The second converts the arguments into a two-dimensional array which - * represents the switch matrix. - */ -#define LAYOUT( \ - k00, k01, k02, \ - k10, k12 \ -) { \ - { k00, k01, k02 }, \ - { k10, KC_NO, k12 } \ -} diff --git a/data/templates/base/info.json b/data/templates/base/info.json deleted file mode 100644 index a50ccba7bf9..00000000000 --- a/data/templates/base/info.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "keyboard_name": "%(KEYBOARD)s", - "url": "", - "maintainer": "%(USER_NAME)s", - "layouts": { - "LAYOUT": { - "layout": [ - {"label": "k00", "x": 0, "y": 0}, - {"label": "k01", "x": 1, "y": 0}, - {"label": "k02", "x": 2, "y": 0}, - - {"label": "k10", "x": 0, "y": 1, "w": 1.5}, - {"label": "k12", "x": 1.5, "y": 1, "w": 1.5} - ] - } - } -} diff --git a/data/templates/base/keymaps/default/keymap.c b/data/templates/base/keymaps/default/keymap.c deleted file mode 100644 index 3fec3d51203..00000000000 --- a/data/templates/base/keymaps/default/keymap.c +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright %(YEAR)s %(YOUR_NAME)s (@%(USER_NAME)s) -// SPDX-License-Identifier: GPL-2.0-or-later - -#include QMK_KEYBOARD_H - -// Defines names for use in layer keycodes and the keymap -enum layer_names { - _BASE, - _FN -}; - -const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { - /* Base */ - [_BASE] = LAYOUT( - KC_A, KC_1, MO(_FN), - KC_TAB, KC_SPC - ), - [_FN] = LAYOUT( - _______, _______, _______, - RESET, XXXXXXX - ) -}; diff --git a/data/templates/base/keymaps/default/readme.md b/data/templates/base/keymaps/default/readme.md deleted file mode 100644 index 63a06432757..00000000000 --- a/data/templates/base/keymaps/default/readme.md +++ /dev/null @@ -1 +0,0 @@ -# The default keymap for %(KEYBOARD)s diff --git a/data/templates/keyboard/info.json b/data/templates/keyboard/info.json new file mode 100644 index 00000000000..92718faf3ae --- /dev/null +++ b/data/templates/keyboard/info.json @@ -0,0 +1,24 @@ +{ + "keyboard_name": "%KEYBOARD%", + "maintainer": "%USER_NAME%", + "processor": "%MCU%", + "bootloader": "%BOOTLOADER%", + "diode_direction": "COL2ROW", + "matrix_pins": { + "cols": ["C2"], + "rows": ["D1"] + }, + "usb": { + "vid": "0xFEED", + "pid": "0x0000", + "device_ver": "0x0001" + }, + "features": { + "bootmagic_lite": true, + "command": false, + "console": false, + "extrakey": true, + "mousekey": true, + "nkro": true + } +} \ No newline at end of file diff --git a/data/templates/avr/readme.md b/data/templates/keyboard/readme.md similarity index 82% rename from data/templates/avr/readme.md rename to data/templates/keyboard/readme.md index 207850e0656..ca703c53f01 100644 --- a/data/templates/avr/readme.md +++ b/data/templates/keyboard/readme.md @@ -1,20 +1,20 @@ -# %(KEYBOARD)s +# %KEYBOARD% -![%(KEYBOARD)s](imgur.com image replace me!) +![%KEYBOARD%](imgur.com image replace me!) *A short description of the keyboard/project* -* Keyboard Maintainer: [%(YOUR_NAME)s](https://github.com/%(USER_NAME)s) +* Keyboard Maintainer: [%REAL_NAME%](https://github.com/%USER_NAME%) * Hardware Supported: *The PCBs, controllers supported* * Hardware Availability: *Links to where you can find this hardware* Make example for this keyboard (after setting up your build environment): - make %(KEYBOARD)s:default + make %KEYBOARD%:default Flashing example for this keyboard: - make %(KEYBOARD)s:default:flash + make %KEYBOARD%:default:flash See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). diff --git a/data/templates/keyboard/rules.mk b/data/templates/keyboard/rules.mk new file mode 100644 index 00000000000..6e7633bfe01 --- /dev/null +++ b/data/templates/keyboard/rules.mk @@ -0,0 +1 @@ +# This file intentionally left blank diff --git a/data/templates/ps2avrgb/config.h b/data/templates/ps2avrgb/config.h deleted file mode 100644 index ef29da0de08..00000000000 --- a/data/templates/ps2avrgb/config.h +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright %(YEAR)s %(YOUR_NAME)s (@%(USER_NAME)s) -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "config_common.h" - -/* USB Device descriptor parameter */ -#define VENDOR_ID 0xFEED -#define PRODUCT_ID 0x0000 -#define DEVICE_VER 0x0001 -#define MANUFACTURER %(USER_NAME)s -#define PRODUCT %(KEYBOARD)s - -/* key matrix size */ -#define MATRIX_ROWS 8 -#define MATRIX_COLS 15 - -/* - * Keyboard Matrix Assignments - * - * Change this to how you wired your keyboard - * COLS: AVR pins used for columns, left to right - * ROWS: AVR pins used for rows, top to bottom - * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode) - * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode) - * - */ -#define MATRIX_ROW_PINS { B0, B1, B2, B3, B4, B5, B6, B7 } -#define MATRIX_COL_PINS { A0, A1, A2, A3, A4, A5, A6, A7, C7, C6, C5, C4, C3, C2, D7 } -#define UNUSED_PINS - -/* COL2ROW, ROW2COL */ -#define DIODE_DIRECTION COL2ROW - -//#define LED_NUM_LOCK_PIN D0 -//#define LED_CAPS_LOCK_PIN D1 -//#define LED_SCROLL_LOCK_PIN D6 - -#define BACKLIGHT_PIN D4 -//#define BACKLIGHT_LEVELS 3 -//#define BACKLIGHT_BREATHING - -#define RGBLED_NUM 16 -//#define RGBLIGHT_HUE_STEP 8 -//#define RGBLIGHT_SAT_STEP 8 -//#define RGBLIGHT_VAL_STEP 8 -//#define RGBLIGHT_LIMIT_VAL 255 /* The maximum brightness level */ -//#define RGBLIGHT_SLEEP /* If defined, the RGB lighting will be switched off when the host goes to sleep */ -/*== all animations enable ==*/ -//#define RGBLIGHT_ANIMATIONS -/*== or choose animations ==*/ -//#define RGBLIGHT_EFFECT_BREATHING -//#define RGBLIGHT_EFFECT_RAINBOW_MOOD -//#define RGBLIGHT_EFFECT_RAINBOW_SWIRL -//#define RGBLIGHT_EFFECT_SNAKE -//#define RGBLIGHT_EFFECT_KNIGHT -//#define RGBLIGHT_EFFECT_CHRISTMAS -//#define RGBLIGHT_EFFECT_STATIC_GRADIENT -//#define RGBLIGHT_EFFECT_RGB_TEST -//#define RGBLIGHT_EFFECT_ALTERNATING -/*== customize breathing effect ==*/ -/*==== (DEFAULT) use fixed table instead of exp() and sin() ====*/ -//#define RGBLIGHT_BREATHE_TABLE_SIZE 256 // 256(default) or 128 or 64 -/*==== use exp() and sin() ====*/ -//#define RGBLIGHT_EFFECT_BREATHE_CENTER 1.85 // 1 to 2.7 -//#define RGBLIGHT_EFFECT_BREATHE_MAX 255 // 0 to 255 - -/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ -#define DEBOUNCE 5 - -/* define if matrix has ghost (lacks anti-ghosting diodes) */ -//#define MATRIX_HAS_GHOST - -/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ -#define LOCKING_SUPPORT_ENABLE -/* Locking resynchronize hack */ -#define LOCKING_RESYNC_ENABLE - -/* If defined, GRAVE_ESC will always act as ESC when CTRL is held. - * This is useful for the Windows task manager shortcut (ctrl+shift+esc). - */ -//#define GRAVE_ESC_CTRL_OVERRIDE - -/* - * Force NKRO - * - * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved - * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the - * makefile for this to work.) - * - * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N) - * until the next keyboard reset. - * - * NKRO may prevent your keystrokes from being detected in the BIOS, but it is - * fully operational during normal computer usage. - * - * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N) - * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by - * bootmagic, NKRO mode will always be enabled until it is toggled again during a - * power-up. - * - */ -//#define FORCE_NKRO - -/* - * Feature disable options - * These options are also useful to firmware size reduction. - */ - -/* disable debug print */ -//#define NO_DEBUG - -/* disable print */ -//#define NO_PRINT - -/* disable action features */ -//#define NO_ACTION_LAYER -//#define NO_ACTION_TAPPING -//#define NO_ACTION_ONESHOT - -/* Bootmagic Lite key configuration */ -//#define BOOTMAGIC_LITE_ROW 0 -//#define BOOTMAGIC_LITE_COLUMN 0 diff --git a/data/templates/ps2avrgb/readme.md b/data/templates/ps2avrgb/readme.md deleted file mode 100644 index a2ac4495b68..00000000000 --- a/data/templates/ps2avrgb/readme.md +++ /dev/null @@ -1,28 +0,0 @@ -# %(KEYBOARD)s - -![%(KEYBOARD)s](imgur.com image replace me!) - -*A short description of the keyboard/project* - -* Keyboard Maintainer: [%(YOUR_NAME)s](https://github.com/yourusername) -* Hardware Supported: *The PCBs, controllers supported* -* Hardware Availability: *Links to where you can find this hardware* - -Make example for this keyboard (after setting up your build environment): - - make %(KEYBOARD)s:default - -Flashing example for this keyboard ([after setting up the bootloadHID flashing environment](https://docs.qmk.fm/#/flashing_bootloadhid)) - - make %(KEYBOARD)s:default:flash - -See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs). - -## Bootloader - -Enter the bootloader in 3 ways: - -* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (usually the top left key or Escape) and plug in the keyboard -* **BootloadHID reset**: Hold down the key connected to the `A0` and `B0` pins on the MCU if it is known (often top left or bottom left) and plug in the keyboard -* **Physical reset button**: Briefly press the button on the back of the PCB - some may have pads you must short instead -* **Keycode in layout**: Press the key mapped to `RESET` if it is available diff --git a/data/templates/ps2avrgb/rules.mk b/data/templates/ps2avrgb/rules.mk deleted file mode 100644 index 1bbfa8fa0ec..00000000000 --- a/data/templates/ps2avrgb/rules.mk +++ /dev/null @@ -1,17 +0,0 @@ -# MCU name -MCU = atmega32a - -# Bootloader selection -BOOTLOADER = bootloadhid - -# Build Options -# change yes to no to disable -# -BOOTMAGIC_ENABLE = yes # Enable Bootmagic Lite -MOUSEKEY_ENABLE = yes # Mouse keys -EXTRAKEY_ENABLE = yes # Audio control and System control -CONSOLE_ENABLE = no # Console for debug -COMMAND_ENABLE = no # Commands for debug and configuration -BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality -RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow -WS2812_DRIVER = i2c diff --git a/docs/cli_commands.md b/docs/cli_commands.md index dfbd4c6a284..93af906b8a3 100644 --- a/docs/cli_commands.md +++ b/docs/cli_commands.md @@ -310,7 +310,7 @@ Any arguments that are not provided will prompt for input. If `-u` is not passed **Usage**: ``` -qmk new-keyboard [-kb KEYBOARD] [-t {avr,ps2avrgb}] -u USERNAME +qmk new-keyboard [-kb KEYBOARD] [-t {atmega32u4,STM32F303,etc}] [-l {60_ansi,75_iso,etc}] -u USERNAME ``` ## `qmk new-keymap` diff --git a/lib/python/qmk/cli/new/keyboard.py b/lib/python/qmk/cli/new/keyboard.py index 4093b8c90d0..59e781a932e 100644 --- a/lib/python/qmk/cli/new/keyboard.py +++ b/lib/python/qmk/cli/new/keyboard.py @@ -1,15 +1,82 @@ """This script automates the creation of new keyboard directories using a starter template. """ +import re +import json +import shutil from datetime import date from pathlib import Path -import re +from dotty_dict import dotty -from qmk.commands import git_get_username -import qmk.path from milc import cli from milc.questions import choice, question -KEYBOARD_TYPES = ['avr', 'ps2avrgb'] +from qmk.commands import git_get_username +from qmk.json_schema import load_jsonschema +from qmk.path import keyboard +from qmk.json_encoders import InfoJSONEncoder +from qmk.json_schema import deep_update + +COMMUNITY = Path('layouts/default/') +TEMPLATE = Path('data/templates/keyboard/') + +MCU2BOOTLOADER = { + "MKL26Z64": "halfkay", + "MK20DX128": "halfkay", + "MK20DX256": "halfkay", + "MK66FX1M0": "halfkay", + "STM32F042": "stm32-dfu", + "STM32F072": "stm32-dfu", + "STM32F103": "stm32duino", + "STM32F303": "stm32-dfu", + "STM32F401": "stm32-dfu", + "STM32F405": "stm32-dfu", + "STM32F407": "stm32-dfu", + "STM32F411": "stm32-dfu", + "STM32F446": "stm32-dfu", + "STM32G431": "stm32-dfu", + "STM32G474": "stm32-dfu", + "STM32L412": "stm32-dfu", + "STM32L422": "stm32-dfu", + "STM32L432": "stm32-dfu", + "STM32L433": "stm32-dfu", + "STM32L442": "stm32-dfu", + "STM32L443": "stm32-dfu", + "GD32VF103": "gd32v-dfu", + "WB32F3G71": "wb32-dfu", + "atmega16u2": "atmel-dfu", + "atmega32u2": "atmel-dfu", + "atmega16u4": "atmel-dfu", + "atmega32u4": "atmel-dfu", + "at90usb162": "atmel-dfu", + "at90usb646": "atmel-dfu", + "at90usb647": "atmel-dfu", + "at90usb1286": "atmel-dfu", + "at90usb1287": "atmel-dfu", + "atmega32a": "bootloadhid", + "atmega328p": "usbasploader", + "atmega328": "usbasploader", +} + +# defaults +schema = dotty(load_jsonschema('keyboard')) +mcu_types = sorted(schema["properties.processor.enum"], key=str.casefold) +available_layouts = sorted([x.name for x in COMMUNITY.iterdir() if x.is_dir()]) + + +def mcu_type(mcu): + """Callable for argparse validation. + """ + if mcu not in mcu_types: + raise ValueError + return mcu + + +def layout_type(layout): + """Callable for argparse validation. + """ + if layout not in available_layouts: + raise ValueError + return layout def keyboard_name(name): @@ -27,8 +94,111 @@ def validate_keyboard_name(name): return bool(regex.match(name)) +def select_default_bootloader(mcu): + """Provide sane defaults for bootloader + """ + return MCU2BOOTLOADER.get(mcu, "custom") + + +def replace_placeholders(src, dest, tokens): + """Replaces the given placeholders in each template file. + """ + content = src.read_text() + for key, value in tokens.items(): + content = content.replace(f'%{key}%', value) + + dest.write_text(content) + + +def augment_community_info(src, dest): + """Splice in any additional data into info.json + """ + info = json.loads(src.read_text()) + template = json.loads(dest.read_text()) + + # merge community with template + deep_update(info, template) + + # avoid assumptions on macro name by using the first available + first_layout = next(iter(info["layouts"].values()))["layout"] + + # guess at width and height now its optional + width, height = (0, 0) + for item in first_layout: + width = max(width, int(item["x"]) + 1) + height = max(height, int(item["y"]) + 1) + + info["matrix_pins"] = { + "cols": ["C2"] * width, + "rows": ["D1"] * height, + } + + # assume a 1:1 mapping on matrix to electrical + for item in first_layout: + item["matrix"] = [int(item["y"]), int(item["x"])] + + # finally write out the updated info.json + dest.write_text(json.dumps(info, cls=InfoJSONEncoder)) + + +def prompt_keyboard(): + prompt = """{fg_yellow}Name Your Keyboard Project{style_reset_all} + +For more infomation, see: +https://docs.qmk.fm/#/hardware_keyboard_guidelines?id=naming-your-keyboardproject + +keyboard Name? """ + + return question(prompt, validate=lambda x: not keyboard(x).exists()) + + +def prompt_user(): + prompt = """{fg_yellow}Attribution{style_reset_all} + +Used for maintainer, copyright, etc + +Your GitHub Username? """ + return question(prompt, default=git_get_username()) + + +def prompt_name(def_name): + prompt = """{fg_yellow}More Attribution{style_reset_all} + +Used for maintainer, copyright, etc + +Your Real Name? """ + return question(prompt, default=def_name) + + +def prompt_layout(): + prompt = """{fg_yellow}Pick Base Layout{style_reset_all} + +As a starting point, one of the common layouts can be used to bootstrap the process + +Default Layout? """ + # avoid overwhelming user - remove some? + filtered_layouts = [x for x in available_layouts if not any(xs in x for xs in ['_split', '_blocker', '_tsangan', '_f13'])] + filtered_layouts.append("none of the above") + + return choice(prompt, filtered_layouts, default=len(filtered_layouts) - 1) + + +def prompt_mcu(): + prompt = """{fg_yellow}What Powers Your Project{style_reset_all} + +For more infomation, see: +https://docs.qmk.fm/#/compatible_microcontrollers + +MCU? """ + # remove any options strictly used for compatibility + filtered_mcu = [x for x in mcu_types if not any(xs in x for xs in ['cortex', 'unknown'])] + + return choice(prompt, filtered_mcu, default=filtered_mcu.index("atmega32u4")) + + @cli.argument('-kb', '--keyboard', help='Specify the name for the new keyboard directory', arg_only=True, type=keyboard_name) -@cli.argument('-t', '--type', help='Specify the keyboard type', arg_only=True, choices=KEYBOARD_TYPES) +@cli.argument('-l', '--layout', help='Community layout to bootstrap with', arg_only=True, type=layout_type) +@cli.argument('-t', '--type', help='Specify the keyboard MCU type', arg_only=True, type=mcu_type) @cli.argument('-u', '--username', help='Specify your username (default from Git config)', arg_only=True) @cli.argument('-n', '--realname', help='Specify your real name if you want to use that. Defaults to username', arg_only=True) @cli.subcommand('Creates a new keyboard directory') @@ -38,102 +208,49 @@ def new_keyboard(cli): cli.log.info('{style_bright}Generating a new QMK keyboard directory{style_normal}') cli.echo('') - # Get keyboard name - new_keyboard_name = None - while not new_keyboard_name: - new_keyboard_name = cli.args.keyboard if cli.args.keyboard else question('Keyboard Name:') - if not validate_keyboard_name(new_keyboard_name): - cli.log.error('Keyboard names must contain only {fg_cyan}lowercase a-z{fg_reset}, {fg_cyan}0-9{fg_reset}, and {fg_cyan}_{fg_reset}! Please choose a different name.') + kb_name = cli.args.keyboard if cli.args.keyboard else prompt_keyboard() + user_name = cli.args.username if cli.args.username else prompt_user() + real_name = cli.args.realname or cli.args.username if cli.args.realname or cli.args.username else prompt_name(user_name) + default_layout = cli.args.layout if cli.args.layout else prompt_layout() + mcu = cli.args.type if cli.args.type else prompt_mcu() + bootloader = select_default_bootloader(mcu) - # Exit if passed by arg - if cli.args.keyboard: - return False + if not validate_keyboard_name(kb_name): + cli.log.error('Keyboard names must contain only {fg_cyan}lowercase a-z{fg_reset}, {fg_cyan}0-9{fg_reset}, and {fg_cyan}_{fg_reset}! Please choose a different name.') + return 1 - new_keyboard_name = None - continue + if keyboard(kb_name).exists(): + cli.log.error(f'Keyboard {{fg_cyan}}{kb_name}{{fg_reset}} already exists! Please choose a different name.') + return 1 - keyboard_path = qmk.path.keyboard(new_keyboard_name) - if keyboard_path.exists(): - cli.log.error(f'Keyboard {{fg_cyan}}{new_keyboard_name}{{fg_reset}} already exists! Please choose a different name.') + tokens = {'YEAR': str(date.today().year), 'KEYBOARD': kb_name, 'USER_NAME': user_name, 'REAL_NAME': real_name, 'LAYOUT': default_layout, 'MCU': mcu, 'BOOTLOADER': bootloader} - # Exit if passed by arg - if cli.args.keyboard: - return False + if cli.config.general.verbose: + cli.log.info("Creating keyboard with:") + for key, value in tokens.items(): + cli.echo(f" {key.ljust(10)}: {value}") - new_keyboard_name = None + # TODO: detach community layout and rename to just "LAYOUT" + if default_layout == 'none of the above': + default_layout = "ortho_4x4" - # Get keyboard type - keyboard_type = cli.args.type if cli.args.type else choice('Keyboard Type:', KEYBOARD_TYPES, default=0) + # begin with making the deepest folder in the tree + keymaps_path = keyboard(kb_name) / 'keymaps/' + keymaps_path.mkdir(parents=True) - # Get username - user_name = None - while not user_name: - user_name = question('Your GitHub User Name:', default=find_user_name()) + # copy in keymap.c or keymap.json + community_keymap = Path(COMMUNITY / f'{default_layout}/default_{default_layout}/') + shutil.copytree(community_keymap, keymaps_path / 'default') - if not user_name: - cli.log.error('You didn\'t provide a username, and we couldn\'t find one set in your QMK or Git configs. Please try again.') + # process template files + for file in list(TEMPLATE.iterdir()): + replace_placeholders(file, keyboard(kb_name) / file.name, tokens) - # Exit if passed by arg - if cli.args.username: - return False + # merge in infos + community_info = Path(COMMUNITY / f'{default_layout}/info.json') + augment_community_info(community_info, keyboard(kb_name) / community_info.name) - real_name = None - while not real_name: - real_name = question('Your real name:', default=user_name) - - keyboard_basename = keyboard_path.name - replacements = { - "YEAR": str(date.today().year), - "KEYBOARD": keyboard_basename, - "USER_NAME": user_name, - "YOUR_NAME": real_name, - } - - template_dir = Path('data/templates') - template_tree(template_dir / 'base', keyboard_path, replacements) - template_tree(template_dir / keyboard_type, keyboard_path, replacements) - - cli.echo('') - cli.log.info(f'{{fg_green}}Created a new keyboard called {{fg_cyan}}{new_keyboard_name}{{fg_green}}.{{fg_reset}}') - cli.log.info(f'To start working on things, `cd` into {{fg_cyan}}{keyboard_path}{{fg_reset}},') + cli.log.info(f'{{fg_green}}Created a new keyboard called {{fg_cyan}}{kb_name}{{fg_green}}.{{fg_reset}}') + cli.log.info(f'To start working on things, `cd` into {{fg_cyan}}keyboards/{kb_name}{{fg_reset}},') cli.log.info('or open the directory in your preferred text editor.') - - -def find_user_name(): - if cli.args.username: - return cli.args.username - elif cli.config.user.name: - return cli.config.user.name - else: - return git_get_username() - - -def template_tree(src: Path, dst: Path, replacements: dict): - """Recursively copy template and replace placeholders - - Args: - src (Path) - The source folder to copy from - dst (Path) - The destination folder to copy to - replacements (dict) - a dictionary with "key":"value" pairs to replace. - - Raises: - FileExistsError - When trying to overwrite existing files - """ - - dst.mkdir(parents=True, exist_ok=True) - - for child in src.iterdir(): - if child.is_dir(): - template_tree(child, dst / child.name, replacements=replacements) - - if child.is_file(): - file_name = dst / (child.name % replacements) - - with file_name.open(mode='x') as dst_f: - with child.open() as src_f: - template = src_f.read() - dst_f.write(template % replacements) + cli.log.info(f"And build with {{fg_yellow}}qmk compile -kb {kb_name} -km default{{fg_reset}}.") diff --git a/lib/python/qmk/path.py b/lib/python/qmk/path.py index 72bae592734..dfb8371f845 100644 --- a/lib/python/qmk/path.py +++ b/lib/python/qmk/path.py @@ -46,7 +46,7 @@ def keymap(keyboard_name): """ keyboard_folder = keyboard(keyboard_name) - for i in range(MAX_KEYBOARD_SUBFOLDERS): + for _ in range(MAX_KEYBOARD_SUBFOLDERS): if (keyboard_folder / 'keymaps').exists(): return (keyboard_folder / 'keymaps').resolve() diff --git a/util/new_keyboard.sh b/util/new_keyboard.sh deleted file mode 100755 index 62e8cb9e133..00000000000 --- a/util/new_keyboard.sh +++ /dev/null @@ -1,181 +0,0 @@ -#!/usr/bin/env bash - -# This script generates a new keyboard directory under keyboards/, -# and copies the template files from data/templates/ into it. - -# Print an error message with the word "ERROR" in red. -echo_error() { - echo -e "[\033[0;91mERROR\033[m]: $1" -} - -# Print a message in bold. -echo_bold() { - echo -e "\033[1m$1\033[m" -} - -# Prompt the user for information, showing the default value in brackets. -prompt() { - local message="$1" - local default="$2" - - [ -n "$default" ] && message+=" [$default]" - message+=": " - - read -rp "$message" prompt_return - [ -z "$prompt_return" ] && prompt_return="$default" -} - -# Grab a username from Git config. -set_git_username() { - git_username="$(git config --get user.name)" -} - -# Copy the template files to the new keyboard directory. -copy_templates() { - mkdir -p "$keyboard_dir" - - echo -n "Copying base template files..." - cp -r "data/templates/base/." "${keyboard_dir}" - echo " done" - - echo -n "Copying $keyboard_type template files..." - cp -r "data/templates/${keyboard_type}/." "${keyboard_dir}" - echo " done" - - echo -n "Renaming keyboard files..." - mv "${keyboard_dir}/keyboard.c" "${keyboard_dir}/${keyboard_base_name}.c" - mv "${keyboard_dir}/keyboard.h" "${keyboard_dir}/${keyboard_base_name}.h" - echo " done" -} - -# Set the inplace editing parameter for sed. -# macOS/BSD sed expects a file extension immediately following -i. -set_sed_i() { - sed_i=(-i) - - case $(uname -a) in - *Darwin*) sed_i=(-i "") - esac -} - -# Replace a token with a value in the given list of files. -replace_placeholders() { - local replace_token="$1" - local replace_value="$2" - shift 2 - local replace_filenames=("$@") - - echo -n "Replacing $replace_token with $replace_value..." - for replace_filename in "${replace_filenames[@]}"; do - sed "${sed_i[@]}" -e "s/${replace_token}/${replace_value}/g" "$replace_filename" - done - echo " done" -} - -# Replace %YEAR% with the current year. -replace_year_placeholders() { - local replace_year_filenames=( - "${keyboard_dir}/config.h" - "${keyboard_dir}/${keyboard_base_name}.c" - "${keyboard_dir}/${keyboard_base_name}.h" - "${keyboard_dir}/keymaps/default/keymap.c" - ) - replace_placeholders "%YEAR%" "$(date +%Y)" "${replace_year_filenames[@]}" -} - -# Replace %KEYBOARD% with the keyboard name. -replace_keyboard_placeholders() { - local replace_keyboard_filenames=( - "${keyboard_dir}/config.h" - "${keyboard_dir}/info.json" - "${keyboard_dir}/readme.md" - "${keyboard_dir}/${keyboard_base_name}.c" - "${keyboard_dir}/keymaps/default/readme.md" - ) - replace_placeholders "%KEYBOARD%" "$keyboard_base_name" "${replace_keyboard_filenames[@]}" -} - -# Replace %YOUR_NAME% with the username. -replace_name_placeholders() { - local replace_name_filenames=( - "${keyboard_dir}/config.h" - "${keyboard_dir}/info.json" - "${keyboard_dir}/readme.md" - "${keyboard_dir}/${keyboard_base_name}.c" - "${keyboard_dir}/${keyboard_base_name}.h" - "${keyboard_dir}/keymaps/default/keymap.c" - ) - replace_placeholders "%YOUR_NAME%" "$username" "${replace_name_filenames[@]}" -} - -# Check if an array contains an element. -array_contains() { - local e match="$1" - shift - for e; do - [[ "$e" == "$match" ]] && return 0; - done - - return 1 -} - -# If we've been started from util/, we want to be in qmk_firmware/ -[[ "$PWD" == *util ]] && cd .. - -# The root qmk_firmware/ directory should have a subdirectory called quantum/ -if [ ! -d "quantum" ]; then - echo_error "Could not detect the QMK firmware directory!" - echo_error "Are you sure you're in the right place?" - exit 1 -fi - -echo_bold "########################################" -echo_bold "# NOTICE #" -echo_bold "# This script has been deprecated. #" -echo_bold "# Please use qmk new-keyboard instead. #" -echo_bold "########################################" -echo -echo_bold "Generating a new QMK keyboard directory" -echo - -# Keyboard name is required, so keep prompting until we get one -while [ -z "$keyboard_name" ]; do - prompt "Keyboard Name" "" - keyboard_name=$prompt_return - keyboard_base_name=$(basename $keyboard_name) -done - -keyboard_dir="keyboards/$keyboard_name" - -if [ -d "$keyboard_dir" ]; then - echo_error "Keyboard $keyboard_name already exists!" - exit 1 -fi - -KEYBOARD_TYPES=("avr" "ps2avrgb") - -prompt "Keyboard Type" "avr" -keyboard_type=$prompt_return - -if ! array_contains "$keyboard_type" "${KEYBOARD_TYPES[@]}"; then - echo_error "Keyboard type must be one of: ${KEYBOARD_TYPES[*]}" - exit 1 -fi - -set_git_username -prompt "Your Name" "$git_username" -username=$prompt_return - -echo - -copy_templates -set_sed_i -replace_year_placeholders -replace_keyboard_placeholders -[ -n "$username" ] && replace_name_placeholders - -echo -echo_bold "Created a new keyboard called $keyboard_name." -echo -echo_bold "To start working on things, cd into keyboards/$keyboard_name," -echo_bold "or open the directory in your favourite text editor." diff --git a/util/new_keymap.sh b/util/new_keymap.sh deleted file mode 100755 index c483314fdb0..00000000000 --- a/util/new_keymap.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh -# Script to make a new keymap for a keyboard of your choosing -# This script automates the copying of the default keymap into -# your own keymap - -KB_PATH=$(echo "$1" | tr 'A-Z' 'a-z') -USERNAME=$(echo "$2" | tr 'A-Z' 'a-z') - -if [ -z "$KB_PATH" ]; then - printf "Usage: %s \n" "$0" - printf "Example: %s 1upkeyboards/1up60hse yourname\n" "$0" - exit 1 -fi - -if [ -z "$USERNAME" ]; then - printf "Usage: %s \n" "$0" - printf "Example: %s 1upkeyboards/1up60hse yourname\n" "$0" - exit 1 -fi - -cd "$(dirname "$0")/.." - -if [ ! -d "keyboards/$KB_PATH" ]; then - printf "Error! keyboards/%s does not exist!\n" "$KB_PATH" - exit 1 -fi - -if [ -d "keyboards/$KB_PATH/keymaps/$USERNAME" ]; then - printf "Error! keyboards/%s/keymaps/%s already exists!\n" "$KB_PATH" "$USERNAME" - exit 1 -fi - -# Recursively copy the chosen keyboard's default keymap -cp -r keyboards/"$KB_PATH"/keymaps/default keyboards/"$KB_PATH"/keymaps/"$USERNAME" - -printf "%s keymap directory created in: qmk_firmware/keyboards/%s/keymaps/\n\n" "$USERNAME" "$KB_PATH" - -printf "Compile a firmware file with your new keymap by typing: \n" -printf " make %s:%s\n" "$KB_PATH" "$USERNAME" -printf "from the qmk_firmware directory\n"