Hello!
This is my 3rd weekly update. Read previous updates: Week 1, Week 2.
I’ve spent the week implementing and unit-testing the keymapHandler
module. This module is responsible for abstracting the in-memory keymap. It can be queried and updated through provided methods. See my current progress in my PR #3252.
Data Structure
The default keymap will be stored as a list of JavaScript objects in the source code.
For example,
[
{ accelerator: 'CommandOrControl+N', command: 'newNoteItem', label: 'New note', section: 'File' },
{ accelerator: 'CommandOrControl+T', command: 'newTodoItem', label: 'New to-do', section: 'File' },
....
]
This would allow us the maximum customizability.
Some shortcuts have different default Accelerators depending on the platform, like the shortcut “Search in all notes”. They can be stored like this:
{ accelerator: shim.isMac() ? 'Shift+Command+F' : 'F6', command: 'focusSearch', label: 'Search in all the notes', section: 'Edit' }
This will give us the correct Accelerator in run-time.
Some shortcuts are available only on specific platforms. It’s perfectly okay to keep them in the default keymap. We can use a simple platforms
property to remember if they should be shown in the graphical shortcut editor or not, as a UX measure.
{ accelerator: 'CommandOrControl+,', command: 'options', label: 'Options', section: 'Tools', platforms: ['linux', 'windows'] },
{ accelerator: 'CommandOrControl+,', command: 'preferences', label: 'Preferences', section: 'File', platforms: ['darwin'] }
Above shortcut item will be shown in the graphical shortcut editor only on linux
and windows
platforms. If there’s no platform
property, it’s shown in all platforms. It’s as simple as that.
The label
and section
properties will be useful in the graphical shortcut editor.
Initialization
It benefits a lot if we have a way to retrieve shortcuts by command. Similar to the CLI client, the module first reads the default keymap list, and creates a keymap object in which the keys are command
s and values are shortcut objects.
This allows us to easily get and set shortcuts via simple methods.
Custom Keymap
Because keymap.json
is the keymap file for the CLI client, we can’t use that. I think keymap-desktop.json
would be a good choice for this. This is not final. Feel free to post what you think.
The module provides the method overrideKeymap()
which accepts the custom keymap JSON as parameter and updates the in-memory keymap accordingly. This has to be done before any getAccelerator()
calls in order to get the updated Accelerators. Any validation errors caused by missing commands, accelerators, invalid accelerators, incorrect commands will abort the method and log a helpful error message to the console.
Custom keymap items require command
and accelerator
properties. Following is an example for keymap-desktop.json
file:
[
{ "accelerator": "CommandOrControl+M", "command": "newNoteItem" },
{ "accelerator": "CommandOrControl+Y", "command": "newTodoItem" },
{ "accelerator": "CommandOrControl+L", "command": "goToAnything" }
]
What’s next?
- Check for conflicting Accelerators. If there’s the same Accelerator for two or more commands, it should warn the user. This can be tricky sometimes. What if user changes command X’s accelerator to Y’s default accelerator, and also change Y’s accelerator to X’s default accelerator?
- Best way to handle different context: Same shortcut can mean two different commands in two contexts.
- Since the changes are done in-memory, how to handle a “Save”? Maybe compare default keymap and current in-memory keymap and generate a JSON with the changes. This JSON can be
stringify
-ed and saved tokeymap-desktop.json
file. - Restore default Accelerator for some command.
Cheers!