keymapviz
keymapviz copied to clipboard
[Suggestion] Leverage QMK's info.json for diagrams
Currently, adding keymapviz support for a keyboard requires a considerable amount of manual effort; This is not scalable to QMK's 2k+ boards.
An "easy" way to extend keymapviz's support from 16 boards to ~2k keyboards would be to take inspiration from qmk info -m
.
To give an example, qmk info --matrix --keyboard merge/um70
reads qmk_firmware/keyboards/merge/um70/info.json
to determine how to draw the layout diagram (this is also what the online QMK configurator uses to draw the layout)
❯ qmk info -m -kb merge/um70
Keyboard Name: UM-70
Manufacturer: Merge
Website: https://mergedesign.store/um-70
Maintainer: duoshock
Keyboard Folder: merge/um70
Layouts: LAYOUT_lspace_2u_bksp, LAYOUT_lspace_split_bksp, LAYOUT_rspace_2u_bksp, LAYOUT_rspace_split_bksp
Processor: atmega32u4
Bootloader: atmel-dfu
Matrix for "LAYOUT_rspace_split_bksp":
┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐
│0A││0B││0C││0D││0E││0F││0G│ │5A││5B││5C││5D││5E││5F││5G││5H│ │7H│
└──┘└──┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└──┘└──┘└──┘ └──┘
┌────┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌────┐ ┌──┐
│1A ││1B││1C││1D││1E││1F│ │6A││6B││6C││6D││6E││6F││6G││6H │ │8H│
└────┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└──┘└──┘└────┘ └──┘
┌──┐ ┌─────┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌───────┐ ┌──┐
│4F│ │2A ││2B││2C││2D││2E││2F│ │7A││7B││7C││7D││7E││7F││7G │ │9H│
└──┘ └─────┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└──┘└───────┘ └──┘
┌──┐ ┌───────┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌─────┐
│4G│ │3A ││3B││3C││3D││3E││3F│ │8A││8B││8C││8D││8E││8F │ ┌──┐
└──┘ └───────┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└─────┘ │8G│
┌──┐ ┌───┐┌───┐┌───┐┌───┐┌───────┐ ┌─────────┐┌────┐┌────┐ └──┘
│4H│ │4A ││4B ││4C ││4D ││4E │ │9A ││9B ││9C │ ┌──┐┌──┐┌──┐
└──┘ └───┘└───┘└───┘└───┘└───────┘ └─────────┘└────┘└────┘ │9D││9E││9F│
└──┘└──┘└──┘
Matrix for "LAYOUT_rspace_2u_bksp":
┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──────┐ ┌──┐
│0A││0B││0C││0D││0E││0F││0G│ │5A││5B││5C││5D││5E││5F││5H │ │7H│
└──┘└──┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└──┘└──────┘ └──┘
┌────┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌────┐ ┌──┐
│1A ││1B││1C││1D││1E││1F│ │6A││6B││6C││6D││6E││6F││6G││6H │ │8H│
└────┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└──┘└──┘└────┘ └──┘
┌──┐ ┌─────┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌───────┐ ┌──┐
│4F│ │2A ││2B││2C││2D││2E││2F│ │7A││7B││7C││7D││7E││7F││7G │ │9H│
└──┘ └─────┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└──┘└───────┘ └──┘
┌──┐ ┌───────┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌─────┐
│4G│ │3A ││3B││3C││3D││3E││3F│ │8A││8B││8C││8D││8E││8F │ ┌──┐
└──┘ └───────┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└─────┘ │8G│
┌──┐ ┌───┐┌───┐┌───┐┌───┐┌───────┐ ┌─────────┐┌────┐┌────┐ └──┘
│4H│ │4A ││4B ││4C ││4D ││4E │ │9A ││9B ││9C │ ┌──┐┌──┐┌──┐
└──┘ └───┘└───┘└───┘└───┘└───────┘ └─────────┘└────┘└────┘ │9D││9E││9F│
└──┘└──┘└──┘
Matrix for "LAYOUT_lspace_2u_bksp":
┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──────┐ ┌──┐
│0A││0B││0C││0D││0E││0F││0G│ │5A││5B││5C││5D││5E││5F││5H │ │7H│
└──┘└──┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└──┘└──────┘ └──┘
┌────┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌────┐ ┌──┐
│1A ││1B││1C││1D││1E││1F│ │6A││6B││6C││6D││6E││6F││6G││6H │ │8H│
└────┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└──┘└──┘└────┘ └──┘
┌──┐ ┌─────┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌───────┐ ┌──┐
│4F│ │2A ││2B││2C││2D││2E││2F│ │7A││7B││7C││7D││7E││7F││7G │ │9H│
└──┘ └─────┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└──┘└───────┘ └──┘
┌──┐ ┌───────┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌─────┐
│4G│ │3A ││3B││3C││3D││3E││3F│ │8A││8B││8C││8D││8E││8F │ ┌──┐
└──┘ └───────┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└─────┘ │8G│
┌──┐ ┌───┐┌───┐┌───┐┌───────┐┌───┐ ┌─────────┐┌────┐┌────┐ └──┘
│4H│ │4A ││4B ││4C ││4E ││4D │ │9A ││9B ││9C │ ┌──┐┌──┐┌──┐
└──┘ └───┘└───┘└───┘└───────┘└───┘ └─────────┘└────┘└────┘ │9D││9E││9F│
└──┘└──┘└──┘
Matrix for "LAYOUT_lspace_split_bksp":
┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐
│0A││0B││0C││0D││0E││0F││0G│ │5A││5B││5C││5D││5E││5F││5G││5H│ │7H│
└──┘└──┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└──┘└──┘└──┘ └──┘
┌────┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌────┐ ┌──┐
│1A ││1B││1C││1D││1E││1F│ │6A││6B││6C││6D││6E││6F││6G││6H │ │8H│
└────┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└──┘└──┘└────┘ └──┘
┌──┐ ┌─────┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌───────┐ ┌──┐
│4F│ │2A ││2B││2C││2D││2E││2F│ │7A││7B││7C││7D││7E││7F││7G │ │9H│
└──┘ └─────┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└──┘└───────┘ └──┘
┌──┐ ┌───────┐┌──┐┌──┐┌──┐┌──┐┌──┐ ┌──┐┌──┐┌──┐┌──┐┌──┐┌─────┐
│4G│ │3A ││3B││3C││3D││3E││3F│ │8A││8B││8C││8D││8E││8F │ ┌──┐
└──┘ └───────┘└──┘└──┘└──┘└──┘└──┘ └──┘└──┘└──┘└──┘└──┘└─────┘ │8G│
┌──┐ ┌───┐┌───┐┌───┐┌───────┐┌───┐ ┌─────────┐┌────┐┌────┐ └──┘
│4H│ │4A ││4B ││4C ││4E ││4D │ │9A ││9B ││9C │ ┌──┐┌──┐┌──┐
└──┘ └───┘└───┘└───┘└───────┘└───┘ └─────────┘└────┘└────┘ │9D││9E││9F│
└──┘└──┘└──┘
I'm not suggesting that we use the same display style for keymapviz as qmk info -m
(having dedicated outlines for each key takes too much screen space and doesn't leave enough space for actual key legends) but we can write a program that reads layout x,y information and generates a keymapviz-style string template.
info.json
and qmk info -f json
are both viable methods but the latter would require calling the QMK CLI in a subprocess
and check its output so my preference would go to simply reading the info.json
file instead since we don't need any of the extra information that qmk info -f json
provides.
~/qmk_firmware
❯ cat keyboards/binepad/bn003/info.json
{
"keyboard_name": "BN003",
"url": "https://binepad.com",
"maintainer": "binepad",
"layouts": {
"LAYOUT": {
"layout": [
{
"label": "K0",
"x": 0,
"y": 0
},
{
"label": "K1",
"x": 1,
"y": 0
},
{
"label": "K2",
"x": 2,
"y": 0
}
]
}
}
}
~/qmk_firmware
❯ qmk info --keyboard binepad/bn003 -f json | jq ".layouts"
{
"LAYOUT": {
"c_macro": true,
"filename": "keyboards/binepad/bn003/bn003.h",
"layout": [
{
"label": "K0",
"matrix": [
0,
0
],
"w": 1,
"x": 0,
"y": 0
},
{
"label": "K1",
"matrix": [
0,
1
],
"w": 1,
"x": 1,
"y": 0
},
{
"label": "K2",
"matrix": [
0,
2
],
"w": 1,
"x": 2,
"y": 0
}
]
}
}
One downside is that it is not possible (at least easily) to infer a good-looking KLE template from the layout diagram info but clearly the main usecase of keymapviz is to automatically generate ASCII visualisations in the keymap.c
file so the absence of KLE support is not a deal-breaker. We can document the few keyboards that have had KLE support manually added in and let other keyboards graciously "fail" in case the user tries to generate a KLE JSON for an unsupported keyboard and leave a notice saying that "Option -t json
is currently not supported for this keyboard.".