Only consider BindingSets with a binding for first keystroke of event

The keymap was slow because it would find the binding sets with matching selectors for every ancestor of every keydown event. The problem was, it was considering a lot of binding sets that didn't even have a binding for the event in question. Now we index all binding sets on what bindings they contain, and filter them by that first. Rejecting an event that has no bindings is almost instantaneous now.
This commit is contained in:
Nathan Sobo
2012-11-02 14:13:03 -06:00
parent 2c211ba504
commit adbcb9f49e

View File

@@ -8,10 +8,12 @@ Specificity = require 'specificity'
module.exports =
class Keymap
bindingSets: null
bindingSetsByFirstKeystroke: null
queuedKeystrokes: null
constructor: ->
@bindingSets = []
@bindingSetsByFirstKeystroke = {}
bindDefaultKeys: ->
@bindKeys "*",
@@ -25,8 +27,12 @@ class Keymap
$(document).on 'open', => atom.open()
bindKeys: (selector, bindings) ->
index = @bindingSets.length
@bindingSets.unshift(new BindingSet(selector, bindings, index))
bindingSet = new BindingSet(selector, bindings, @bindingSets.length)
@bindingSets.unshift(bindingSet)
for keystrokes of bindingSet.commandsByKeystrokes
keystroke = keystrokes.split(' ')[0] # only index by first keystroke
@bindingSetsByFirstKeystroke[keystroke] ?= []
@bindingSetsByFirstKeystroke[keystroke].push(bindingSet)
bindingsForElement: (element) ->
keystrokeMap = {}
@@ -43,9 +49,14 @@ class Keymap
event.keystrokes = @multiKeystrokeStringForEvent(event)
isMultiKeystroke = @queuedKeystrokes?
@queuedKeystrokes = null
firstKeystroke = event.keystrokes.split(' ')[0]
bindingSetsForFirstKeystroke = @bindingSetsByFirstKeystroke[firstKeystroke]
return true unless bindingSetsForFirstKeystroke?
currentNode = $(event.target)
while currentNode.length
candidateBindingSets = @bindingSetsForNode(currentNode)
candidateBindingSets = @bindingSetsForNode(currentNode, bindingSetsForFirstKeystroke)
for bindingSet in candidateBindingSets
command = bindingSet.commandForEvent(event)
if command
@@ -61,8 +72,8 @@ class Keymap
!isMultiKeystroke
bindingSetsForNode: (node) ->
bindingSets = @bindingSets.filter (set) -> node.is(set.selector)
bindingSetsForNode: (node, candidateBindingSets = @bindingSets) ->
bindingSets = candidateBindingSets.filter (set) -> node.is(set.selector)
bindingSets.sort (a, b) ->
if b.specificity == a.specificity
b.index - a.index