Coder Social home page Coder Social logo

nickcoutsos / keymap-editor Goto Github PK

View Code? Open in Web Editor NEW
872.0 16.0 234.0 48.53 MB

A web based graphical editor of ZMK keymaps.

Home Page: http://nickcoutsos.github.io/keymap-editor

License: MIT License

JavaScript 93.48% HTML 0.77% CSS 5.73% Procfile 0.02%
editor zmk configurator keymap-editor gui

keymap-editor's Introduction

Keymap Editor Icon Keymap Editor

A browser app to edit ZMK keymaps. Although one of the goals for this project is to simplify the manual effort of keymap editing for the end user, is isn't a substitute for understanding ZMK. Be sure to read ZMK's documentation in order to fully leverage this app's functionality.

Try it now! Go to the Keymap Editor and try it out with the built-in keymap-editor-demo-crkbd before setting up your own repo.

Talk to me! ๐Ÿ—ฃ

I'd love to know how the Keymap Editor is working out for you! Has it helped you with managing your own keymaps, are you struggling with functionality, have you created your own keyboard and directed users here?

I want to know about all of that. I'm not taking any donations, the only thing driving this work forward is knowing what is or isn't helping people.

Shows a screenshot of the Keymap Editor application featuring a graphical layout of the Corne Keyboard with a keymap loaded from the nickcoutsos/keymap-editor-demo-crkbd GitHub repository.

Note

Source code updates are no longer shared here

I have been developing this application on and off since August 2020, but more recent source changes have not been published and this isn't likely to change any time soon. For more information see Wiki: Source Code Updates

If you do want to use the available source code as-is, you may wish to review the original README.

Features

  • WYSIWYG keymap editing
  • Multiple keymap sources:
    • GitHub repositories
    • Clipboard
    • File system*
  • Dark mode!
  • Conditional Layers
  • Combo editing
  • Macro editing (including support for creating/using parameterized macros)
  • Behavior editing (creation and re-configuration)
  • Auto-generated layouts for ZMK's supported keyboards**
  • Rotary encoders
  • Multiple keymaps

*File system web APIs are currently only supported in Chromium-based browsers

**Auto-generated layouts are meant as a starting-off point and are provided for most keyboards available in the ZMK repo and may need customization -- I own exactly one keyboard, I don't know all the layouts.

Read more: Wiki:Features

Usage

Local

This project runs as a web application, but there are still options for working with offline ZMK keymaps:

In the editor you can choose the Clipboard keymap source and paste in the contents of your ZMK .keymap file, and if you're using a Chromium-based web browser you can alternatively use the FileSystem source to read and make changes to select .keymap files directly.

Actual firmware builds are outside of the scope of this project, so if you're working on local keymap data it is assumed that you have a local ZMK development environment or some other means of running builds.

Web Integrations

This editor includes a GitHub integration. You can load the web app and grant it access to your public or private zmk-config repos. Changes to your keymap are committed right back to the repository so you only ever need to leave the app to download and flash firmware.

License

The code in this repo is available under the MIT license.

The collection of ZMK keycodes is taken from the ZMK documentation under the MIT license as well.

keymap-editor's People

Contributors

cpiro avatar dependabot[bot] avatar nickcoutsos avatar panzerstadt avatar refil avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

keymap-editor's Issues

Windows issues

Running node apps in Windows can be just different enough to frustrate development, and as I'm not testing this in a Windows environment I tend to learn about these things after fact.

  • Use cross-env to run scripts with environment variables
  • Get rid of cross-env?
    • It is in maintenance mode now and I kind of just resent the idea of depending on it for something so fundamental.
    • Can I get away with using dotenv or something so that I don't explicitly need to use environment variables? I can add .env.local to .gitignore and have a pre-start script to create the default if it doesn't exist yet
  • Check platform to conditionally spawn npm.cmd instead of npm (even if the npm command is used to start the server it seems to somehow not be available in the PATH used for subprocesses) when starting the webpack dev server in dev mode

Local install issue

Hello, this project looks awesome.

I am having an issue installing locally. I cloned the repo, npm install, then npm run dev and I get the error

`Z:\web dev\github\keymap-editor>npm run dev

[email protected] dev
ENABLE_DEV_SERVER=true node index.js

'ENABLE_DEV_SERVER' is not recognized as an internal or external command`

Any pointers? Thanks!

Support rotary encoders and other features

Need to look into how encoders should fit into a layout definition, but it looks like in ZMK they're bound separately from the regular keybinds for a layer. To make this work I would need to either make another array of array of binds (one for each layer) just for encoders or, more likely, change the schema from

"layers": [
  ["&kp Q", "&kp W", ...],
]

to

"layers": [{
  "keys": ["&kp Q", "&kp W", ...],
  "encoders": [...]
}]

This would be a backwards incompatible break from the convention of using QMK's keymap.json schema, but necessary. I think other features like combos may need to live there as well, unless they are independent of layers.

If the schema is changed it should also include a version and support for seamlessly updating old keymap files.

Delete a macro makes the app crash

I created a macro in my config, deleted it in the gui, and then tried to go bac to the main page of the editor.

I got this error:

TypeError

t is undefined

  keymap.js:7:19
  Keyboard/Binding/Binding.js:43:45
  ../node_modules/react-dom/cjs/react-dom.production.min.js:166:136
  ../node_modules/react-dom/cjs/react-dom.production.min.js:289:385
  ../node_modules/react-dom/cjs/react-dom.production.min.js:279:391
  ../node_modules/react-dom/cjs/react-dom.production.min.js:279:322
  ../node_modules/react-dom/cjs/react-dom.production.min.js:279:179
  ../node_modules/react-dom/cjs/react-dom.production.min.js:270:87
  ../node_modules/react-dom/cjs/react-dom.production.min.js:272:299
  ../node_modules/react-dom/cjs/react-dom.production.min.js:127:104
  ../node_modules/react-dom/cjs/react-dom.production.min.js:266:268

Change selected Repo in github app

Hi there, maybe I'm being dense but is there a way to change which repo the github app is using?
I can't see one and even when I clear all local storage it just re-authenticates to the same repo?

Do I need to de-authorize on the repo side?

Document zmk binding behaviour definitions

Some of the current zmk-behaviours.json is pretty straightforward and don't need much explanation. Other parts ("commands" and, more specifically, "additionalParams") are my own invention and while they get the job done for now, they could do with some refinement and justification.

Preserve selected parameter when switching behaviours

When switching from something like "key press" to "sticky key" or from "sticky layer" to "to layer" or "toggle layer" the key binding component should note that the new parameter list matches the old one and avoid clearing the selected layer value.

Report backend parsing/API errors to the UI

Right now there are a number of things that can go wrong before a user can even load their keymap for the first time:

  • Invalid GitHub repo selection
  • Layout/keymap files that are
    • missing,
    • not well-formed JSON, or
    • invalid bind syntax
  • probably more

The API should handle these a little more elegantly by reporting errors to the user if it's something they can fix.

Cache GitHub access tokens

Installation tokens can be persisted in memory for a while to avoid repeated network round-trips anytime an API call requires it.

Add new "Demo" keyboard source

There's actually a quite a bit of initial setup for a user to even see if they'd like using this app:

  1. Register for a GitHub account
  2. Fork the https://github.com/nickcoutsos/zmk-config-corne-demo repo
  3. Install the keymap-editor app
  4. Go through the authentication flow

The app could instead (with a flag enabled) offer a Demo source in addition to Local and GitHub so that the user can get a read-only keymap to play around with. The entire thing could be client-side.

Generate a hacky layout by parsing <keyboard>.dtsi

Using the devicetree parser and treating the default_transform.map node as row-based grid we can put together a rough ortholinear layout.

  1. Each line in the map is a new row.
  2. Find the column start/end location of each RC(...) instance
  3. Compare each column's approximate position to the columns in the previous row
  4. Cells with the greatest amount of text overlap are considered to be the same column

The result is a simple layout of 1u keys that means the end user doesn't need to have created an info.json file to get started. This process could spit one out, however, and give the user an opportunity to tweak it as required.

This will likely look like shit for row-staggered keyboards but I don't care.

Highlight keys with unselected parameter values

At the moment its possible to change a key's behaviour and neglect to re-assign the parameter values. Even if the app doesn't outright prevent you from submitting the keymap in this state (because it requires examining the behaviour binding to start with, which may be a custom definition) it should at least make the issue apparent to the end user.

Configuration changes

Config variables are in board_defconfig or shield.conf depending on if it's a board or a shield, this could be moved to the top of config folder to be used and manipulated by the editor. config variables to be changed could be defined in info.json to be edited with bool ones changed using switches and int ones changed with a simple number box

Export/Print as PDF

It would be very helpful to be able to export all layers simultaneously in one PDF.

Delete layer button doesn't seem to work

When i click delete layer, it pops up the confirm message "really delete?" then I click ok and nothing happens, irrelevant of if the layer is on the keymap.json or a newly added one

Feature Request: "Raw Mode"

It would be great to have a way to use the UI to dump arbitrary text into the keymap file

Maybe one way to implement it is to have a placeholder raw "behavior" that takes a raw string as its argument and inlines that into the keymap?

Whenever the parser doesn't know what a given behavior is, it can just use the placeholder behavior and allow the user to edit the text via the UI

(Related to #50 (reply in thread) )

Prompt user for commit message

Instead of just posting "Updated keymap" when making commits on the user's repo, the app could prompt them for a description of the changes and submit that in the commit instead.

Feature Request: Support for arbitrary key codes

My .keymap file has a custom binding defined (&mo_sl). However I am unable to input a layer number as the key code value. For example, it auto changes (layer) 1 to N1. It would be very convenient to have the ability to override suggested keycodes and input arbitrary values.
fdsas
dfs

Loving this software so far ๐Ÿ˜„ . Being able to visualize the layout has sped up configuration considerably.

Nodes with addresses are formatted incorrectly

https://docs.zephyrproject.org/2.5.0/guides/dts/intro.html#unit-address-examples

The formatter isn't expecting nodes with addresses and is somehow turning

foo@123 {
   bar;
};

into

foo {
  123

  bar;
};

Likely the address is just another named child of the node syntax node and because it's not one of the typical syntax node types I've looked at so far I'm "handling" it by spitting it out un-modified.

It's an unusual case because the editor is only applying formatting to the .keymap file and while there isn't a valid case, I think, to have to reference addresses in the devicetree source in the keymap file, there doesn't seem to be anything restricting its use here instead of the board or shield .dts/.overlay/.dtsi files.

Nonetheless, its happening and this issue actually generates invalid devicetree syntax so it needs to be fixed.

Automatically include required headers for behaviours used in the keymap

Bluetooth behaviours, for example, require

#include <dt-bindings/zmk/bt.h>

to be included in the keymap. The generated code can be made cleaner and more efficient if it only includes necessary headers. These are described in the zmk documentation, and can be added to the zmk-behaviours.json definition.

Note that the application currently sends the keymap as an array of binds (e.g. &kp LS(F)) and not the parsed object structure (e.g. {"bind": "&kp", "params": [{"code": "LS", "params": [{"code": "F"}]]}). To avoid duplicating effort, the API should formally use the parsed keymap in its communication and handling those transformations server-side.

Keymap fails to load, error handler also doesn't load

The keymap editor now fails to load for my heavily customized keymap -- the spinner never stops spinning. The editor was able to load the same keymap a few days ago.

Default keymaps load fine. The customized keymap has a fair number of custom behaviors, including mouse behaviors from the ZMK mouse button fork.

GEThttps://zmk-keymap-editor.fly.dev/github/keyboard-files/29762192/xaelectronics/zmk_swept_kb_config?branch=miryoku&useDevicetree=true
[HTTP/2 500 Internal Server Error 1031ms]
Uncaught (in promise) Error: Request failed with status code 500
    exports createError.js:16
    exports settle.js:17
    w xhr.js:66
    exports xhr.js:78
    exports xhr.js:15
    exports dispatchRequest.js:58
    request Axios.js:108
    exports bind.js:9
    e api.js:33
    c runtime.js:63
    _invoke runtime.js:294
    k runtime.js:119
    Babel 4
    value api.js:8
    e api.js:211
    c runtime.js:63
    _invoke runtime.js:294
    k runtime.js:119
    Babel 4
    value api.js:8
    e Picker.js:97
    c runtime.js:63
    _invoke runtime.js:294
    k runtime.js:119
    Babel 4
    ef Picker.js:205
    React 3
    w scheduler.production.min.js:13
    M scheduler.production.min.js:14
    6813 scheduler.production.min.js:14
    Webpack 12
[createError.js:16:14](https://nickcoutsos.github.io/keymap-editor/static/node_modules/axios/lib/core/createError.js)
    Babel 6
    ef Picker.js:205
    React 3
    w scheduler.production.min.js:13
    M scheduler.production.min.js:14
    (Async: EventHandlerNonNull)
    6813 scheduler.production.min.js:14
    Webpack 12

Switching repository selection doesn't clear the branch selection

  1. Select repositoryA
  2. Select branch repositoryA/branchB
  3. Select repositoryB (which doesn't have a branch branchB)
  4. API will attempt to load keyboard files for repositoryB/branchB, fail, and treat it as a layout generation error.

The immediate problem to solve is to clear the branch selection when switching repositories.

Additionally, there may need to be better handling in place for GitHub API error responses, but there are more API changes coming and it may not be worth digging into that too much just yet.

Can't nest modifiers for keypress in the UI.

For example attempting to create a &kp with both LGUI and Left Shift Modifiers, after adding the modifiers, there is no option to add the keypress. (e.g. no way to say LGUI ( Shift ( A ) ).

This is read properly from existing keymap but can't create a new one in the interface.

Missing support for modifier function keypresses such as `LC(Z)`?

I may be missing something, but there appears to be no way to enter a keypress code such as LC(Z) into the UI. Funnily enough, if I enter a modifier function in my keymap file manually and then tell the UI to refresh from GitHub then I am able to edit the keypress.

Am I missing something? This scenario isn't mentioned in the docs and I wasn't able to get it to work by exploring the UI.

Please add Label Name and Sensor Bindings in .keymap

We need label = "LayerName"; for oled display and sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>; for Rotary Encode
Also need add dynamic for sensor-bindings
Just replace line 100 to 107 in /api/services/zmk/keymap.js

return `
        ${name.replace(/[^a-zA-Z0-9_]/g, '_')} {
	    label = "${name.replace('layer', '')}";
            bindings = <
${rendered}
            >;
	    sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN>;
        };
`
  })

Document the key binding schema

Probably the most important part of this project is to promote structures and interfaces for working with zmk keyboard layouts and keymaps. Documentation should be provided to explain the breakdown of a simple (or complex) key binding into the nested structure used in the web app to facilitate graphical editing.

Allow for empty/missing keymap.json files

Technically as long as the layout is defined in info.json a default keymap could be created (at the simplest, a single layer with &trans for every keybind) and this would reduce the barrier to entry somewhat.

Support for mod-morph

Is is currently possible to create mod-morph behaviours in the web-app ?

My use-case would be to change SHIFT+COMMA to output SEMICOLON

Is there a way to do it ?
If not, will that be supported in the future ?

Feature Request: Support for user-defined behaviors.json

I've got a board that has some custom behaviors defined in firmware, that haven't yet made it into the upstream zmk firmware.

It would be really cool if the app could somehow pick up a user-behaviors.json file if it's in the keymap repo, and merge it with the zmk-behaviors.json that it uses to determine behaviors.

I imagine this might also allow users to custom-define things like HYPER/MEH and provide it in the includes block (related to this: #50 (reply in thread))

Support dynamic keymap selection

Assuming that in a given repository or ZMK_CONFIG workspace any editable .keymap file will found under config/ regardless of board/shield stuff, we should be able to dynamically fetch this information and present it as another selection just like the GitHub picker does with branches.

Doing this once means the keymap name becomes an identifier of sorts so we don't have to do that same "search" when committing changes to the repo.

Using the matrix in build.yaml might be useful but this is unclear to me still.

Refactor Search component

Search used to be a simple auto-complete field for keycodes, but now it can also serve as a picker for

  • zmk binding behaviours
  • modifiers (a refined subset of keycodes)
  • layers (which can be named)

Ideally it should:

  • not force the autocomplete list to use the same shape as keycode definitions (i.e. {"code": ...}).
  • include a more helpful prompt for what to do when it appears, and maybe autofocus the input field.
  • probably look into using Vue's teleport component to render itself at a higher level in the DOM.

keymap editor crash

Crash has occurred twice, both times when I click on a key to edit it.

TypeError

g is undefined

  EnhancedPickers/Keycode/KeycodePicker.js:60:7
  ../node_modules/react-dom/cjs/react-dom.production.min.js:166:136
  ../node_modules/react-dom/cjs/react-dom.production.min.js:289:385
  ../node_modules/react-dom/cjs/react-dom.production.min.js:279:391
  ../node_modules/react-dom/cjs/react-dom.production.min.js:279:322
  ../node_modules/react-dom/cjs/react-dom.production.min.js:279:179
  ../node_modules/react-dom/cjs/react-dom.production.min.js:270:87
  ../node_modules/react-dom/cjs/react-dom.production.min.js:272:299
  ../node_modules/react-dom/cjs/react-dom.production.min.js:127:104
  ../node_modules/react-dom/cjs/react-dom.production.min.js:266:268

Key toggle `&kt` not supported by UI?

Discussed in #59

Originally posted by Richiban October 9, 2022
It seems that key toggle isn't supported by the tool? It doesn't appear in the behaviour drop-down and if &kt appears in the keymap file the UI displays an error.

Issue loading locally from directory

First off, I absolutely love this project and I'm planning on doing everything I can to help contribute to it!

I'm working on getting everything running locally but for some reason when I clone my zmk-config repo into the root of the project directory, it seems that the app can't load my existing keymap.

When I select 'Local' in the top right, it shows the proper layout for my keyboard, but none of the keycodes are filled in.

Perhaps the strangest part is that when I run this from here everything loads fine.

I'm guessing it's a simple config option I'm overlooking, so feel free to just link me to a doc that I may have missed to get me on my way.

Thanks!

Experimental devicetree parsing: missing required behaviour includes

The original implementation which overwrites <keyboard>.keymap with the generated keymap code used to add all of the required includes based on the behaviours used. The experimental implementation that edits the devicetree inline needs to look at the existing includes and ensure that missing behaviour includes are added.

Cannot read properties of undefined (reading 'bindings')

TypeError

Cannot read properties of undefined (reading 'bindings')

  Keyboard/Keyboard.js:81:45
  ../node_modules/react-dom/cjs/react-dom.production.min.js:166:136
  ../node_modules/react-dom/cjs/react-dom.production.min.js:215:269
  ../node_modules/react-dom/cjs/react-dom.production.min.js:291:201
  ../node_modules/react-dom/cjs/react-dom.production.min.js:279:388
  ../node_modules/react-dom/cjs/react-dom.production.min.js:279:319
  ../node_modules/react-dom/cjs/react-dom.production.min.js:279:179
  ../node_modules/react-dom/cjs/react-dom.production.min.js:270:87
  ../node_modules/react-dom/cjs/react-dom.production.min.js:267:428
  ../node_modules/scheduler/cjs/scheduler.production.min.js:13:202

Encoders appear to have been defined backwards

It appears that the UI gets clockwise and anti-clockwise the wrong way round. See screenshot for how I've had to define my encoders incorrectly int order to get the keycodes to show up correctly in the keymap file:

Screenshot 2022-10-10 at 14 39 11

The above produces the following keymap:

Screenshot 2022-10-10 at 14 40 37

Look into key positioning code

Applying rotations to keys can be hard to get right, especially when trying to make a symmetric layout.

Two things that make this troublesome:

  1. the default origin for a key is its top-left corner; not a problem for the most part but once you get into rotations things will start to feel unpredictable
    • to make things harder, the transformations around custom key sizes sort of depends on that origin
  2. the calculations are done based on a known "1u" size for a key, but they also have to contend with the margin I've thrown into the mix. I think technically the "1u" spacing should be the distance from one switch to the next and whatever margin there is after that is a product of keycap dimensions

Some changes are needed, but they could break existing layouts. The good news is that 1u-based layouts with no rotated keys should be unaffected, because regardless of individual key placement the entire layout is positioned according to its bounding box. Still, maybe there should be a way to detect this and gracefully fallback to the old functionality.

Bindings parser can't handle macro functions with spaces in the params list

The bindings parser finds keycodes that look like "functions" and parses them into a list of parameters.

E.g. LS(F) becomes

{
  "value": "LS",
  "params": [{
    "value": "F",
    "params" []
  }]
}

But the pattern matcher isn't handling spaces correctly, so something like LS( LA(F)) becomes

{
  "value": "LS(",
  "params": []
},
{
  "value": "LA",
  "params": [{
    "value": "F)",
    "params": []
  }]
}

Keymap-editor stuck on Waiting for API..

Heya, tried opening up the web keymap-editor, but it just says "Waiting for API..". Tried several browsers and even on my phone, but the issues persists.

Alternatively I tried to set up the editor locally by following the readme. Managed to start the npm app by adding PORT=8081 node index.js at the end of my .env filebut eventually ended up in the same situation where it just says "Waiting for API.." and nothing happens.

Restrict accepted characters for devicetree identifiers

There is some code in the backend that will strip out certain characters in things like layer names, but this should really happen on the frontend for transparency.

  1. Review the devicetree spec
  2. Update EditableField to accept a validator prop, and display errors(?)
  3. Ensure sanitization is being applied consistently in the API
  4. Define validation schema for the next API version

Preserve whitespace for inline comments

When encountering lines in the devicetree such as

foo;         // bar

this gets parsed into two nodes: property, and comment. Then two steps are followed:

  1. the preceding whitespace is removed (ignored, rather, because the comment node only starts at the //)
  2. the contents of the comment node are added to the contents of its preceding sibling node

which means the output is

foo;// bar

In order to add the comment text to the same line it is already checking that both nodes are on the same line, so this same property can be used to see how much whitespace exists between the two nodes and copy it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.