Add ability to add/remove keymaps by name

This commit is contained in:
Corey Johnson & Nathan Sobo
2013-03-26 11:56:45 -06:00
committed by Nathan Sobo
parent 772787121c
commit 5410e9368f
3 changed files with 46 additions and 7 deletions

View File

@@ -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", ->

View File

@@ -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)

View File

@@ -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)