mirror of
https://github.com/atom/atom.git
synced 2026-01-24 14:28:14 -05:00
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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user