atom and stdlib

This commit is contained in:
Chris Wanstrath
2011-11-09 18:33:43 -08:00
parent 84acc61ce1
commit 9dea4c24b2
18 changed files with 4 additions and 2 deletions

View File

@@ -0,0 +1,146 @@
_ = require 'underscore'
fs = require 'fs'
Watcher = require 'watcher'
{CoffeeScript} = require 'coffee-script'
module.exports =
class KeyBinder
bindings: {}
scopes: {}
register: (name, scope) ->
@scopes[name] = scope
load: (path) ->
try
Watcher.watch path, =>
# Should we keep track of which file bindings are associated with? That
# way we could clear bindings when the file is changed or deleted. I
# think the answer is yes, but I don't want to do this right now.
console.log "#{@name}: Reloading #{path}"
@load path
json = CoffeeScript.eval "return " + (fs.read path)
for scopeName, bindings of json
@create scopeName, binding, method for binding, method of bindings
catch error
console.error "#{@name}: Could not load key bindings at `#{path}`. #{error}"
create: (scope, binding, method) ->
if typeof scope is "string"
throw "#{@name}: Unknown scope `#{scope}`" unless @scopes[scope]
scope = @scopes[scope]
callback = if _.isFunction method
-> method scope
else if scope[method]
-> scope[method]()
else
throw "#{@name}: '#{method}' not found found in scope #{scope}"
callbacks = @bindings[@bindingParser binding] ?= []
callbacks.push callback
handleEvent: (event) ->
keys = []
keys.push @modifierKeys.command if event.modifierFlags & OSX.NSCommandKeyMask
keys.push @modifierKeys.control if event.modifierFlags & OSX.NSControlKeyMask
keys.push @modifierKeys.alt if event.modifierFlags & OSX.NSAlternateKeyMask
keys.push event.charactersIgnoringModifiers.charCodeAt 0
binding = keys.sort().join "-"
callbacks = @bindings[binding]
return false if not callbacks
# Only use the most recently added binding
try
_.last(callbacks)()
catch e
console.warn "Failed to run binding #{@bindingFromAscii binding}. #{e}"
true
bindingParser: (binding) ->
keys = binding.trim().split '-'
modifiers = []
key = null
for k in keys
if modifier = @modifierKeys[k.toLowerCase()]
modifiers.push modifier unless modifier == @modifierKeys['shift'] # Shift is implied? YES
else if key
throw "#{@name}: #{binding} specifies TWO keys, we don't handle that yet."
else if namedKey = @namedKeys[k.toLowerCase()]
key = namedKey
else if k.length > 1
throw "#{@name}: #{binding} uses an unknown key #{k}."
else
charCode = k.charCodeAt 0
key = k.charCodeAt 0
modifiers.concat(key).sort().join "-"
bindingFromAscii: (binding) ->
inverseModifierKeys = {}
inverseModifierKeys[number] = label for label, number of @modifierKeys
inverseNamedKeys = {}
inverseNamedKeys[number] = label for label, number of @namedKeys
asciiKeys = binding.split '-'
keys = []
for asciiKey in asciiKeys
key = inverseModifierKeys[asciiKey]
key ?= inverseNamedKeys[asciiKey]
key ?= String.fromCharCode asciiKey
keys.push key or "?"
keys.join '-'
modifierKeys:
'': 16
'': 91
'': 18
shift: 16
alt: 18
option: 18
control: 17
ctrl: 17
command: 91
cmd: 91
namedKeys:
backspace: 8
tab: 9
clear: 12
enter: 13
return: 13
esc: 27
escape: 27
space: 32
left: 37
up: 38
right: 39
down: 40
del: 46
delete: 46
home: 36
end: 35
pageup: 33
pagedown: 34
',': 188
'.': 190
'/': 191
'`': 192
'-': 189
'=': 187
';': 186
'\'': 222
'[': 219
']': 221
'\\': 220