Files
atom/src/key-binding.coffee

65 lines
1.9 KiB
CoffeeScript

_ = require 'underscore-plus'
fs = require 'fs-plus'
{specificity} = require 'clear-cut'
module.exports =
class KeyBinding
@parser: null
@currentIndex: 1
@specificities: null
@calculateSpecificity: (selector) ->
@specificities ?= {}
value = @specificities[selector]
unless value?
value = specificity(selector)
@specificities[selector] = value
value
@normalizeKeystroke: (keystroke) ->
normalizedKeystroke = keystroke.split(/\s+/).map (keystroke) =>
keys = @parseKeystroke(keystroke)
modifiers = keys[0...-1]
modifiers.sort()
key = _.last(keys)
modifiers.push 'shift' if /^[A-Z]$/.test(key) and 'shift' not in modifiers
key = key.toUpperCase() if /^[a-z]$/.test(key) and 'shift' in modifiers
[modifiers..., key].join('-')
normalizedKeystroke.join(' ')
@parseKeystroke: (keystroke) ->
unless @parser?
try
@parser = require './keystroke-pattern'
catch
{allowUnsafeEval} = require 'loophole'
keystrokePattern = fs.readFileSync(require.resolve('./keystroke-pattern.pegjs'), 'utf8')
PEG = require 'pegjs'
allowUnsafeEval => @parser = PEG.buildParser(keystrokePattern)
@parser.parse(keystroke)
constructor: (source, command, keystroke, selector) ->
@source = source
@command = command
@keystroke = KeyBinding.normalizeKeystroke(keystroke)
@selector = selector.replace(/!important/g, '')
@specificity = KeyBinding.calculateSpecificity(selector)
@index = KeyBinding.currentIndex++
matches: (keystroke) ->
multiKeystroke = /\s/.test keystroke
if multiKeystroke
keystroke == @keystroke
else
keystroke.split(' ')[0] == @keystroke.split(' ')[0]
compare: (keyBinding) ->
if keyBinding.specificity == @specificity
keyBinding.index - @index
else
keyBinding.specificity - @specificity