Releases: caksoylar/keymap-drawer
v0.19.0
This release updates ZMK parsing to use a tree-sitter-based parser and adds support for ZMK physical layouts in devicetree format (used by Studio), among other improvements.
The new parsing implementation results in speed improvements that range from 10% shorter runtime to 7x, with a median speed-up of ~2x in my test cases.
If you encounter any new problems with parsing your keymaps, please open an issue!
Features
Drawing
- Add
dts_layout
option for physical layouts, and corresponding--dts-layout
CLI arg.- This is analogous to
qmk_info_json
field pointing to a file path, except the file should contain ZMK's physical layout nodes in devicetree
- This is analogous to
- Deprecated
qmk_layout
field in physical layout definitions, and corresponding--qmk-layout
CLI arg.
Uselayout_name
instead, which also works withdts_layout
above
Parsing
- Add
parse_config.layer_legend_map
which can be used to customize how layer names are represented in the keymap- This is similar to how e.g.
zmk_keycode_map
is used to change keycode representations, but applied to layer names instead
- This is similar to how e.g.
- Switch to a
tree-sitter-devicetree
-based parser for ZMK, from the oldpyparsing
-based one - Add
--virtual-layers
CLI argument tokeymap parse
- This appends empty "virtual" layers at the end of the keymap; this can be used for assigning combos etc. to show them on a separate diagram
- Also look-up behavior prefixes in
raw_binding_map
- For example match entries like
&td
for ZMK behavior bindings like&td 0
to fix for behaviors nested in hold-taps
- For example match entries like
Fixes
- Ignore "reserved" ZMK layers while parsing, used for ZMK Studio
- Better support for Studio-related ZMK updates to come, see #125
- Switch to using Github raw URL for
mdi
glyphs, by @magicDGS in #132- The old unpkg URL was unreliable and seems to have eventually disappeared
- Add retries and a more generous timeout for fetching SVG glyphs from remote URLs
- More correctly center/normalize QMK physical layouts when there are rotated keys
ZMK drawing workflow
- Use pipx for installs in draw-zmk.yml (PEP 668) by @janwvjaarsveld in #118
- Enable extended globbing for pattern matching by @thazhemadam in #121
New Contributors
- @janwvjaarsveld made their first contribution in #118
- @thazhemadam made their first contribution in #121
- @dhruvinsh made their first contribution in #126
- @magicDGS made their first contribution in #132
Full Changelog: v0.18.1...v0.19.0
v0.18.1
This release contains a couple bug fixes.
- Avoid newlines between 2 tspan elements by @wouterj in #114. This fixes the annoying horizontal mis-alignment when the tap legend had 3+lines.
- Add an additional
u
alias for key width in json-formatqmk_keyboard
. This is sometimes emitted by https://nickcoutsos.github.io/keymap-layout-tools after importing e.g. Kicad PCB files.
v0.18.0: ZMK modules support and layer key styling
This release adds support for parsing ZMK configs that use modules like zmk-helpers with additional config options, along with adding special styling to layer key legends and making them clickable.
Edit: zmk-helpers
now have docs on using keymap-drawer
with it using below changes.
Features
Drawing
-
Breaking change: Add new config option
draw_config.style_layer_activators
which defaults to true. This marks layer activators legends by adding a link that goes to the corresponding layer (might not work for embedded SVGs), and adding an underline by default.- If you want to restore the old behavior, this setting can be disabled in the config file:
draw_config: { style_layer_activators: false }
- You can change the styling, e.g. if you want italic instead of underlined:
draw_config: svg_extra_style: | text.layer-activator { text-decoration: none; font-style: italic }
- If you want to restore the old behavior, this setting can be disabled in the config file:
-
Add a new CSS class
alternate
so you can define separate styling for extra activators marked by theparse_config.mark_alternate_layer_activators
config (no styling defined by default) (#98)- Example:
parse_config: mark_alternate_layer_activators: true draw_config: svg_extra_style: | rect.held.alternate { fill: #478583; } @media (prefers-color-scheme: dark) { rect.held.alternate { fill: #478583; } } # some other color here
- Example:
-
Add
hidden
property to the combo spec, so you can avoid drawing certain combos that the parser outputs by addinghidden: true
(for instance throughparse_config.zmk_combos
) (#104)- Example:
parse_config: zmk_combos: combo_esc: { hidden: true }
- Example:
-
Support using underscore instead of space as split separator for the cols+thumbs notation spec in order to reduce command line quoting issues
- Example:
keymap draw -n 33333+2_3+233331 my_asymmetric_keymap.yaml
- Example:
-
Implement support for
layout_aliases
inqmk_keyboard
physical layout definitions
Parsing
- Add
parse_config.zmk_additional_includes
to augment the preprocessor include path (#105)- This can be used to be able to parse keymaps using
zmk-helpers
using the module functionality, since#include
s aren't using relative paths in that case. Example:parse_config: zmk_additional_includes: [ "zmk-helpers/include" ]
- If you want to use it in the automated ZMK drawing workflow, use the new
west_config_path
argument to the workflow (#107) so that the modules defined in thewest.yml
file are automatically fetched. (You still need the above value in the config.) Example:jobs: draw: uses: caksoylar/keymap-drawer/.github/workflows/draw-zmk.yml@main permissions: contents: write # allow workflow to commit to the repo with: [...] west_config_path: 'config' # this folder contains west.yml with module definitions
- Module fetching is not (yet) supported in the ZMK URL parse option of the web app
- This can be used to be able to parse keymaps using
- Add
parse_config.zmk_preamble
config option which is text inserted at the beginning of the keymap, usually used to modify preprocessor behavior. It defaults to#define KEYMAP_DRAWER
(#103)- The default value exposes the existing behavior which was being defined internally before this change
- Restore support for using modified keycodes like
LC(LEFT)
inparse_config.*_keycode_map
that was removed in v0.16 (#106)
Fixes
- More robust devicetree parsing because of a few fixes involving parsing phandle arrays, such as when elements can have commas or split to multiple
<...>, <...>;
blocks (#102) - More robust QMK keymap.json parsing, for cases where the keycodes can contain extra spaces
Misc
- Add a physical layout definition for
hummingbird
keyboard - For unibody keyboards like
fingerpunch/ffkb
andrufous
, change the default physical layout to avoid all keys being rotated. This should improve readability by sacrificing faithfulness to the actual layout- The older rotated versions are available using
fingerpunch/ffkb_rotated
andrufous_rotated
- The older rotated versions are available using
Full Changelog: v0.17.0...v0.18.0
v0.17.0
This is a release with minor external-facing changes, since most of them were internal tweaks to help downstream users like the web app.
I recently spent some time working on it at https://caksoylar.github.io/keymap-drawer and implemented a few improvements (and added sorely needed tooltips). If you haven't checked it out lately, you might want to have a look!
Also if you are a Kanata user, you can check out the work-in-progress Kanata config parser at https://github.com/caksoylar/keymap-drawer/tree/kanata and related issue #95.
Features
Drawing
- Breaking change: Truncate legends when they are too long:
- Number of lines in the
tap
field is truncated to at most 3; if >3, 3rd line will be replaced with…
- Length of each legend (in a single line) is truncated to
1.7 × draw_cfg.shrink_wide_legends
(by default11
) chars. If longer than that, the last visible char will be replaced with…
, similar to above
- Number of lines in the
Fixes
- Fix parsing of devicetree arrays when they are split to multiple lines and multiple
<...>
blocks
Misc
- Add Ferris physical layout with rotated thumb keys, applying to all Ferris/Sweep variants
- This will be used by default; if you don't want this you can use the original
info.json
withkeymap draw --qmk-info-json
argument, or the new "Layout Override" dialog in the web app
- This will be used by default; if you don't want this you can use the original
- Add Swoop physical layout
- Add support for generic physical layouts via
layout: {qmk_keyboard: generic/<layout_name>}
, which are specially fetched from https://github.com/qmk/qmk_firmware/tree/master/layouts/default/ (wherelayout_name
is a subfolder name)
Full Changelog: v0.16.0...v0.17.0
v0.16.0: Dark mode and modifier functions parsing
This release contains two major new features: parsing of modifier functions and dark mode support! It also contains a couple of smaller breaking changes, so make sure to check them out below.
Features
Parsing
- Added support for parsing modifier functions like
LC(V)
in ZMK andLCTL(KC_V)
in QMK, used for sending modified keycodes like ctrl+v events with one key press- By default these will be converted to
Ctl+ V
representation, this is configurable via the newparse_config.modifier_fn_map
setting - You can also assign special names to specific mod combinations, like
Hyper+ X
forLC(LS(LG(LA(X))))
- Breaking change: If you were using entries like
LC(V): Paste
inparse_config.zmk_keycode_map
orC(V): Paste
inqmk_keycode_map
, they will no longer work becauseLC
andV
parts are processed separately. If you want to preserve the mapping, instead define them inraw_binding_map
like&kp LC(V): Paste
for ZMK orC(KC_V): Paste
for QMK.
- By default these will be converted to
- Added parsing for QMK tap-toggle layers
TT(LAYER)
by @m-demare in #87
Drawing
- Added dark mode support, by @snoyer!
- This is implemented as a special set of CSS overrides that get added to the final CSS if the new
draw_config.dark_mode
setting is on, or added under@media (prefers-color-scheme: dark)
when set to"auto"
to fit the web page or OS light/dark setting. - The default is
false
which means light mode only, so this is not a breaking change for CLI users. The web app overrides it to"auto"
.
- This is implemented as a special set of CSS overrides that get added to the final CSS if the new
dark_mode: false |
dark_mode: true |
dark_mode: auto |
---|---|---|
-
Added support for appending footer text to produced SVGs using
draw_config.footer_text
- The value goes into a
<text>
element but it isn't escaped, so you can add e.g. links using<a>
tags - The default value is empty so this isn't a breaking change for CLI users. The web app overrides it to "Created with keymap-drawer"
- The value goes into a
-
Added support for using Phosphor Icons, check out how to use them in the README section
CLI
- Added
-o
/--output
parameter to allkeymap
subcommands, to write their output to the given path rather than stdout- Using these parameters are recommended if you are running the CLI on Windows, since they ensure the outputs are written with
utf-8
encoding rather than the locale-specific one (which can break many things). This release also incorporates a couple fixes that ensure operation in Windows (tested in powershell) - Breaking change:
keymap draw --ortho-layout
no longer supports the-o
short form since that is taken over by the output parameter
- Using these parameters are recommended if you are running the CLI on Windows, since they ensure the outputs are written with
Full Changelog: v0.15.0...v0.16.0
v0.15.0: QMK keyboard mapping
This is a smaller release with a couple of features that I wanted to release quickly: Automatic QMK keyboard mappings and changes to the config dumping.
Features
- Breaking change: Added a new mapping layer for QMK keyboard names
- This allows us to map given QMK keyboard name prefixes to other keyboard names during drawing
- It is currently used to map Corne, Lily58, Sofle and Kyria variants to the versions with rotated keys in
qmk_layouts
folder - This is a breaking change if you were using e.g.
qmk_keyboard: crkbd/rev1
rather thanqmk_keyboard: corne_rotated
-- there is no way to prevent this mapping right now, so let me know if you really want the old behavior instead
- Breaking change: Config dumps via
keymap dump-config
no longer include certain "internal" draw config options, namelysvg_style
,glyph_urls
anduse_local_cache
- The rationale is that these shouldn't typically touched by users, and having them be present in all configs creates issues when default values change (such as when #78 is fixed)
- You can still override them in your config by manually including the keys, the functionality didn't change
Fixes
- Specially parse
0xff
as a special value in thelayers
property of the combo spec in ZMK keymaps, to mean all layers. This is used by nodefree-config
Misc
- Add Kyria physical layout with rotated keys, by @micampe
- Log what config args are used during ZMK drawing workflow
Full Changelog: v0.14.1...v0.15.0
v0.14.x: Cols+thumbs notation, and more
It has been some time since the last release so this release is mostly a collection of smaller improvements, a lot of them contributed by the community (thanks!).
You might have noticed we also have a logo now, itself generated in keymap-drawer
!1
Features
Parsing
- Support parsing of overridden node properties with
&nodelabel { prop = "new_value"; };
syntax (#66)
Drawing
- Add a new way to specify physical layouts: "Cols+Thumbs" notation! This generates layouts with only non-rotated 1u keys, but it is significantly more flexible than
ortho_layout
. It supports columns with arbitrary number of keys, moving the thumb clusters left/right, asymmetric and 2+ number of split keyboard parts.
See the documentation in the keymap spec to start using. - Assign
key.type
to the CSS class of combos by @englmaxi in #73 - Add a thin gray outline to combo boxes, to be consistent with key styling and look better
ZMK workflow
- Add workflow input for base path for
<keymap>.json
layout files by @michaelrommel in #71 - Add published artifacts as a destination option by @michaelrommel in #72
- Add a workflow input to fail GitHub action on parse/draw errors by @englmaxi in #74
Fixes
- Update Tabler glyphs url that changed (again) by @thebino in #79
v0.14.1
: Fix parsing for Tabler glyphs by @SethMilliken in #82
- Use bounding boxes of combo boxes to properly calculate layer heights, to fix rendering issues with small
draw_config.outer_pad_h
values (#70) - Disallow using unrecognized fields in layer key specs or combo specs in keymap YAMLs
Misc
- Add kilipan/zilpzalp keyboard by @kilipan in #68
- Add BastardKB boards by @finrod09 in #76
- Add ZSA Voyager layout by @stasmarkin in #75
- Upgrade Pydantic to version 2.x, along with other dev dependencies
Full Changelog: v0.13.4...v0.14.0
-
Here is the source keymap YAML for posterity:
draw_config: append_colon_to_layer_header: false svg_extra_style: "text.key { font-weight: bold; font-size: 16px; }" glyph_tap_size: 16 layers: " ": [keymap, drawer] combos: - {p: [0, 1], k: $$mdi:keyboard$$, a: bottom, o: 0.15, arc_scale: 1.2} - {p: [0, 1], k: $$mdi:pencil-ruler$$, a: top, o: -0.15, d: false}
And layout json:
↩[ { "x": 0, "y": 0, "w": 1.2, "h": 1.2, "r": 15, "rx": 1.2, "ry": 0 }, { "x": 1.2, "y": 0, "w": 1.2, "h": 1.2, "r": -15, "rx": 1.2, "ry": 0 } ]
v0.13.x: Parsing tweaks and new combo configs
This release has a few fixes, adds more combo options to customize drawing and new ways to customize the ZMK parsing behavior.
Features
Parsing
- Add parsing for toggled keys, i.e..
&tog
,&to
,&kt
for ZMK,TG
,TO
,DF
for QMK- The added label can be customized via
parse_config.toggle_label
- The added label can be customized via
- Add a way to customize how keymap-drawer parses ZMK keymaps, via the
KEYMAP_DRAWER
define- The ZMK parser now defines this symbol before parsing
- You can use it to add keymap-drawer-specific defines without affecting the ZMK build via
#ifdef KEYMAP_DRAWER ... #endif
guards - You can use it to have keymap-drawer ignore certain parts without affecting the ZMK build via
#ifndef KEYMAP_DRAWER ... #endif
guards
- Add a way to specify prefixes to be removed from keycodes before further processing, via
parse_config.qmk_remove_keycode_prefix
andparse_config.zmk_remove_keycode_prefix
- See example in #50 (comment) on how to combine above these two features to better handle locale headers like the ones generated via
zmk-locale-generator
- This feature broke
parse_config.trans_legend
in v0.13.0, fixed in v0.13.1 (#62)
- See example in #50 (comment) on how to combine above these two features to better handle locale headers like the ones generated via
Drawing
- Add
rotation (r)
field to the combo spec so you can individually rotate combo boxes -- this is in addition towidth
,height
properties from v0.12.0 - Also add
draw_separate
field to the combo spec to let you decide whether you want a combo to be drawn on the layers, or using a separate diagram for that combodraw_config.separate_combo_diagrams
setting introduced in v0.11.0 now sets the default behavior for combos ifdraw_separate
isn't specified
Fixes
- Add support for using
display-name
in addition tolabel
for figuring out ZMK layer names - Calculate the total layer height (which can be increased due to combo boxes) in the correct way, rather than doing a rough approximation
- Fix bug during glyph aspect ratio calculation which led to small glyphs for
$$material:...$$
SVGs -- thanks to @dhruvinsh for the bringing up the issue (and sorry for the late fix) - Fix
APOS
/APOSTROPHE
mapping in defaultzmk_keycode_map
- Update Tabler template URL to fetch SVGs from using
$$tabler:...$$
in v0.13.2, since the previous one doesn't seem to work anymore
Misc
- Added user friendly(-er) configuration reference at CONFIGURATION.md
- Fix layout mapping for
luna
keyboard and make it use the splayed Hummingbird variant - Add layouts for BastardKB Dilemma v2 and MAX, overriding the defaults when used with
qmk_keyboard: bastardkb/dilemma/3x5_3
andqmk_keyboard: bastardkb/dilemma/4x6_4
, by @casuanoob - Add layout mapping for
wizza
Looking forward
One feature that I have been working on some time is parsing for modified keys, to automatically convert keycodes like &kp LC(LS(A))
to strings like Ctrl+Shift+A
. While the implementation is complete and the end result is configurable, I still haven't reached a decision on the default configuration for how to do the conversion so I haven't merged it to the main
branch. I iterated through a few variations, e.g.
Ctrl+Shift+ A
resulting inA
rendered on a separate line (default in the implementation)- Also automatically uses
Hyper
andMeh
for the appropriate mod combinations
- Also automatically uses
CS+A
C-S-A
- Using Mac-like symbols like
⎈⇧A
You can test this feature in the dev
branch (also deployed to streamlit) and let me know your opinions/suggestions in the discussion linked to this release.
Full Changelog: v0.12.1...v0.13.1
v0.12.0 and v0.12.1
This release contains a couple minor features, a few fixes and some physical layout updates for ZMK keyboards.
Features
- Add per-combo
width (w)
andheight (h)
field support. Defaults todraw_config.combo_w
/draw_config.combo_h
if they aren't specified or are null - Add
draw_config.svg_extra_style
config that gets appended todraw_config.svg_style
. This way you don't need to duplicate and modifydraw_config.svg_style
in your configuration and can simply add your overrides todraw_config.svg_extra_style
Fixes
- Fix invalid SVG error when using special char in layer labels by @HelloThisIsFlo in #55
- Move workflow write permission field from workflow file to usage example
Misc
- Add a Sofle layout with rotated thumb keys by @YellowAfterlife in #46
- Fix FFKB coordinates order by @jaeyounglee978 in #52
- Add physical layouts support for keyboards designed by @hazels-garage and @cyril279
- Fix Glove80 thumb cluster layout
- Key ordering broken in v0.12.0 and then fixed in v0.12.1
- Add support for a few new ZMK shields:
microdox_v2
,reviung34
,reviung53
, fixedtidbit
Full Changelog: v0.11.0...v0.12.1
v0.11.0: New drawing features
This release introduces a few major drawing features, automated ZMK workflow improvements and a major internal refactor to improve the project structure.
Features
-
Multiple output columns!
- Set the
draw_config.n_columns
variable to e.g. 3 to output with three layer columns
- Set the
-
Separate combo diagrams! For those of you who use thumb+alpha combos or steno-like keymaps, there is now the option
to draw each combo in a separate minified layer diagram, showing the output key and the triggering key positions.- Set
draw_config.separate_combo_diagrams: true
to enable, anddraw_config.combo_diagrams_scale
to tweak the scaling factor (default2
) - Currently the
layers
property of the combos are ignored and not visualized, might be added in the future if there is a clean way to show it - Key corner radii are currently not scaled, so the keys will look rounder for higher scale factors
- Set
-
Add key sides to drawn keys to give a keycap "profile" appearance, by @riccardoflp
draw_config.draw_key_sides: true
to enable, tweak the appearance viadraw_config.key_side_pars
- Currently may not render well on Safari, looking into workarounds
Fixes
- Sort SVG glyph defs before writing to avoid non-deterministic output
- Tweak Tabler-related CSS to hide the outline boxes in Safari, by @bryanforbes
- Fix font size issue in hold/shifted fields due to
draw_config.shrink_wide_legends
, byinxi
(at MoErgo Discord) - Fix issue creating unnecessarily long dendrons for certain combo types
ZMK drawing workflow
- Add option to amend the last commit and also commit parse output YAML, by @minusfive
- Recursively checkout the repo to support git submodules like zmk-nodefree-config, by @shroomist
Misc
- Tweak classes for output SVG elements to allow for better customization via CSS
- Assign
key
/combo
classes to rect+text elements for layout keys/combos - Assign
keypos-N
/combopos-N
classes to key/combo elts. to allow addressing via position indexN
- Assign
- Add a proper physical layout for
slicemk_ergodox
, by @xudongzheng - Round SVG coordinate/size values for better readability and smaller output size, by @art4ride and me
Note that future updates might unfortunately include more CSS changes, such as converting to the descendants selector syntax, e.g. .held rect { ... }
from rect.held { ... }
. Thanks to the folks at LowProKB and MoErgo for helpful discussions.
I will also prioritize a better documentation organization in the short term, possibly hosted on Github pages.
Full Changelog: v0.10.0...v0.11.0