mirror of
https://github.com/atom/atom.git
synced 2026-02-05 04:05:05 -05:00
135 lines
4.1 KiB
CoffeeScript
135 lines
4.1 KiB
CoffeeScript
$ = require 'jquery'
|
|
_ = require 'underscore'
|
|
fs = require 'fs'
|
|
|
|
BindingSet = require 'binding-set'
|
|
Specificity = require 'specificity'
|
|
|
|
module.exports =
|
|
class Keymap
|
|
bindingSets: null
|
|
bindingSetsByFirstKeystroke: null
|
|
queuedKeystrokes: null
|
|
|
|
constructor: ->
|
|
@bindingSets = []
|
|
@bindingSetsByFirstKeystroke = {}
|
|
|
|
bindDefaultKeys: ->
|
|
@bindKeys "*",
|
|
'meta-n': 'new-window'
|
|
'meta-,': 'open-user-configuration'
|
|
'meta-o': 'open'
|
|
'meta-O': 'open-unstable'
|
|
'meta-w': 'core:close'
|
|
|
|
$(document).on 'new-window', => atom.newWindow()
|
|
$(document).on 'open-user-configuration', => atom.open(atom.configFilePath)
|
|
$(document).on 'open', => atom.open()
|
|
$(document).on 'open-unstable', => atom.openUnstable()
|
|
|
|
bindKeys: (selector, bindings) ->
|
|
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 = {}
|
|
currentNode = $(element)
|
|
|
|
while currentNode.length
|
|
bindingSets = @bindingSetsForNode(currentNode)
|
|
_.defaults(keystrokeMap, set.commandsByKeystrokes) for set in bindingSets
|
|
currentNode = currentNode.parent()
|
|
|
|
keystrokeMap
|
|
|
|
handleKeyEvent: (event) ->
|
|
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, bindingSetsForFirstKeystroke)
|
|
for bindingSet in candidateBindingSets
|
|
command = bindingSet.commandForEvent(event)
|
|
if command
|
|
continue if @triggerCommandEvent(event, command)
|
|
return false
|
|
else if command == false
|
|
return false
|
|
|
|
if bindingSet.matchesKeystrokePrefix(event)
|
|
@queuedKeystrokes = event.keystrokes
|
|
return false
|
|
currentNode = currentNode.parent()
|
|
|
|
!isMultiKeystroke
|
|
|
|
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
|
|
else
|
|
b.specificity - a.specificity
|
|
|
|
triggerCommandEvent: (keyEvent, commandName) ->
|
|
commandEvent = $.Event(commandName)
|
|
commandEvent.keyEvent = keyEvent
|
|
aborted = false
|
|
commandEvent.abortKeyBinding = ->
|
|
@stopImmediatePropagation()
|
|
aborted = true
|
|
$(keyEvent.target).trigger(commandEvent)
|
|
aborted
|
|
|
|
multiKeystrokeStringForEvent: (event) ->
|
|
currentKeystroke = @keystrokeStringForEvent(event)
|
|
if @queuedKeystrokes
|
|
@queuedKeystrokes + ' ' + currentKeystroke
|
|
else
|
|
currentKeystroke
|
|
|
|
keystrokeStringForEvent: (event) ->
|
|
if event.originalEvent.keyIdentifier.indexOf('U+') == 0
|
|
hexCharCode = event.originalEvent.keyIdentifier[2..]
|
|
charCode = parseInt(hexCharCode, 16)
|
|
key = @keyFromCharCode(charCode)
|
|
else
|
|
key = event.originalEvent.keyIdentifier.toLowerCase()
|
|
|
|
modifiers = []
|
|
if event.altKey and key isnt 'alt'
|
|
modifiers.push 'alt'
|
|
if event.ctrlKey and key isnt 'ctrl'
|
|
modifiers.push 'ctrl'
|
|
if event.metaKey and key isnt 'meta'
|
|
modifiers.push 'meta'
|
|
|
|
if event.shiftKey
|
|
isNamedKey = key.length > 1
|
|
modifiers.push 'shift' if isNamedKey
|
|
else
|
|
key = key.toLowerCase()
|
|
|
|
[modifiers..., key].join('-')
|
|
|
|
keyFromCharCode: (charCode) ->
|
|
switch charCode
|
|
when 8 then 'backspace'
|
|
when 9 then 'tab'
|
|
when 13 then 'enter'
|
|
when 27 then 'escape'
|
|
when 32 then 'space'
|
|
when 127 then 'delete'
|
|
else String.fromCharCode(charCode)
|