diff --git a/spec/keymap-manager-spec.coffee b/spec/keymap-manager-spec.coffee index 04b48a8..78abe9e 100644 --- a/spec/keymap-manager-spec.coffee +++ b/spec/keymap-manager-spec.coffee @@ -1009,24 +1009,35 @@ describe "KeymapManager", -> assert.equal(keymapManager.findKeyBindings(command: 'Y').length, 0) describe "events", -> + [elementA] = [] + + beforeEach -> + elementA = appendContent $$ -> + @div class: 'a' + it "emits `matched` when a key binding matches an event", -> + elementA.addEventListener 'aborted-command', (e) -> e.abortKeyBinding() + handler = stub() keymapManager.onDidMatchBinding handler keymapManager.add "test", "body": "ctrl-x": "used-command" - "*": + ".a": + "ctrl-x": "aborted-command" + "html": "ctrl-x": "unused-command" ".not-in-the-dom": - "ctrl-x": "unmached-command" + "ctrl-x": "unmatched-command" - keymapManager.handleKeyboardEvent(buildKeydownEvent(key: 'x', ctrlKey: true, target: document.body)) + keymapManager.handleKeyboardEvent(buildKeydownEvent(key: 'x', ctrlKey: true, target: elementA)) assert.equal(handler.callCount, 1) - {keystrokes, binding, keyboardEventTarget} = handler.firstCall.args[0] + {keystrokes, binding, keyboardEventTarget, abortedBindings} = handler.firstCall.args[0] assert.equal(keystrokes, 'ctrl-x') assert.equal(binding.command, 'used-command') - assert.equal(keyboardEventTarget, document.body) + assert.equal(keyboardEventTarget, elementA) + assert.equal(abortedBindings[0].command, 'aborted-command') it "emits `matched-partially` when a key binding partially matches an event", -> handler = stub() diff --git a/src/keymap-manager.coffee b/src/keymap-manager.coffee index 209ec61..7dadad6 100644 --- a/src/keymap-manager.coffee +++ b/src/keymap-manager.coffee @@ -144,6 +144,8 @@ class KeymapManager # * `binding` {KeyBinding} that the keystrokes matched. # * `keyboardEventTarget` DOM element that was the target of the most # recent keyboard event. + # * `abortedBindings` {KeyBinding} objects that were matched but the command aborted itself + # prior to `binding` being executed. # # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe. onDidMatchBinding: (callback) -> @@ -547,6 +549,8 @@ class KeymapManager if isKeyup(keystroke) exactMatchCandidates = exactMatchCandidates.concat(@pendingKeyupMatcher.getMatches(keystroke)) + abortedBindings = [] + # Determine if the current keystrokes match any bindings *exactly*. If we # do find an exact match, the next step depends on whether we have any # partial matches. If we have no partial matches, we dispatch the command @@ -595,6 +599,9 @@ class KeymapManager for pendingKeyupMatch in pendingKeyupMatchCandidates @pendingKeyupMatcher.addPendingMatch(pendingKeyupMatch) break + else + abortedBindings.push(exactMatchCandidate) + currentTarget = currentTarget.parentElement # Emit events. These are done on their own for clarity. @@ -604,7 +611,8 @@ class KeymapManager keystrokes, eventType: event.type, binding: dispatchedExactMatch, - keyboardEventTarget: target + keyboardEventTarget: target, + abortedBindings } else if hasPartialMatches and shouldUsePartialMatches event.preventDefault()