Skip to content

Master Keybindings

This defines version 2.0 of the master keybinding file format. Breaking changes from version 1.0 are described below

Master keybindings are TOML files that begin with a line containing #:master-keybindings and include the following top-level fields:

  • header: top-level properties of the binding file
  • mode: array describing behavior of keybinding modes
  • define: object of arbitrary fields which can be used in computed arguments.
  • bind: an actual keybinding; extends the schema used by VSCode's keybindings.json

In addition, any comments prefixed with ## will show up in the documentation displayed by Master Key: Show Text Documentation. Any key bindings that fall between paragraphs of the literate documentation are combined and presented as a table of keybindings.

Example

Here's a minimal example, demonstrating the most basic use of each field

toml
#:master-keybindings

## # My Key Bindings
##
## The binding file is a literate document. This text will show up in
## `Master Key: Show Text Documentation`

[header]
# this denotes the file-format version, it must be semver compatible with 2.0
version = "2.0.0"
name = "My Bindings"

[[mode]]
name = "insert"
# this comment will not show up in the documentation because it is prefixed
# with `#` instead of `##`.
whenNoBinding = 'insertCharacters'

[[mode]]
name = "normal"
default = true

[[kind]]
name = "motion"
description = "Commands that move your cursor"

[[kind]]
name = "mode"
description = "Commands that change the keybinding mode"

[[bind]]
key = "i"
doc.name = "insert"
mode = "normal"
command = "master-key.enterInsert"
doc.kind = "mode"

[[bind]]
key = "escape"
doc.name = "normal"
mode = "insert"
command = "master-key.enterNormal"
doc.kind = "mode"

[[define.bind]]
id = "basic_motion"
mode = "normal"
doc.kind = "motion"
command = "cursorMove"

[[bind]]
default = '{{bind.basic_motion}}'
doc.name = "right"
key = "l"
args.to = "right"

[[bind]]
doc.name = "left"
default = '{{bind.basic_motion}}'
key = "h"
args.to = "left"

[[define.val]]
foo = 1

[[bind]]
doc.name = "double right"
key = "g l"
default = '{{bind.basic_motion}}'
args.to = "right"
args.value = "{{foo+1}}"

Breaking Changes

The following changes were made from version 1.0 of the file format.

  • header.version is now 2.0
  • [[define]] now has several sub fields. Definitions previously under [[define]] should usually go under [[define.val]], but also see [[define.command]].
  • Comments prefixed with ## show up in literate documentation and all other comments are ignored. (Previously # showed up as literate documentation and #- was ignored).
  • generalized expressions. This changed or replaced several other features:
    • bind.computedArgs no longer exists: instead, place expressions inside of args
    • bind.foreach has changed
      • {key: [regex]} is now {{keys(`[regex]`)}}
      • foreach variables are interpolated as expressions ({{symbol}} instead of {symbol}).
    • bind.path and [[path]]: A similar, but more explicit approach is possible using default and define.bind
    • replaced mode = [] with mode = '{{all_modes()}}'
    • replaced mode = ["!normal", "!visual"] with mode = '{{not_modes(["normal", "visual"])}}'
  • revised several fields:
    • replaced prefixes = ["a", "b", ...] with prefixes.anyOf = ["a", "b", ...]
    • replaced prefixes = "<all-prefixes>" with prefixes.any = true
    • name, description, hideInPalette and hideInDocs moved to doc.name, doc.description, doc.hideInPalette and doc.hideInDocs
    • combinedName, combinedDescription and combinedKey moved to doc.combined.name, doc.combined.description and doc.combined.key.
    • resetTransient is now finalKey
    • bind.if replaced with bind.skipWhen
    • removed (re)storeNamed commands
    • replay-related command fields have changed their semantics, see examples under replayFromHistory