diff --git a/spec/app/keymap-spec.coffee b/spec/app/keymap-spec.coffee index 5cdb9978c..b341debd4 100644 --- a/spec/app/keymap-spec.coffee +++ b/spec/app/keymap-spec.coffee @@ -190,18 +190,6 @@ describe "Keymap", -> expect(fooHandler).toHaveBeenCalled() - describe ".bindKey(selector, pattern, eventName)", -> - it "binds a single key", -> - keymap.bindKey '.child-node', 'z', 'foo' - - fooHandler = jasmine.createSpy('fooHandler') - fragment.on 'foo', fooHandler - - target = fragment.find('.child-node')[0] - keymap.handleKeyEvent(keydownEvent('z', target: target)) - - expect(fooHandler).toHaveBeenCalled() - describe ".keystrokeStringForEvent(event)", -> describe "when no modifiers are pressed", -> it "returns a string that identifies the key pressed", -> @@ -224,3 +212,24 @@ describe "Keymap", -> expect(keymap.keystrokeStringForEvent(keydownEvent('{', shiftKey: true))).toBe '{' expect(keymap.keystrokeStringForEvent(keydownEvent('left', shiftKey: true))).toBe 'shift-left' expect(keymap.keystrokeStringForEvent(keydownEvent('Left', shiftKey: true))).toBe 'shift-left' + + + describe ".bindingsForElement(element)", -> + it "returns the matching bindings for the element", -> + keymap.bindKeys '.command-mode', 'c': 'c' + keymap.bindKeys '.grandchild-node', 'g': 'g' + + bindings = keymap.bindingsForElement(fragment.find('.grandchild-node')) + expect(Object.keys(bindings).length).toBe 2 + expect(bindings['c']).toEqual "c" + expect(bindings['g']).toEqual "g" + + describe "when multiple bindings match a keystroke", -> + fit "only returns bindings that match the most specific selector", -> + keymap.bindKeys '.command-mode', 'g': 'command-mode' + keymap.bindKeys '.command-mode .grandchild-node', 'g': 'command-and-grandchild-node' + keymap.bindKeys '.grandchild-node', 'g': 'grandchild-node' + + bindings = keymap.bindingsForElement(fragment.find('.grandchild-node')) + expect(Object.keys(bindings).length).toBe 1 + expect(bindings['g']).toEqual "command-and-grandchild-node" \ No newline at end of file diff --git a/src/app/binding-set.coffee b/src/app/binding-set.coffee index 1f2dc4ca8..29dccb011 100644 --- a/src/app/binding-set.coffee +++ b/src/app/binding-set.coffee @@ -8,6 +8,7 @@ PEG = require 'pegjs' module.exports = class BindingSet selector: null + keystrokeMap: null commandForEvent: null keystrokePatternParser: null @@ -15,6 +16,7 @@ class BindingSet @parser = PEG.buildParser(fs.read(require.resolve 'keystroke-pattern.pegjs')) @specificity = Specificity(@selector) @commandForEvent = @buildEventHandler(mapOrFunction) + @keystrokeMap = if not _.isFunction(mapOrFunction) then mapOrFunction else {} buildEventHandler: (mapOrFunction) -> if _.isFunction(mapOrFunction) diff --git a/src/app/keymap.coffee b/src/app/keymap.coffee index 9d02c540d..d729083a0 100644 --- a/src/app/keymap.coffee +++ b/src/app/keymap.coffee @@ -6,7 +6,7 @@ $ = require 'jquery' module.exports = class Keymap - bindingSetsBySelector: null + bindingSets: null constructor: -> @bindingSets = [] @@ -26,10 +26,22 @@ class Keymap bindKeys: (selector, bindings) -> @bindingSets.unshift(new BindingSet(selector, bindings)) - bindKey: (selector, pattern, eventName) -> - bindings = {} - bindings[pattern] = eventName - @bindKeys(selector, bindings) + bindingsForElement: (element) -> + currentNode = $(element) + keystrokeMap = {} + + while currentNode.length + bindingSets = @bindingSets.filter (set) -> currentNode.is(set.selector) + console.log @bindingSets, currentNode + + bindingSets.sort (a, b) -> b.specificity - a.specificity + for bindingSet in bindingSets + for keystroke, command of bindingSet.keystrokeMap + keystrokeMap[keystroke] ?= command + + currentNode = currentNode.parent() + + keystrokeMap handleKeyEvent: (event) -> event.keystroke = @keystrokeStringForEvent(event)