If you are here, maybe is because you want to make flow behave according to your key presses preferences or possibly you already have edited your own keybinds to suit your use cases and make everything easier, faster and more fluid when in flow.
First make sure you are aware of the existence of ctrl+f2 palette which exposes a list of commands available for you to use, and when you select a command, it’s pasted in your current cursor position.
Using the command palette Ctrl+Shift+p and typing Edit key bindings, takes you to a json file to extend flow, configuring keybindings to suit your needs. According to the mode you are in, your personal mode’s file configuration will be opened. Explore the the file to discover how commands are bound to some combos, key presses and the different imodes present.
Command palette can also be reached left clicking on the current mode in the status bar.
Once you open the corresponding json file, locate inside the imode(internal mode) that will accept the key or key/combos and add an array, where the first element is the combination to map to the commands that will be invoked, the array accepts strings like in
["ctrl+alt+shift+p", "open_command_palette"]
To avoid screwing up the combinations, and putting flow in an unusable state derived from a wrong mapping of key combinations, read on.
User configured keybindings are stored in Flow’s configuration directory under keys/mode.json where mode can be flow, emacs, vim, helix or customized ones. Removing the keys directory or the particular mode file can take you out from a broken state.
Keybinds are edited per mode, and other modes inherit what is defined in your flow.json keybindings. Each mode override keybindings of its parent mode. For example, if you are in emacs mode you will be redirected to emacs.json and it will override the keybindings from flow, and the default ones defined for emacs mode.
introducing keybindings showcases how to get to edit keybindings.
Some terminology
flow.json.project or descendant from project.project.In general a keybinding json shows this hierarchy:
flow.json <-- keybindings for flow mode {
<-- imode<-- react when press<-- the keys with commands<-- imode<-- Inherits all the keypresses and reactions from project<- custom actions for normal imode<-- normal imode also reacts when some keys are released<-- no more jumping when left control is released<-- imode with a cursor change<-- imode<-- keys are handled by a palette<-- minimodes also handle actions}project is the main imode in flow.json, mapping many combo key down presses.
Notice that normal imode inherits from project, meaning all the key presses handled by project react the same way in normal, which also extends with other keypresses. normal also captures key releases, we show a sample when the control key is released, stopping jumping mode inside flow.json.
SELECT imode inherits from normal and shows a different cursor to remind it is the current one.
home mode is shown when no buffer is open and if the user presses keys that are not explicitly handled to bring mental peace to the user.
overlay/palette gets active when a palette is active.
Looking further, it can be seen that minimodes have their own keybinding mappings defined in a particular imode, the same as palettes.
As stated previously, there is a mode hierarchy, the main mode is flow and other modes inherit from it. Each mode inherits, extends and overrides actions and define their internal imodes extending as required each minimode.
The most basic case to map a keybind to a command was covered in TLDR which used the combination of three keys pressed simultaneously ctrl, shift and p, all of them where combined with + to execute the command open_command_palette.
A common use case is to add a keybinding to invoke an already existing command and chain it to another, making Flow more suited to your own needs.
For example, f5 by default is used to run zig build test outputting its results to a scratch buffer called test.
The original definition is:
["f5", ["create_scratch_buffer", "*test*"], ["shell_execute_insert", "zig", "build", "test"]],
Note that:
The keybind is f5, which maps to the keycode generated by pressing the f5 key.
create_scratchbuffer is invoked receiving the parameter *test* which results in creating a scratch buffer if didn’t exist. And then executing the command shell_execute_insert that receives the parameters zig, build, test. This latter command is executing a shell command called zig with the parameters build and test; if you don’t have zig installed, it will not work, and you might want to remap f5 to a different shell command.
[
"f5",
[
"create_scratch_buffer",
"*test*"
],
[
"shell_execute_insert",
"zig",
"build",
"test"
]
]
Observe tasks running and maybe consider using more keybindings or running tasks for your projects.
If you realized that there is a handy combination that others can benefit from or that a mode lacks the combination and it might be included in flow, look at the contribution guidelines to submit your findings and solutions.
Probably binding commands is good, but maybe there is a feature in other text editors that you miss and would love to have at your fingertips. Then it’s Zig time: Adding commands to flow.