Keymap Manager
Allows commands to be associated with keystrokes in a context-sensitive way. In Inkdrop, you can access a global instance of this object via inkdrop.keymaps
.
Key bindings are JavaScript objects containing CSS selectors as their top-level keys, with keystroke patterns mapped to commands.
Key Binding Syntax
When a keystroke sequence matches a binding in a given context, a custom DOM event with a type based on the command is dispatched on the target of the keyboard event.
To match a keystroke sequence, the keymap starts at the target element for the keyboard event. It looks for key bindings associated with selectors that match the target element. If multiple match, the most specific is selected. If there is a tie in specificity, the most recently added binding wins. If no bindings are found for the events target, the search is repeated again for the target's parent node and so on recursively until a binding is found or we traverse off the top of the document.
When a binding is found, its command event is always dispatched on the original target of the keyboard event, even if the matching element is higher up in the DOM.
In addition, .preventDefault()
is called on the keyboard event to prevent the browser from taking action.
.preventDefault
is only called if a matching binding is found.
Command event objects have a non-standard method called .abortKeyBinding()
.
If your command handler is invoked but you programmatically determine that no action can be taken and you want to allow other bindings to be matched, call .abortKeyBinding()
on the event object.
An example of where this is useful is binding snippet expansion to tab
.
If snippets:expand
is invoked when the cursor does not follow a valid snippet prefix, we abort the binding and allow tab
to be handled by the default handler, which inserts whitespace.
Multi-keystroke bindings are possible. If a sequence of one or more keystrokes partially matches a multi-keystroke binding, the keymap enters a pending state.
The pending state is terminated on the next keystroke, or after ::getPartialMatchTimeout
milliseconds has elapsed.
When the pending state is terminated via a timeout or a keystroke that leads to no matches, the longest ambiguous bindings that caused the pending state are temporarily disabled and the previous keystrokes are replayed.
If there is ambiguity again during the replay, the next longest bindings are disabled and the keystrokes are replayed again.
Key Binding Example
{
// global
body: {
'cmd-n': 'core:new-note',
'cmd-alt-n': 'window:new-inkdrop-window',
},
// editor
'.CodeMirror textarea': {
'ctrl-shift-up': 'editor:select-lines-upward',
'ctrl-shift-down': 'editor:select-lines-downward',
enter: 'editor:new-line',
tab: 'editor:indent'
}
}
Matched Binding Subscription
Invoke the given callback when keystrokes completely match a key binding.
Parameters
- Name
callback(event)
- Type
- function
- Required
- Description
Function to be called when keystrokes match a binding, where the
event
object contains the following properties:- Name
keystrokes
- Type
- string
- Description
String of keystrokes that matched the binding.
- Name
binding
- Type
- Keybinding
- Description
The matched keystrokes
- Name
keyboardEventTarget
- Type
- HTMLElement
- Description
The DOM element that was the target of the most recent keyboard event.
event object
Returns
Returns a Disposable on which .dispose()
can be called to unsubscribe.
Subscription Example
inkdrop.keymaps.onDidMatchBinding((event) => {
console.log('Matched binding:', event)
})
Partial Match Subscription
Invoke the given callback when keystrokes partially match a binding.
Parameters
- Name
callback(event)
- Type
- function
- Required
- Description
Function to be called when keystrokes partially match a binding, where the
event
object contains the following properties:- Name
keystrokes
- Type
- string
- Description
String of keystrokes that partially matched the binding.
- Name
partiallyMatchedBindings
- Type
- KeyBinding[]
- Description
KeyBinding
s that the keystrokes partially matched.
- Name
keyboardEventTarget
- Type
- HTMLElement
- Description
The DOM element that was the target of the most recent keyboard event.
event object
Returns
Returns a Disposable on which .dispose()
can be called to unsubscribe.
Subscription Example
inkdrop.keymaps.onDidPartiallyMatchBindings((event) => {
console.log('Partially matched binding:', event)
})
Failed Match Subscription
Invoke the given callback when keystrokes fail to match any bindings.
Parameters
- Name
callback(event)
- Type
- function
- Required
- Description
Function to be called when keystrokes fail to match any bindings, where the
event
object contains the following properties:- Name
keystrokes
- Type
- string
- Description
String of keystrokes that failed to match any binding.
- Name
keyboardEventTarget
- Type
- HTMLElement
- Description
The DOM element that was the target of the most recent keyboard event.
event object
Returns
Returns a Disposable on which .dispose()
can be called to unsubscribe.
Subscription Example
inkdrop.keymaps.onDidFailToMatchBinding((event) => {
console.log('Failed to match binding:', event)
})
Constructing Key Bindings
Construct KeyBinding
s from an object grouping them by CSS selector.
Parameters
- Name
source
- Type
- string
- Required
- Description
A string uniquely identifying the given bindings for later removal.
- Name
bindings
- Type
- object
- Required
- Description
Objects mapping keystroke patterns to commands, grouped by CSS selector.
- Name
priority
- Type
- number
- Description
Number used to sort keybindings with the same specificity, defaults to
0
.
Constructing Bindings Example
inkdrop.keymaps.build('my-plugin', {
'body': {
'ctrl-alt-n': 'my-plugin:do-something'
}
}, 0)
Adding Bindings
Add sets of key bindings grouped by CSS selector.
Parameters
- Name
source
- Type
- string
- Required
- Description
A string identifying the bindings for removal later.
- Name
bindings
- Type
- object
- Required
- Description
Mappings of keystroke patterns to commands.
- Name
priority
- Type
- number
- Description
Used to sort keybindings with the same specificity.
Adding Bindings Example
inkdrop.keymaps.add('my-plugin', {
'body': {
'ctrl-alt-n': 'my-plugin:do-something'
}
})
Accessing Bindings
Get all current key bindings.
Returns
An array of KeyBinding
s.
Finding Bindings
Get key bindings for a command and optional target.
Parameters
- Name
params
- Type
- object
- Required
- Description
Constraints for the binding search.
- Name
keystrokes
- Type
- string
- Description
A String representing one or more keystrokes, such as 'ctrl-x ctrl-s'.
- Name
command
- Type
- string
- Description
A String representing the name of a command, such as 'editor:delete-char-before'.
- Name
target
- Type
- HTMLElement
- Description
An optional DOM element constraining the search. If this parameter is supplied, the call will only return bindings that can be invoked by a KeyboardEvent originating from the target element.
params object
Finding Bindings Example
const bindings = inkdrop.keymaps.findKeyBindings({ command: 'editor:new-line' })
Returns
An array of KeyBinding
s.