From 5410e9368fef33177a8880a68eaf87450f20eb72 Mon Sep 17 00:00:00 2001 From: Corey Johnson & Nathan Sobo Date: Tue, 26 Mar 2013 11:56:45 -0600 Subject: [PATCH] Add ability to add/remove keymaps by name --- spec/app/keymap-spec.coffee | 21 ++++++++++++++++++++- src/app/binding-set.coffee | 3 ++- src/app/keymap.coffee | 29 ++++++++++++++++++++++++----- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/spec/app/keymap-spec.coffee b/spec/app/keymap-spec.coffee index b813ad50c..2e6e7a534 100644 --- a/spec/app/keymap-spec.coffee +++ b/spec/app/keymap-spec.coffee @@ -1,5 +1,6 @@ Keymap = require 'keymap' $ = require 'jquery' +{$$} = require 'space-pen' RootView = require 'root-view' describe "Keymap", -> @@ -234,7 +235,7 @@ describe "Keymap", -> it "returns false to prevent the browser from transferring focus", -> expect(keymap.handleKeyEvent(keydownEvent('U+0009', target: fragment[0]))).toBe false - describe ".bindKeys(selector, hash)", -> + describe ".bindKeys(selector, bindings)", -> it "normalizes the key patterns in the hash to put the modifiers in alphabetical order", -> fooHandler = jasmine.createSpy('fooHandler') fragment.on 'foo', fooHandler @@ -249,6 +250,24 @@ describe "Keymap", -> expect(result).toBe(false) expect(fooHandler).toHaveBeenCalled() + describe ".remove(name)", -> + it "removes the binding set with the given selector and bindings", -> + keymap.add 'nature', + '.green': + 'ctrl-c': 'cultivate' + '.brown': + 'ctrl-h': 'harvest' + + expect(keymap.bindingsForElement($$ -> @div class: 'green')).toEqual { 'ctrl-c': 'cultivate' } + expect(keymap.bindingsForElement($$ -> @div class: 'brown')).toEqual { 'ctrl-h': 'harvest' } + + keymap.remove('nature') + + expect(keymap.bindingsForElement($$ -> @div class: 'green')).toEqual {} + expect(keymap.bindingsForElement($$ -> @div class: 'brown')).toEqual {} + expect(keymap.bindingSetsByFirstKeystroke['ctrl-c']).toEqual [] + expect(keymap.bindingSetsByFirstKeystroke['ctrl-h']).toEqual [] + describe ".keystrokeStringForEvent(event)", -> describe "when no modifiers are pressed", -> it "returns a string that identifies the key pressed", -> diff --git a/src/app/binding-set.coffee b/src/app/binding-set.coffee index 5621ef9cb..3bf87dab8 100644 --- a/src/app/binding-set.coffee +++ b/src/app/binding-set.coffee @@ -14,8 +14,9 @@ class BindingSet commandsByKeystrokes: null commandForEvent: null parser: null + name: null - constructor: (@selector, commandsByKeystrokes, @index) -> + constructor: (@selector, commandsByKeystrokes, @index, @name) -> BindingSet.parser ?= PEG.buildParser(fs.read(require.resolve 'keystroke-pattern.pegjs')) @specificity = Specificity(@selector) @commandsByKeystrokes = @normalizeCommandsByKeystrokes(commandsByKeystrokes) diff --git a/src/app/keymap.coffee b/src/app/keymap.coffee index ec260f417..068ccc606 100644 --- a/src/app/keymap.coffee +++ b/src/app/keymap.coffee @@ -40,20 +40,39 @@ class Keymap @load(filePath) for filePath in fs.list(directoryPath, ['.cson', '.json']) ? [] load: (path) -> - @add(CSON.readObject(path)) + @add(path, CSON.readObject(path)) - add: (keymap) -> + add: (args...) -> + name = args.shift() if args.length > 1 + keymap = args.shift() for selector, bindings of keymap - @bindKeys(selector, bindings) + @bindKeys(name, selector, bindings) - bindKeys: (selector, bindings) -> - bindingSet = new BindingSet(selector, bindings, @bindingSets.length) + remove: (name) -> + for bindingSet in @bindingSets.filter((bindingSet) -> bindingSet.name is name) + _.remove(@bindingSets, bindingSet) + for keystrokes of bindingSet.commandsByKeystrokes + keystroke = keystrokes.split(' ')[0] + _.remove(@bindingSetsByFirstKeystroke[keystroke], bindingSet) + + bindKeys: (args...) -> + name = args.shift() if args.length > 2 + [selector, bindings] = args + bindingSet = new BindingSet(selector, bindings, @bindingSets.length, name) @bindingSets.unshift(bindingSet) for keystrokes of bindingSet.commandsByKeystrokes keystroke = keystrokes.split(' ')[0] # only index by first keystroke @bindingSetsByFirstKeystroke[keystroke] ?= [] @bindingSetsByFirstKeystroke[keystroke].push(bindingSet) + unbindKeys: (selector, bindings) -> + bindingSet = _.detect @bindingSets, (bindingSet) -> + bindingSet.selector is selector and bindingSet.bindings is bindings + + if bindingSet + console.log "binding set", bindingSet + _.remove(@bindingSets, bindingSet) + bindingsForElement: (element) -> keystrokeMap = {} currentNode = $(element)