/zmk-helpers

Convenience macros simplifying ZMK's keymap configuration

Primary LanguageCMIT LicenseMIT

ZMK-Helpers (Version 2)

This is a collection of helper macros (formerly zmk-nodefree-config), simplifying the configuration of ZMK keymaps. The migration guide has instructions on how to migrate from v1. Version 1 continuous to be available here.

Installation

To use the helpers, it is recommended to add them as a module to your config/west.yml by adding a new entry to remotes and projects:

manifest:
  remotes:
    - name: zmkfirmware
      url-base: https://github.com/zmkfirmware
    - name: urob
      url-base: https://github.com/urob
  projects:
    - name: zmk
      remote: zmkfirmware
      revision: main
      import: app/west.yml
    - name: zmk-helpers
      remote: urob
      revision: main
  self:
    path: config

If you are building locally, see the instructions for building with external modules in ZMK docs.

Manual installation

Alternatively, copy include/zmk-helpers into your config/ directory:

zmk-config
├── config
│   ├── corne.keymap
│   ├── zmk-helpers
│   │   ├── helper.h
│   │   └── ...
│   └── ...
└── ...

Instead of copying, one could also add a git-submodule1:

cd /path/to/zmk-config/
git submodule add -b v2 -- https://github.com/urob/zmk-helpers config/zmk-helpers-repo
ln -s zmk-helpers-repo/include/zmk-helpers config/zmk-helpers

Usage

Source helper.h near the top of your .keymap file. Optionally, source key-labels and unicode-chars as needed:

#include "zmk-helpers/helper.h"

// Source desired key-position labels
#include "zmk-helpers/key-labels/glove80.h"

// Source unicode-chars for desired languages
#include "zmk-helpers/unicode-chars/german.dtsi"

The following subsections describe the available helpers. See the example configuration or my personal zmk-config for a demonstration.

Core helpers

The helper.h header provides a number of convenience macros for defining behaviors, combos, layers, etc.

Macro Purpose
ZMK_BEHAVIOR Create a new behavior instance (generic form)
ZMK_APPLY_MATRIX_TRANSFORM Apply a matrix_transform
ZMK_COMBO Create a combo
ZMK_CONDITIONAl_LAYER Create a tri-layer condition
ZMK_LAYER Create a layer and add it to the keymap
ZMK_LEADER_SEQUENCE Create a leader key sequence
ZMK_UNICODE_SINGLE Create a unicode-char
ZMK_UNICODE_PAIR Create a pair of lowercase/uppercase unicode-chars

In addition to the generic ZMK_BEHAVIOR macro, version 2 also provides the following explicit variants.

Macro Purpose
ZMK_AUTO_LAYER Create a new auto-layer behavior instance
ZMK_CAPS_WORD Create a new caps-word behavior instance
ZMK_HOLD_TAP Create a new hold-tap behavior instance
ZMK_KEY_REPEAT Create a new key-repeat behavior instance
ZMK_MACRO Create a new key-macro behavior instance
ZMK_MACRO_ONE_PARAM Create a new macro-one-param behavior instance
ZMK_MACRO_TWO_PARAM Create a new macro-two-param behavior instance
ZMK_MOD_MORPH Create a new mod-morph behavior instance
ZMK_STICKY_KEY Create a new sticky-key behavior instance
ZMK_TAP_DANCE Create a new tap-dance behavior instance
ZMK_TRI_STATE Create a new tri-state behavior instance (requires #1366)

The explicit behavior helpers are inspired by the native ZMK implementation of ZMK_MACRO. They differ in that they automatically create all Devicetree nodes as needed. So instead of calling them from inside the Devicetree, they should be placed outside the root node.

Note

By default, sourcing helper.h will replace the native implementation of ZMK_MACRO. To work reliably, helper.h should be included after behaviors.dtsi. To keep the native implementation of ZMK_MACRO, set #define ZMK_HELPER_KEEP_NATIVE 1 before including helper.h.

Key-labels collection

These layout headers define easy to remember "key-labels" for many popular keyboards, which can be used instead of numeric key-positions to configure position-based properties (e.g., in combos).

Key-labels are standardized to make keymaps portable across keyboards. For instance, the labels for the 60-key Sofle nest the labels for the 34-key Sweep as follows:

plot

The following layouts are currently implemented.

Header # of Keys Examples
34.h 34 Ferris, Hypergolic, Sweep
36.h 36 Corne (5 cols), Corne-ish Zen (5 cols)
42.h 42 Corne, Corne-ish Zen
4x12.h, 4x12_wide.h 48 Planck
5x6.h 60 Caldera
adv360_custom.h 76 Advantage360 Pro (custom matrix transform)
glove80.h 80 Glove80
hillside_*.h 46, 48, 52 or 56 Hillside family
jian.h 44 Jian, Jorne
kyria.h 50 Kyria
lily58.h 58 Lily58
osprette.h 34 Osprette
sofle.h 60 Sofle
totem.h 38 Totem

Unicode-characters and language collection

This collection defines unicode behaviors for all relevant characters in a given language. For instance, sourcing the German language file, one can add &de_ae to the keymap, which will send ä/Ä when pressed or shifted.

See the unicode-chars directory for a list of all currently available languages. To use these language files, follow the instructions for your OS below.

Windows

On your computer, install WinCompose. In your keymap, source helper.h and the desired language files. For example:

#include "zmk-helpers/helper.h"
#include "zmk-helpers/unicode-chars/german.dtsi"
Linux

In your keymap, set HOST_OS to 1, then source helper.h and the desired language files. For example:

#define HOST_OS 1
#include "zmk-helpers/helper.h"
#include "zmk-helpers/unicode-chars/german.dtsi"
macOS

On your computer, enable unicode input in the system preferences by selecting Unicode Hex Input as input source. In your keymap, set HOST_OS to 2, then source helper.h and the desired language files. For example:

#define HOST_OS 2
#include "zmk-helpers/helper.h"
#include "zmk-helpers/unicode-chars/german.dtsi"

Note

Unicodes allow typing international characters without changing the OS keyboard layout. See zmk-locale-generator for a collection of headers that configure ZMK to work with non-US layouts set in the OS.

Contributing

Contributions of any form are very welcome! New key-labels and unicode-chars should follow these guidelines:

Footnotes

  1. To enable the submodule when building with Github Actions, replace zmk-config/.github/workflows/build.yml with

    on: [push, pull_request, workflow_dispatch]
    
    jobs:
      build:
        uses: urob/zmk/.github/workflows/build-user-config.yml@build-with-submodules