{"id":27629455,"url":"https://github.com/mnesarco/zkeymap","last_synced_at":"2025-07-07T02:06:03.682Z","repository":{"id":282976809,"uuid":"948846339","full_name":"mnesarco/zkeymap","owner":"mnesarco","description":"DSL for ZMK Keymaps, compiles to devicetree","archived":false,"fork":false,"pushed_at":"2025-06-23T19:25:17.000Z","size":322,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-23T20:28:14.673Z","etag":null,"topics":["generator","keymap-drawer","layout","python","svg","zmk"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mnesarco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-03-15T04:51:00.000Z","updated_at":"2025-06-23T19:25:21.000Z","dependencies_parsed_at":"2025-03-18T00:30:20.603Z","dependency_job_id":"f5c06f39-142d-42e5-91b9-44d87eec6ff0","html_url":"https://github.com/mnesarco/zkeymap","commit_stats":null,"previous_names":["mnesarco/zkeymap"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mnesarco/zkeymap","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnesarco%2Fzkeymap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnesarco%2Fzkeymap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnesarco%2Fzkeymap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnesarco%2Fzkeymap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mnesarco","download_url":"https://codeload.github.com/mnesarco/zkeymap/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnesarco%2Fzkeymap/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264000628,"owners_count":23542112,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["generator","keymap-drawer","layout","python","svg","zmk"],"created_at":"2025-04-23T15:17:22.419Z","updated_at":"2025-07-07T02:06:03.660Z","avatar_url":"https://github.com/mnesarco.png","language":"Python","readme":"# ZKeymap (WIP)\n\nPython DSL for ZMK Keymaps definitions and files generation.\n\nThis tool can generate keymaps, transoforms and layouts in json and svg formats.\n\n![](https://github.com/mnesarco/zkeymap/raw/main/docs/diagram1.png)\n\n## Motivation\n\nWhile I still prefer text-based layout definitions over graphical editors, devicetree syntax seems overly complicated. As a result, I created this small language to enable easy and pleasant keymap definitions for ZMK, eliminating the need for graphical editors.\n\n## Big Note\n\nYou can use unicode chars directly as aliases, it looks good and works well but it is totally optional.\nAll aliases are user defined or can be overridden by the user.\n\n## Usage\n\n### 1. Install zkeymap\n\n```bash\npip install zkeymap\n```\n\n### 2. Add a python file to your config directory, for example `mykeymap.py`\n\n### 3. Write your keymap in zkeymap language, here is an example `splitkb.py`:\n\n[src/zkeymap/demo/splitkb.py](src/zkeymap/demo/splitkb.py)\n\n### 4. Generate your devicetree files:\n\n```bash\npython3 mykeymap.py\n```\n\nThat will generate four files as per the example:\n\n| File | Content| Format |\n|------|--------|--------|\nsplitkb_keymap.dtsi| Keymap, macros, dances, encoders| devicetree |\nsplitkb_transform.dtsi| zmk,matrix-transform | devicetree |\nsplitkb_layout.dtsi| zmk,physical-layout | devicetree |\nsplitkb_info.json | physical layout | QMK info.json |\nsplitkb_layout.svg | Graphical layout (built-in generator) | svg |\nsplitkb_drawer.svg | Graphical layout (keymap-drawer generator) | svg |\nsplitkb_switches_layout.svg | Graphical layout for switches holes | svg |\n\n### 5. Then in your zmk keymap file remove the keymap node and include the generated file example:\n\n```c\n#include \u003cbehaviors.dtsi\u003e\n#include \u003cdt-bindings/zmk/keys.h\u003e\n#include \u003cdt-bindings/zmk/bt.h\u003e\n#include \u003cdt-bindings/zmk/ext_power.h\u003e\n#include \u003cdt-bindings/zmk/outputs.h\u003e\n#include \u003cdt-bindings/zmk/matrix_transform.h\u003e\n\n// +------------------------------------+\n// | Include the generated keymap here: |\n// +------------------------------------+\n#include \"splitkb_keymap.dtsi\"\n#include \"splitkb_transform.dtsi\"\n#include \"splitkb_layout.dtsi\"\n\n/ {\n\n    chosen {\n        zmk,kscan = \u0026kscan0;\n        zmk,matrix-transform = \u0026marz_split_3x6_4_transform;\n        zmk,physical-layout = \u0026marz_split_3x6_4;\n    };\n\n    kscan0: kscan {\n        compatible = \"zmk,kscan-gpio-matrix\";\n        label = \"KSCAN\";\n\n        diode-direction = \"col2row\";\n        wakeup-source;\n\n        row-gpios\n            = \u003c\u0026pro_micro 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)\u003e\n            , \u003c\u0026pro_micro 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)\u003e\n            , \u003c\u0026pro_micro 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)\u003e\n            , \u003c\u0026pro_micro 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)\u003e\n            ;\n\n    };\n\n\n};\n```\n\n### Commit and push your changes as usual to built the firmware.\n\n## Basic language rules\n\nEverything is based around aliases, you define an alias mapping any char\n(even unicode chars) to ZML Keys or macros or whatever.\n\nDepending on how you decorate the alias, it will be translated into a specific\nbehavior (\u0026lt, \u0026mo, \u0026to, \u0026kp, etc...)\n\n### Aliases definitions\n\nTo define an alias just express it like this:\n\n```python\nalias / \"alias\" / \"translation\"\n```\n\nExample: define symbol `⌘` as an alias of `LGUI`:\n\n```python\nalias / \"⌘\" / \"LGUI\"\n```\n\nThen you can use `⌘` in the keymap as `[ ⌘ ]` it will be translated to `\u0026kp LGUI`\n\n### Key press (\u0026kp, \u0026sk)\n\nSquare brackets syntax `[ alias ]`.\n\nExample:\nWhere `a` is an alias and `X` is the alias resolution\n\n| syntax      | compiles to   | Notes                  |\n|-------------|---------------|------------------------|\n| [ a ]       | \u0026kp X         | Simple case            |\n| [ shift a ] | \u0026kp LS(X)     | With shift mods        |\n| [ ⎈ a ]     | \u0026kp LC(X)     | With Ctrl mods         |\n| [ r⇧ ⎈ a ]  | \u0026kp RS(LC(X)) | With RShift+LCtrl mods |\n\nFor a sticky key variation, just add `~` at the end and\n`\u0026kp` will be changed to `\u0026sk`\n\n| syntax      | compiles to   | Notes                  |\n|-------------|---------------|------------------------|\n| [ lshift ~] | \u0026sk LSHIFT    | One shot/sticky Shift  |\n\n\n### Mod-Tap behavior (\u0026mt)\n\nCurly brackets syntax `{ mod alias }`.\n\nExample:\nWhere `a` is an alias and `X` is the alias resolution.\n\n| syntax      | compiles to   | Notes                  |\n|-------------|---------------|------------------------|\n| { shift a } | \u0026mt LSHIFT X  | hold=lshift, tap=X     |\n| { ⎈ a }     | \u0026mt LCTRL X   | hold=lctrl, tap=X      |\n| { r⇧ a }    | \u0026mt RSHIFT X  | hold=rshift, tap=X     |\n\n\n### Layer based behaviors (\u0026lt, \u0026mo, \u0026sl, \u0026to, \u0026tog)\n\nParenthesis syntax `( layer alias )`.\n\nExample:\nWhere `LAY` is a layer, `a` is an alias and `X` is the alias resolution.\n\n| syntax      | compiles to   | Notes                  |\n|-------------|---------------|------------------------|\n| ( LAY )     | \u0026mo LAY       | momentary layer        |\n| ( LAY a )   | \u0026lt LAY X     | layer tap LAY and X    |\n| ( LAY / ~ )   | \u0026lt LAY TILDE | layer tap LAY and ~    |\n| ( LAY ~)    | \u0026sl LAY       | sticky layer LAY. See the difference with previous  |\n| ( LAY !)    | \u0026to LAY       | absolute layer LAY        |\n| ( LAY /)    | \u0026tog LAY      | toggle layer LAY          |\n\n### Raw ZMK stuff\n\nTriangle brackets syntax `\u003c whatever \u003e`.\n\nContent inside `\u003c` and `\u003e` is resolved to raw ZMK code.\n\nExample:\n\n| syntax       | compiles to   | Notes                  |\n|--------------|---------------|------------------------|\n| \u003cA\u003e          | A             | raw zmk code           |\n| \u003c\u0026lt 1 A\u003e    | \u0026lt 1 A       | raw zmk code            |\n| \u003c\u0026caps_word\u003e | \u0026caps_word    | raw zmk code            |\n| \u003c\u0026kp LCTRL\u003e  | \u0026kp LCTRL     | raw zmk code            |\n\n\n### Macros\n\nDefinitions of macros is done using aliases:\n\n```python\nalias / \"hello\" / macro(\"[shift h] e l l o\")\n```\n\nThen it can be used in a layer:\n\n```python\nlayer / \"def\" / r\"\"\" hello \"\"\"\n```\n\n### Unicode\n\nA special case for Unicode macros allows to define lower and upper variations:\n\n```python\n\nalias / \"∴\" / uc(name=\"t3p\", char=\"∴\", shifted=\"△\")\n\nlayer / \"def\" / r\"\"\" [ ∴ ] \"\"\"\n\n```\n\nIn this case `[ ∴ ]` will be translated to `∴` on tap and to `△` on Shift tap.\n\n## Status\n\nThis project is quite new and experimental, testers and contributors are welcome.\n\nKey areas of contribution:\n\n1. Documentation\n2. Aliases for different languages/layouts.\n3. Unit tests\n4. Reporting bugs\n\n\n## Common Unicode chars for keyboards\n\n|  LEFT  | RIGHT   | UNICODE   | DESCRIPTION       |\n| -------|---------|-----------|-------------------|\n|  ⌘     |  r⌘     |  u2318    |  GUI/Command |\n|  ⎈     |  r⎈     |  u2388    |  Ctrl |\n|  ⇧     |  r⇧     |  u21E7    |  Shift |\n|  ⎇     |  r⎇     |  u2387    |  Alt |\n|  ⏎     |         |  u23CE    |  Enter |\n|  ␣     |         |  u2423    |  Space |\n|  ⌫     |         |  u232b    |  Backspace |\n|  ←     |         |  u2190    |  Arrow Left |\n|  ↑     |         |  u2191    |  Arrow Up |\n|  →     |         |  u2192    |  Arrow Right |\n|  ↓     |         |  u2193    |  Arrow Down |\n|  ᛒ     |         |  u16D2    |  Bluetooth |\n|  ⇪     |         |  u21EA    |  CapsLock |\n|  🄰     |         | u1F130    | CapsLock |\n|  ⎙     |         |  u2399    |  PrintScreen |\n|  ⇄     |         |  u21C4    |  Tab |\n|  ↖     |         |  u2196    |  Home |\n|  ↘     |         |  u2198    |  End |\n|  ⇞     |         |  u21DE    |  PgUp |\n|  ⇟     |         |  u21DF    |  PgDn |\n|  ↶     |         |  u21B6    |  Undo |\n|  ↷     |         |  u21B7    |  Redo |\n|  ✂     |         |  u2702    |  Cut |\n|  ⿻     |         | u2FFb     | Copy |\n|  ⧉     |         |  u29c9    |  Paste |\n|  ⚙     |         |  u2699    |  Bootloader |\n\n## Working examples\n\n- https://github.com/mnesarco/zmk-config\n\n## AI Usage\n\nCodeium AI was used to generate docstrings and basic unit tests.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmnesarco%2Fzkeymap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmnesarco%2Fzkeymap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmnesarco%2Fzkeymap/lists"}