Skip to content

Commit

Permalink
Feature/default qwerty (#5)
Browse files Browse the repository at this point in the history
* pull the qwerty keymap from the build

* add the QWERTY keymap to the config directory for use with GUI keymappers, and update the converstion script to go both ways

* update the script to take path input, and update the reusable workflow to move keymap files around for building

* update the pre req name for the build job in build.yml

* added ending quote to Generate Colemak step in build.yml

* fix fstrings in script

* removed path checking since it's required, and changed the full_path variable to a string instead of a set

* move converted_map variable to the bottom

* reverse the out_file logic so the names work correctly

* remove unterminated quote from user config workflow

* remove another unterminated quote from user config workflow

* fix the spelling of base_config_path

* list files in "${{ github.workspace }}"

* list files in "${{ github.workspace }}"

* list files in "${{ github.workspace }}"

* WIP

* troubleshooting pipeline directories"

* troubleshooting pipeline directories"

* troubleshooting pipeline directories"

* troubleshooting pipeline directories"

* troubleshooting pipeline directories"

* list files in

* change workspace variable to match what's used in GH actions

* update artifact name

* update artifact name

* update download artifact version to 3 to match the upload artifact version

* remove unterminated quote

* update the copy config step

* shorten artifact names

* shorten names for the shield, and artifact-names and change the firmware and merge names

* shorten the shield name in all files

* shorten the shield name in all files

* reset board name and keep the shorened artifact name. Also take keymap out of display_name and artifact_name

* removed unterminated quote

* wip

* try to compile with just the base layer

* try to compile with out the base layer

* try to compile with out macros and combos

* address the missing keymap file by moving it to the board directory

* change keymap name to charybdis.keymap

* update the artifact patterns for the merge job

* rename charybdis_qwerty.keymap to charybdis.keymap so web GUI can interpret it

* update actions from v3 to v4

* list files in workspace

* add the charybdis.keymap to the config directory

* try v5 of setup-python

* try v5 of setup-python

* try v5 of setup-python

* try v5 of setup-python with a name

* remove name from py v5

* update readme
  • Loading branch information
280Zo authored Aug 5, 2024
1 parent 22b9791 commit 38dd8e0
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 155 deletions.
26 changes: 11 additions & 15 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
name: ZMK Firmware Build

on: [push, pull_request, workflow_dispatch]
on: [push, workflow_dispatch]

jobs:
create-qwerty-keymap:
convert-and-store-keymap:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4

- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
# Add any dependencies here
- name: Generate QWERTY keymap
run: |
python scripts/generate_qwerty.py
- uses: actions/upload-artifact@master
- run: python scripts/convert_keymap.py -c q2c --in-path "$GITHUB_WORKSPACE/config/charybdis.keymap"

- uses: actions/upload-artifact@v4
with:
name: charybdis_qwerty.keymap
path: "${{ github.workspace }}/charybdis_qwerty.keymap"
name: keymap_files
path: ${{ github.workspace }}/config/*.keymap

build:
needs: create-qwerty-keymap
needs: convert-and-store-keymap
uses: ./.github/workflows/user_config_build.yaml
# uses: zmkfirmware/zmk/.github/workflows/build-user-config.yml@main
40 changes: 26 additions & 14 deletions .github/workflows/user_config_build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,22 +84,34 @@ jobs:
echo "zephyr_version=${ZEPHYR_VERSION}" >> $GITHUB_ENV
echo "extra_west_args=${extra_west_args}" >> $GITHUB_ENV
echo "extra_cmake_args=${shield:+-DSHIELD=\"$shield\"}${zmk_load_arg}" >> $GITHUB_ENV
echo "display_name=${shield:+$shield - }${board} - ${keymap}" >> $GITHUB_ENV
echo "artifact_name=${artifact_name:-${shield:+$shield-}${board}-zmk-${keymap}}" >> $GITHUB_ENV
echo "display_name=${shield:+$shield - }${board}" >> $GITHUB_ENV
echo "artifact_name=${artifact_name:-${shield:+$shield-}${board}-zmk}" >> $GITHUB_ENV
- name: Copy qwerty keymap to keymap directory
uses: actions/download-artifact@master
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: charybdis_qwerty.keymap
path: ${{ inputs.keymap_path }}
name: keymap_files
path: "${{ github.workspace }}/"

- name: Move keymaps to keymap directory
run: |
rm -f $GITHUB_WORKSPACE/config/*.keymap
mkdir -p "$GITHUB_WORKSPACE/config/boards/shields/charybdis-mini-wireless/keymaps/"
cd "$GITHUB_WORKSPACE"
mv charybdis.keymap charybdis_qwerty.keymap
mv *.keymap "$GITHUB_WORKSPACE/config/boards/shields/charybdis-mini-wireless/keymaps/"
ls -lR "$GITHUB_WORKSPACE/config/boards/shields/charybdis-mini-wireless/keymaps/"
- name: Copy config files to isolated temporary directory
run: |
if [ "${{ env.base_dir }}" != "${GITHUB_WORKSPACE}" ]; then
mkdir "${{ env.base_dir }}/${{ inputs.config_path }}"
cp -R ${{ inputs.config_path }}/* "${{ env.base_dir }}/${{ inputs.config_path }}/"
cp -R "${{ env.base_dir }}/${{ inputs.keymap_path }}/${{ matrix.keymap }}.keymap" \
"${{ env.base_dir }}/${{ inputs.config_path }}/boards/shields/charybdis-mini-wireless/charybdis.keymap"
base_config_path="${{ env.base_dir }}/${{ inputs.config_path }}"
mkdir "$base_config_path"
cp -R "${{ inputs.config_path }}"/* "$base_config_path/"
echo "base installed"
# Copy active keymap to the board directory
cp -Rv "$base_config_path/boards/shields/charybdis-mini-wireless/keymaps/${{ matrix.keymap }}.keymap" \
"$base_config_path/boards/shields/charybdis-mini-wireless/charybdis.keymap"
fi
echo "Build files list:"
ls -R "${{ env.base_dir }}"
Expand Down Expand Up @@ -188,14 +200,14 @@ jobs:
- name: Merge QWERTY Artifacts
uses: actions/upload-artifact/merge@v4
with:
name: "qwerty-firmware"
pattern: artifact-charybdis_QWERTY*
name: "firmware-charybdis-nanov2-qwerty"
pattern: artifact-qwerty*
delete-merged: true
- name: Merge Colemak DH Artifacts
uses: actions/upload-artifact/merge@v4
with:
name: "colemak-dh-firmware"
pattern: artifact-charybdis_colemak*
name: "firmware-charybdis-nanov2-colemakdh"
pattern: artifact-colemak*
delete-merged: true
cleanup:
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This repository outlines most of the steps needed to build/modify the ZMK firmwa

## Pre Built Firmware

If you'd like to skip all the configuration steps and use something prebuilt, the firmware files for qwerty and colemak dh can be found in the [Actions Workflows](https://github.com/280Zo/charybdis-wireless-mini-zmk-firmware/actions?query=is%3Acompleted+branch%3Amain). Just click the link, select the latest run that passed on the main branch, and download the qwerty or colemak firmware. There are a few things to note about how I've chosen to configure things.
If you'd like to skip all the configuration steps and use something prebuilt, the firmware files can be found in the [Actions Workflows](https://github.com/280Zo/charybdis-wireless-mini-zmk-firmware/actions?query=is%3Acompleted+branch%3Amain). Just click the link, select the latest run that passed on the main branch, and download the qwerty or colemak firmware (if you don't know the difference you probably want qwerty). There are a few things to note about how I've chosen to configure things.

- The keyboard name is Charybdis. This is what will show up when you connect to it with bluetooth.
- ZMK has terms for each side of a split keyboard. Central is the half that sends keyboard outputs over USB or advertises to other devices over bluetooth. Peripheral is the half that will only send keystrokes to the central once they are paired and connected through bluetooth. I have chosen the right side as central because it fits my desk layout better.
Expand Down
8 changes: 4 additions & 4 deletions build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ include:
- board: nice_nano_v2
shield: charybdis_left
keymap: charybdis_colemak_dh
artifact-name: charybdis_colemak_left
artifact-name: colemak_left
- board: nice_nano_v2
shield: charybdis_right
keymap: charybdis_colemak_dh
artifact-name: charybdis_colemak_right
artifact-name: colemak_right
- board: nice_nano_v2
shield: charybdis_left
keymap: charybdis_qwerty
artifact-name: charybdis_QWERTY_left
artifact-name: qwerty_left
- board: nice_nano_v2
shield: charybdis_right
keymap: charybdis_qwerty
artifact-name: charybdis_QWERTY_right
artifact-name: qwerty_right
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ features:
- colemak DH
siblings:
- charybdis_left
- charybdis_right
- charybdis_right
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@

Base {
bindings = <
&kp C_AC_SEARCH &kp Q &kp W &kp F &kp P &kp B &kp J &kp L &kp U &kp Y &kp APOS &to 5
&hm LG(E) TAB &hm LEFT_GUI A &hm LEFT_ALT R &hm LCTRL S &hm LEFT_SHIFT T &kp G &kp M &hm LEFT_SHIFT N &hm RCTRL E &hm RIGHT_ALT I &hm LEFT_META O &kp DEL
&kp LA(LC(T)) &kp Z &mt LC(LA(LEFT_SHIFT)) X &mt LA(LC(LG(LEFT_SHIFT))) C &kp D &kp V &kp K &kp H &mt LA(LC(LG(LEFT_SHIFT))) COMMA &mt LC(LA(LEFT_SHIFT)) PERIOD &kp FSLH &to 6
&hm LC(F10) C_PLAY_PAUSE &lt 1 BACKSPACE &lt 2 ESCAPE &lt 4 RETURN &lt 3 SPACE
&kp C_AC_SEARCH &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &to 5
&hm LG(E) TAB &hm LEFT_GUI A &hm LEFT_ALT S &hm LCTRL D &hm LEFT_SHIFT T &kp G &kp H &hm LEFT_SHIFT J &hm RCTRL K &hm RIGHT_ALT L &hm LEFT_META SEMICOLON &kp DEL
&kp LA(LC(T)) &kp Z &mt LC(LA(LEFT_SHIFT)) X &mt LA(LC(LG(LEFT_SHIFT))) C &kp F &kp V &kp B &kp N &mt LA(LC(LG(LEFT_SHIFT))) COMMA &mt LC(LA(LEFT_SHIFT)) PERIOD &kp FSLH &to 6
&hm LC(F10) C_PLAY_PAUSE &lt 1 BACKSPACE &lt 2 ESCAPE &lt 4 RETURN &lt 3 SPACE
>;
};

Expand Down
175 changes: 175 additions & 0 deletions scripts/convert_keymap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import re
import os
import sys
import argparse

def main():
#####################################################################
# Define variables & write output keymap file
#####################################################################

# Create the parser
parser = argparse.ArgumentParser(description="A script that converts ZMK keymap files from QWERTY <|> Colemak DH")
# Define flags and parameters
parser.add_argument(
'-c', '--convert',
type=str,
choices=['q2c', 'c2q'],
default='q2c',
help="Specify the conversion: 'q2c' will convert QWERTY to Colemak DH, 'c2q' will convert Colemak DH to QWERTY (default: 'q2c')"
)
parser.add_argument(
'--in-path',
type=str,
required=True,
help="Path to the input keymap file. This is the path where the ouitput will be stored as well"
)
# Parse the arguments
args = parser.parse_args()
# Set the variable for the chosen option
conversion_type = args.convert
full_path = args.in_path

# Check argument values and convert keymap
if conversion_type not in ['q2c','c2q']:
print("Error: Invalid conversion type selected.")
sys.exit(1)

path, in_file = os.path.split(full_path)
out_file = 'charybdis_qwerty.keymap' if conversion_type == 'c2q' else 'charybdis_colemak_dh.keymap'
out_full_path = os.path.join(path, out_file)

print("#####################################################################")
print(f"Selected conversion type: {conversion_type}")
print(f"path:........{path}")
print(f"input_file:..{in_file}")
print(f"out_file:....{out_file}")
print("#####################################################################")

#####################################################################
# Define conversions
#####################################################################

if conversion_type == 'q2c':
initial_keymap = {
# Top row (numbers and symbols are not included in this example)
'Q': 'Q', 'W': 'W', 'E': 'F', 'R': 'P', 'T': 'B', 'Y': 'J', 'U': 'L', 'I': 'U', 'O': 'Y', 'P': 'APOS',
# Home row
'A': 'A', 'S': 'R', 'D': 'S', 'F': 'D', 'G': 'G', 'H': 'M', 'J': 'N', 'K': 'E', 'L': 'I', 'SEMICOLON': 'O',
# Bottom row
'Z': 'Z', 'X': 'X', 'C': 'C', 'V': 'V', 'B': 'K', 'N': 'H',
# Special keys (not row-specific)
'TAB': 'TAB', 'DEL': 'DEL', 'BACKSPACE': 'BACKSPACE', 'ESCAPE': 'ESCAPE', 'RETURN': 'RETURN', 'SPACE': 'SPACE'
}
else:
initial_keymap = {
# Top row (numbers and symbols are not included in this example)
'Q': 'Q', 'W': 'W', 'F': 'E', 'P': 'R', 'B': 'T', 'J': 'Y', 'L': 'U', 'U': 'I', 'Y': 'O', 'APOS': 'P',
# Home row
'A': 'A', 'R': 'S', 'S': 'D', 'D': 'F', 'G': 'G', 'M': 'H', 'N': 'J', 'E': 'K', 'I': 'L', 'O': 'SEMICOLON',
# Bottom row
'Z': 'Z', 'X': 'X', 'C': 'C', 'V': 'V', 'K': 'B', 'H': 'N',
# Special keys (not row-specific)
'TAB': 'TAB', 'DEL': 'DEL', 'BACKSPACE': 'BACKSPACE', 'ESCAPE': 'ESCAPE', 'RETURN': 'RETURN', 'SPACE': 'SPACE'
}

#####################################################################
# Read and store input keymap
#####################################################################

# Read the content of the keymap_contents
with open(full_path, 'r') as keymap_file:
keymap_contents = keymap_file.read()

#####################################################################
# Functions
#####################################################################

def convert_keymap(keymap_contents):
# Define regex pattern to find the 'Base' keymap section
base_keymap_pattern = re.compile(r'(Base\s*\{\s*bindings\s*=\s*<\s*)(.*?)(\s*>;)', re.DOTALL)
# Apply regex substitution to convert keymap
new_keymap_contents = base_keymap_pattern.sub(replace_keymap, keymap_contents)
return new_keymap_contents

# Find and replace the 'Base' keymap layer
def replace_keymap(match):
before_keymap = match.group(1)
old_keymap = match.group(2)
after_keymap = match.group(3)

print(f"Found Base keymap \n{old_keymap}")

# Split the old keymap by lines
lines = old_keymap.strip().split('\n')

# Process each line
new_lines = []
print("Converting letter keys")
for line in lines:
# Split the line by spaces or other delimiters
parts = line.split()
new_parts = []

for part in parts:
if not part.startswith('&'):
# Extract key (removing ZMK behavior commands)
key = part.split()[1] if len(part.split()) > 1 else part
# Map the key to the conversion type if applicable
if key.upper() in initial_keymap:
print(key.upper(),end=":")
new_key = initial_keymap[key]
print(new_key)
new_parts.append(part.replace(key, new_key))
else:
new_parts.append(part)
else:
new_parts.append(part)

# Join new parts for the line and add to new_lines
new_lines.append(' '.join(new_parts))

# Join new lines to form the new keymap keymap_contents
new_keymap = '\n'.join(new_lines)
print(f"\nGenerated {out_file} \n{format_columns(new_keymap)}")
return before_keymap + format_columns(new_keymap) + after_keymap

def format_columns(text):
zmk_behavior = r'(&\w{2})'

# Split the input text into lines
lines = text.strip().split('\n')

# Split each line into columns
split_lines = [re.split(zmk_behavior,line) for line in lines]

# Determine the number of columns
num_columns = max(len(line) for line in split_lines)

# Calculate the maximum width for each column
column_widths = [0] * num_columns
for line in split_lines:
for i, item in enumerate(line):
column_widths[i] = max(column_widths[i], len(item))

# Format each line with the calculated column widths
formatted_lines = []
for line in split_lines:
formatted_line = ''.join(f"{item:<{column_widths[i] + 1}}" for i, item in enumerate(line))
formatted_lines.append(formatted_line)

# Join all formatted lines
formatted_text = '\n'.join(formatted_lines)
return formatted_text

converted_map = convert_keymap(keymap_contents)

# Write the new keymap_contents to the output file
with open(out_full_path, 'w') as file:
file.write(converted_map)

print("#####################################################################")
print(f"Updated keymap written to {out_full_path}")
print("#####################################################################")
if __name__ == "__main__":
main()
Loading

0 comments on commit 38dd8e0

Please sign in to comment.