in packages/editor-core/src/hotkey.ts [487:542]
private handleKey(character: string, modifiers: string[], e: KeyboardEvent): void {
const callbacks: IPublicTypeHotkeyCallbackConfig[] = this.getMatches(character, modifiers, e);
let i: number;
const doNotReset: SequenceLevels = {};
let maxLevel = 0;
let processedSequenceCallback = false;
// Calculate the maxLevel for sequences so we can only execute the longest callback sequence
for (i = 0; i < callbacks.length; ++i) {
if (callbacks[i].seq) {
maxLevel = Math.max(maxLevel, callbacks[i].level || 0);
}
}
// loop through matching callbacks for this key event
for (i = 0; i < callbacks.length; ++i) {
// fire for all sequence callbacks
// this is because if for example you have multiple sequences
// bound such as "g i" and "g t" they both need to fire the
// callback for matching g cause otherwise you can only ever
// match the first one
if (callbacks[i].seq) {
// only fire callbacks for the maxLevel to prevent
// subsequences from also firing
//
// for example 'a option b' should not cause 'option b' to fire
// even though 'option b' is part of the other sequence
//
// any sequences that do not match here will be discarded
// below by the resetSequences call
if (callbacks[i].level !== maxLevel) {
continue;
}
processedSequenceCallback = true;
// keep a list of which sequences were matches for later
doNotReset[callbacks[i].seq || ''] = 1;
fireCallback(callbacks[i].callback, e, callbacks[i].combo, callbacks[i].seq);
continue;
}
// if there were no sequence matches but we are still here
// that means this is a regular match so we should fire that
if (!processedSequenceCallback) {
fireCallback(callbacks[i].callback, e, callbacks[i].combo);
}
}
const ignoreThisKeypress = e.type === 'keypress' && this.ignoreNextKeypress;
if (e.type === this.nextExpectedAction && !isModifier(character) && !ignoreThisKeypress) {
this.resetSequences(doNotReset);
}
this.ignoreNextKeypress = processedSequenceCallback && e.type === 'keydown';
}