diff --git a/.gitignore b/.gitignore index b25cc76..7dbd771 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ kanata*.exe +**/output/* \ No newline at end of file diff --git a/qmk/arsenik-qmk.sh b/qmk/arsenik-qmk.sh deleted file mode 100755 index 36e5e36..0000000 --- a/qmk/arsenik-qmk.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -if [ "$#" -lt 1 ]; then - echo "Usage:" - echo "$0 [-n] [-b,-f]" - echo " # Install Arsenik for your keyboard, opens your editor to edit the config" - echo ' # -n: no editor: doesn’t open the config with your $EDITOR' - echo " # -b: build the newly created keymap (after you edited the config)" - echo " # -f: build the newly created keymap (after you edited the config) then flash" - exit 0 -fi - -if [ -z "${QMK_PATH+x}" ]; then - QMK_PATH="$HOME/qmk_firmware" -fi - - -if [ -z "${EDITOR+x}" ]; then - if which nano >/dev/null 2>&1; then - EDITOR="nano" - else - EDITOR="vi" - fi -fi - - -function get_keymaps_folder() { - keyboard_name="$1" - while [ ! -d "$QMK_PATH/keyboards/$keyboard_name/keymaps" ]; do - if [ "$keyboard_name" == "." ]; then - echo "Couldn’t find keymap folder for your keyboard" - exit 1 - fi - keyboard_name=$(dirname "$keyboard_name") - done - - echo "$QMK_PATH/keyboards/$keyboard_name/keymaps" -} - -function make_new_arsenik_keymap() { - local keyboard_name="$1" - local qmk_cmd="$2" - local no_editor="$3" - - local keymap_folder=$(get_keymaps_folder "$keyboard_name") - local arsenik_folder="$keymap_folder/arsenik/" - local default_keymap_folder="$keymap_folder/default" - - cp -r "$default_keymap_folder" "$arsenik_folder" - ls -l "$arsenik_folder" - - local layout="" - case $(ls "$default_keymap_folder"/keymap.* | sed 's/.*\(keymap.*\)/\1/') in - "keymap.c") layout=$(grep 'LAYOUT' "$default_keymap_folder"/keymap.c | sed 's/.*= \(.*\)(/\1/' | head -n 1);; - "keymap.json") layout=$(grep 'LAYOUT' "$default_keymap_folder"/keymap.json | sed 's/ *"layout": "\(.*\)",/\1/');; - *) echo "Unable to find layout name, unsupported keymap format";; - esac - - if [ "$layout" == "LAYOUT" ]; then - layout+="_$(echo "$keyboard_name" | sed 's,/,_,g' | sed 's/_rev[0-9]*$//')" - fi - - layout="ARSENIK_$layout" - - rm "$arsenik_folder"/keymap.* - cat ./arsenik_config.h >> "$arsenik_folder/config.h" - cat ./rules.mk >> "$arsenik_folder/rules.mk" - cp ./keymap.c ./arsenik.h ./keymap_ergol.h "$arsenik_folder" - - # echo "s/ARSENIK_PLACEHOLDER_LAYOUT/$layout/" - sed -i "s/ARSENIK_PLACEHOLDER_LAYOUT/$layout/" "$arsenik_folder/config.h" - - if [ "$no_editor" = false ]; then - eval "$EDITOR" "$arsenik_folder/config.h" - fi - - case "$qmk_cmd" in - "none") ;; - "build") cd "$QMK_PATH" && make "$keyboard_name:arsenik";; - "flash") cd "$QMK_PATH" && make "$keyboard_name:arsenik:flash";; - esac -} - - -no_editor=false -qmk_cmd="none" -for arg in "${@:2}"; do - case "$arg" in - "-n") no_editor=true;; - "-b") qmk_cmd="build";; - "-f") qmk_cmd="flash";; - *) echo "Unknown argument $arg."; exit 1;; - esac -done - -make_new_arsenik_keymap "$1" "$qmk_cmd" "$no_editor" diff --git a/qmk/generator.sh b/qmk/generator.sh new file mode 100755 index 0000000..6589057 --- /dev/null +++ b/qmk/generator.sh @@ -0,0 +1,191 @@ +#!/usr/bin/env bash + +# Arsenik QMK keymap generator +# Generates files required by QMK to build/flash an arsenik layout keymap for a given keyboard +# Outputs files in ./output//keymaps/arsenik + +set -euo pipefail + +# Colors for logs +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } +log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } +log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; } +log_error() { echo -e "${RED}[ERROR]${NC} $1" >&2; } + +# Print usage and exit +usage() { + echo "Usage: $0 [-kb ] [-km ] [--generate|-g] [--copy|-cp]" + echo " -kb Specify the keyboard model (optional, will use qmk config if not provided)" + echo " -km Specify the keymap (optional, will use qmk config if not provided)" + echo " --generate, -g Generate the Arsenik keymap (default: off)" + echo " --copy, -cp Copy ./output//keymaps/arsenik to $QMK_HOME/keyboards//keymaps/arsenik (default: off)" + exit 1 +} + +# Parse arguments +copy_keymap=false +generate_keymap=false +keyboard_model="" +keymap="" + +while [ "$#" -gt 0 ]; do + case "$1" in + -kb) + shift + keyboard_model="$1" + ;; + -km) + shift + keymap="$1" + ;; + --copy | -cp) + copy_keymap=true + ;; + --generate | -g) + generate_keymap=true + ;; + *) + usage + ;; + esac + shift +done + +if [ -z "$keyboard_model" ] || [ -z "$keymap" ]; then + log_info "Requirements: It is recommended to have set QMK user.keyboard, user.keymap, and user.qmk_home using 'qmk config'." + log_info "See https://docs.qmk.fm/cli_configuration#setting-user-defaults for more information." + log_info "Your current configuration:" + qmk config || true +fi + +# If keyboard_model or keymap is empty, get from qmk config +if [ -z "$keyboard_model" ]; then + keyboard_model=$(qmk config user.keyboard | awk -F= '{print $2}' | xargs) + log_info "No keyboard_model provided with '-kb' argument, using value from qmk config: ${CYAN}$keyboard_model${NC}" +fi +if [ -z "$keymap" ]; then + keymap=$(qmk config user.keymap | awk -F= '{print $2}' | xargs) + log_info "No keymap provided with '-km' argument, using value from qmk config: ${CYAN}$keymap${NC}" +fi + +# Set QMK_HOME if not already set +if [ -z "${QMK_HOME+x}" ]; then + QMK_HOME=$(qmk config user.qmk_home | awk -F= '{print $2}' | xargs) +fi + +# Find the keymaps folder for a given keyboard name +get_keymaps_folder() { + local keyboard_model="$1" + local keymap="$2" + while [ ! -d "$QMK_HOME/keyboards/$keyboard_model/keymaps/$keymap" ]; do + if [ "$keyboard_model" = "." ]; then + echo "Couldn't find keymap folder for your keyboard/keymap" >&2 + exit 1 + fi + keyboard_model=$(dirname "$keyboard_model") + done + echo "$QMK_HOME/keyboards/$keyboard_model/keymaps/$keymap" +} + +# Detect layout name +detect_layout_name() { + local keyboard_model="$1" + local keymap="$2" + + local keymap_folder + keymap_folder=$(get_keymaps_folder "$keyboard_model" "$keymap") + + local layout="" + if [ -f "$keymap_folder/keymap.c" ]; then + layout=$(grep 'LAYOUT' "$keymap_folder/keymap.c" | sed 's/.*= \(.*\)(/\1/' | head -n 1) + elif [ -f "$keymap_folder/keymap.json" ]; then + layout=$(grep 'LAYOUT' "$keymap_folder/keymap.json" | sed 's/ *\"layout\": \"\(.*\)\",/\1/') + fi + + if [ "$layout" = "LAYOUT" ]; then + layout+="_$(echo "$keyboard_model" | sed 's,/,_,g' | sed 's/_rev[0-9]*$//')" + fi + echo "ARSENIK_$layout" +} + +create_output_dir() { + local output_dir="$1" + if [ -d "$output_dir" ]; then + log_warn "Output directory ${CYAN}$output_dir${NC} already exists." + read -p "Do you want to remove it and continue? [y/N]: " confirm + if [[ ! "$confirm" =~ ^[Yy]$ ]]; then + log_info "Aborted by user." + exit 0 + fi + log_info "Removing existing output directory: ${CYAN}$output_dir${NC}" + rm -rf "$output_dir" + fi + log_info "Creating output directory: ${CYAN}$output_dir${NC}" + mkdir -p "$output_dir" +} + +# Generate the Arsenik keymap in ./output// +generate_arsenik_keymap() { + local keyboard_model="$1" + local keymap="$2" + local output_dir="$3" + + local layout_name="$(detect_layout_name "$keyboard_model" "$keymap")" + log_info "Detected layout name: ${CYAN}$layout_name${NC}" + + log_info "Copying required Arsenik files to output directory..." + rsync -a keymap/ "$output_dir" + + # Replace placeholder in config.h template file + log_info "Set ${CYAN}$layout_name${NC} layout name in config.h template file..." + sed -i "s/ARSENIK_PLACEHOLDER_LAYOUT/$layout_name/" "$output_dir/config.h" + + log_success "Generated Arsenik keymap in ${CYAN}$output_dir${NC}" +} + +# Main +output_dir="./output/$keyboard_model/keymaps/arsenik" + +if [ "$generate_keymap" = true ]; then + create_output_dir "$output_dir" + generate_arsenik_keymap "$keyboard_model" "$keymap" "$output_dir" + log_info "Now you may want to copy the '/output' directory into your QMK home directory." + log_info "This can be done with the './generator.sh --copy' command." +fi + +if [ "$copy_keymap" = true ]; then + if [ ! -d "$output_dir" ]; then + log_error "Output directory ${CYAN}$output_dir${NC} does not exist. Cannot copy." + exit 1 + fi + dest_dir="$QMK_HOME/keyboards/$keyboard_model/keymaps/arsenik" + if [ -d "$dest_dir" ]; then + log_warn "Destination directory ${CYAN}$dest_dir${NC} already exists." + read -p "Do you want to overwrite it and continue? [y/N]: " confirm + if [[ ! "$confirm" =~ ^[Yy]$ ]]; then + log_info "Aborted by user." + exit 0 + fi + log_info "Removing existing destination directory: ${CYAN}$dest_dir${NC}" + rm -rf "$dest_dir" + fi + log_info "Copying ${CYAN}$output_dir${NC} to ${CYAN}$dest_dir${NC} ..." + rsync -a "$output_dir/" "$dest_dir" + log_success "Copied Arsenik keymap to ${CYAN}$dest_dir${NC}" + log_info "Finally, you may want to :" + log_info " cd $dest_dir" + log_info " qmk compile -kb $keyboard_model -km arsenik # compile the keymap" + log_info " # connect the keyboard" + log_info " qmk flash -kb $keyboard_model -km arsenik # flash the keyboard" +fi + +if [ "$generate_keymap" = false ] && [ "$copy_keymap" = false ]; then + log_info "No action requested (--generate/-g or --copy/-cp). Nothing to do." +fi diff --git a/qmk/arsenik.h b/qmk/keymap/arsenik.h similarity index 100% rename from qmk/arsenik.h rename to qmk/keymap/arsenik.h diff --git a/qmk/arsenik_config.h b/qmk/keymap/config.h similarity index 100% rename from qmk/arsenik_config.h rename to qmk/keymap/config.h diff --git a/qmk/keymap.c b/qmk/keymap/keymap.c similarity index 100% rename from qmk/keymap.c rename to qmk/keymap/keymap.c diff --git a/qmk/keymap_ergol.h b/qmk/keymap/keymap_ergol.h similarity index 100% rename from qmk/keymap_ergol.h rename to qmk/keymap/keymap_ergol.h diff --git a/qmk/rules.mk b/qmk/keymap/rules.mk similarity index 100% rename from qmk/rules.mk rename to qmk/keymap/rules.mk diff --git a/qmk/readme.md b/qmk/readme.md index 3067b6d..410d46f 100644 --- a/qmk/readme.md +++ b/qmk/readme.md @@ -1,24 +1,15 @@ # Arsenik QMK -This is a generic implementation of the Arsenik layout for QMK keyboards. +This repository provides: -**Disclaimer** : This is still relatively new. There might be bugs and your -keyboard might not be compatible *yet*. +- `/qmk/keymap`: Generic Arsenik layout files for QMK keyboards +- `/qmk/generator.sh`: Script to generate and install an Arsenik keymap for your keyboard -## How it works +## Overview -Arsenik-QMK will define a full qmk keymap in a dummy `ARSENIK_LAYOUT` layout -definition. At compile time, this dummy gets is replaced by the layout -definition your keyboard actually uses. This means that the keymap will -naturally remove unused keys (like the number row on a keyboard with 3 rows) -or add no-op to the keys unused by Arsenik on bigger keyboards. +Arsenik-QMK generates a complete QMK keymap using a dummy `ARSENIK_LAYOUT` definition. At compile time, this is replaced with your keyboard's actual layout, automatically adapting to different keyboard sizes and shapes. If your keyboard is not yet supported, you can add its layout to `arsenik.h` or open an issue/PR for help. -Ideally, you install it and it just works, but not every keyboards are -currently supported. If the `ARSENIK_LAYOUT` isn’t defined for your keyboard, -it needs to be added at the end of the `arsenik.h` file. PRs are welcome, but -we will gladly help you if you open an issue ^^ - -Here is a list of all currently supported QMK layouts : +**Supported layouts:** - `LAYOUT_split_3x5_2` - `LAYOUT_split_3x5_3` @@ -30,49 +21,95 @@ Here is a list of all currently supported QMK layouts : - `LAYOUT_planck_grid` - `LAYOUT_keebio_iris_default` -## Install +## Quick Start + +> **Note:** Beginners should follow this guide and use the default Arsenik configuration. Advanced users can customize their setup using Arsenik's features. See step 8 for details. + +### 1. Install & Set Up QMK + +Follow the [QMK Getting Started Guide](https://docs.qmk.fm/newbs_getting_started) to: + +- Install the `qmk` CLI +- Run `qmk setup` (clones the QMK repo) +- Verify you can compile a default firmware + +### 2. Identify Your Keyboard and Keymap + +Find your keyboard's QMK name (usually `brand/model/revision`). + +```sh +qmk list-keyboards # List all supported keyboards +qmk list-keyboards | grep corne # Filter for your model +qmk info -kb # Show keyboard info +qmk list-keymaps -kb # List available keymaps +``` + +### 3. Configure QMK User Defaults + +Set your QMK home, keyboard, and keymap: + +```sh +qmk config user.qmk_home= +qmk config user.keyboard= +qmk config user.keymap= +qmk config # Check your config +``` + +### 4. Clone the Arsenik Repository -You’ll need to setup your QMK environment beforhand, QMK’s cli tool does the -job well. You’ll need to know how is your keyboard is called inside of QMK’s -code, usually they are named `brand/model/revision` though that may vary from a -keyboard to another. You can always run `qmk list-keyboard | grep ` to quickly find it, is case you don’t know. +```sh +git clone https://github.com/OneDeadKey/arsenik.git +cd arsenik/qmk +``` -Once you know how your keyboard is named, installing Arsenik-QMK is as easy as -cloning this repo locally and running the `./arsenik-qmk.sh `. -The script expects to find the QMK repo at `~/qmk_firmware`, so if you already -have QMK setup somewhere else, you can set the `QMK_PATH` environment variable -before running the script. +Or download: https://github.com/OneDeadKey/arsenik/archive/refs/heads/main.zip -The script will duplicate the default config for your keyboard, replace the -keymap by Arsenik’s keymap and install As-QMK’s library and default config. -Once this is done, the script will open the newly created `config.h` file with -your `$EDITOR` to let you emmidiatly toggle the different config options you -can choose from (see "Configuration" section). +### 5. Generate and Install the Arsenik Keymap -Optionnal flags can be passed to `arsenik-qmk.sh` to enable or disable certain -features: +```sh +./generator.sh --generate --copy +``` -- `-n`: “no editor” (doesn’t open the `config.h` file) -- `-b`: “build” (immidiatlly build the keymap after installing it) -- `-f`: “flash” (immidiatlly build the keymap and flash your keyboard with it - after installing it) +- `--generate`: Creates the Arsenik keymap in `output//keymaps/arsenik` +- `--copy`: Installs it to your QMK home directory -### example: +You can run these steps separately. The script will prompt before overwriting existing files. -Let’s say I have a Keebio Iris Rev2, and I want to install Arsenik-QMK for it -(with my QMK folder located in `~/Code/qmk`) then flash the keymap. First, I -find my real keyboard name: +### 6. Build the Firmware ```sh -qmk list-keyboards | grep 'iris' -# >> ... -# >> keebio/iris/rev2 -# >> ... +qmk list-keymaps -kb # Confirm 'arsenik' keymap is present +qmk compile -kb -km arsenik ``` -Then I run the script +### 7. Flash Your Keyboard + +Connect your keyboard in bootloader/recovery mode: ```sh -QMK_PATH="$HOME/Code/qmk" ./arsenik-qmk.sh keebio/iris/rev2 -f +qmk flash -kb -km arsenik ``` + +### 8. Advanced Configuration (Optional) + +Want to go further? You can fully customize your Arsenik keymap and layout: + +- Explore QMK firmware options and documentation for advanced features. +- Review the Arsenik philosophy and available configuration options in the `/qmk/keymap` files and the Arsenik documentation. +- Edit `config.h` or other keymap files in `/qmk/keymap` to adjust layers, key assignments, or Arsenik-specific settings. +- After making changes, re-run: + + ```sh + ./generator.sh --generate --copy + ``` + + and re-flash your keyboard as in steps 6 and 7. + +This workflow allows you to iterate on your layout and configuration as much as you like. + +--- + +**Need help or want to contribute?** + +- Open an issue or PR if your layout is missing or you encounter problems. +- See the Arsenik documentation for advanced configuration.