Files
atom/src/app/keymap.coffee
Kevin Sawicki 9ca7214d39 Add --dev flag and remove --stable flag
Atom now runs in stable mode by default and only
runs in dev mode when the --dev flag is specified.

Closes #198
2013-02-22 11:54:54 -08:00

154 lines
4.7 KiB
CoffeeScript

$ = require 'jquery'
_ = require 'underscore'
fs = require 'fs'
BindingSet = require 'binding-set'
module.exports =
class Keymap
bindingSets: null
bindingSetsByFirstKeystroke: null
queuedKeystrokes: null
constructor: ->
@bindingSets = []
@bindingSetsByFirstKeystroke = {}
bindDefaultKeys: ->
@add
'body':
'meta-n': 'new-window'
'meta-,': 'open-user-configuration'
'meta-o': 'open'
'meta-O': 'open-dev'
'meta-w': 'core:close'
'alt-meta-i': 'toggle-dev-tools'
$(document).command 'new-window', => atom.newWindow()
$(document).command 'open-user-configuration', => atom.open(config.configDirPath)
$(document).command 'open', => atom.open()
$(document).command 'open-dev', => atom.openDev()
loadBundledKeymaps: ->
@loadDirectory(require.resolve('keymaps'))
loadUserKeymaps: ->
@loadDirectory(fs.join(config.configDirPath, 'keymaps'))
loadDirectory: (directoryPath) ->
@load(filePath) for filePath in fs.list(directoryPath, ['.cson', '.json'])
load: (path) ->
@add(fs.readObject(path))
add: (keymap) ->
for selector, bindings of keymap
@bindKeys(selector, bindings)
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]
if bindingSetsForFirstKeystroke?
currentNode = $(event.target)
currentNode = rootView if currentNode is $('body')[0]
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()
return false if isMultiKeystroke
return false if firstKeystroke is 'tab'
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) ->
keyEvent.target = rootView[0] if keyEvent.target == document.body and window.rootView
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)