mirror of
https://github.com/atom/atom.git
synced 2026-01-23 13:58:08 -05:00
@@ -13,7 +13,7 @@
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"bootstrap": "git://github.com/twbs/bootstrap.git#v3.0.0",
|
||||
"clear-cut": "0.1.0",
|
||||
"clear-cut": "0.2.0",
|
||||
"coffee-script": "1.6.3",
|
||||
"coffeestack": "0.6.0",
|
||||
"emissary": "0.17.0",
|
||||
@@ -78,7 +78,7 @@
|
||||
"bookmarks": "0.10.0",
|
||||
"bracket-matcher": "0.11.0",
|
||||
"command-logger": "0.6.0",
|
||||
"command-palette": "0.7.0",
|
||||
"command-palette": "0.8.0",
|
||||
"dev-live-reload": "0.15.0",
|
||||
"editor-stats": "0.5.0",
|
||||
"exception-reporting": "0.7.0",
|
||||
@@ -90,12 +90,13 @@
|
||||
"go-to-line": "0.8.0",
|
||||
"grammar-selector": "0.8.0",
|
||||
"image-view": "0.7.0",
|
||||
"keybinding-resolver": "0.2.0",
|
||||
"link": "0.7.0",
|
||||
"markdown-preview": "0.15.0",
|
||||
"metrics": "0.11.0",
|
||||
"package-generator": "0.19.0",
|
||||
"release-notes": "0.11.0",
|
||||
"settings-view": "0.39.0",
|
||||
"settings-view": "0.41.0",
|
||||
"snippets": "0.13.0",
|
||||
"spell-check": "0.13.0",
|
||||
"status-bar": "0.16.0",
|
||||
|
||||
@@ -137,28 +137,28 @@ describe "the `atom` global", ->
|
||||
element2 = $$ -> @div class: 'test-2'
|
||||
element3 = $$ -> @div class: 'test-3'
|
||||
|
||||
expect(atom.keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined()
|
||||
expect(atom.keymap.bindingsForElement(element2)['ctrl-z']).toBeUndefined()
|
||||
expect(atom.keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined()
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)).toHaveLength 0
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element2)).toHaveLength 0
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element3)).toHaveLength 0
|
||||
|
||||
atom.activatePackage("package-with-keymaps")
|
||||
|
||||
expect(atom.keymap.bindingsForElement(element1)['ctrl-z']).toBe "test-1"
|
||||
expect(atom.keymap.bindingsForElement(element2)['ctrl-z']).toBe "test-2"
|
||||
expect(atom.keymap.bindingsForElement(element3)['ctrl-z']).toBeUndefined()
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)[0].command).toBe "test-1"
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element2)[0].command).toBe "test-2"
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element3)).toHaveLength 0
|
||||
|
||||
describe "when the metadata contains a 'keymaps' manifest", ->
|
||||
it "loads only the keymaps specified by the manifest, in the specified order", ->
|
||||
element1 = $$ -> @div class: 'test-1'
|
||||
element3 = $$ -> @div class: 'test-3'
|
||||
|
||||
expect(atom.keymap.bindingsForElement(element1)['ctrl-z']).toBeUndefined()
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)).toHaveLength 0
|
||||
|
||||
atom.activatePackage("package-with-keymaps-manifest")
|
||||
|
||||
expect(atom.keymap.bindingsForElement(element1)['ctrl-z']).toBe 'keymap-1'
|
||||
expect(atom.keymap.bindingsForElement(element1)['ctrl-n']).toBe 'keymap-2'
|
||||
expect(atom.keymap.bindingsForElement(element3)['ctrl-y']).toBeUndefined()
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', element1)[0].command).toBe 'keymap-1'
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-n', element1)[0].command).toBe 'keymap-2'
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-y', element3)).toHaveLength 0
|
||||
|
||||
describe "menu loading", ->
|
||||
beforeEach ->
|
||||
@@ -317,8 +317,8 @@ describe "the `atom` global", ->
|
||||
it "removes the package's keymaps", ->
|
||||
atom.activatePackage('package-with-keymaps')
|
||||
atom.deactivatePackage('package-with-keymaps')
|
||||
expect(atom.keymap.bindingsForElement($$ -> @div class: 'test-1')['ctrl-z']).toBeUndefined()
|
||||
expect(atom.keymap.bindingsForElement($$ -> @div class: 'test-2')['ctrl-z']).toBeUndefined()
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-1')).toHaveLength 0
|
||||
expect(atom.keymap.keyBindingsForKeystrokeMatchingElement('ctrl-z', $$ -> @div class: 'test-2')).toHaveLength 0
|
||||
|
||||
it "removes the package's stylesheets", ->
|
||||
atom.activatePackage('package-with-stylesheets')
|
||||
|
||||
@@ -2719,7 +2719,7 @@ describe "Editor", ->
|
||||
|
||||
describe "when the escape key is pressed on the editor", ->
|
||||
it "clears multiple selections if there are any, and otherwise allows other bindings to be handled", ->
|
||||
keymap.bindKeys '.editor', 'escape': 'test-event'
|
||||
keymap.bindKeys 'name', '.editor', 'escape': 'test-event'
|
||||
testEventHandler = jasmine.createSpy("testEventHandler")
|
||||
|
||||
editor.on 'test-event', testEventHandler
|
||||
|
||||
@@ -21,25 +21,19 @@ describe "Keymap", ->
|
||||
describe ".handleKeyEvent(event)", ->
|
||||
deleteCharHandler = null
|
||||
insertCharHandler = null
|
||||
metaZHandler = null
|
||||
|
||||
beforeEach ->
|
||||
keymap.bindKeys '.command-mode', 'x': 'deleteChar'
|
||||
keymap.bindKeys '.insert-mode', 'x': 'insertChar'
|
||||
keymap.bindKeys 'name', '.command-mode', 'x': 'deleteChar'
|
||||
keymap.bindKeys 'name', '.insert-mode', 'x': 'insertChar'
|
||||
keymap.bindKeys 'name', '.command-mode', 'meta-z': 'metaZPressed'
|
||||
|
||||
deleteCharHandler = jasmine.createSpy('deleteCharHandler')
|
||||
insertCharHandler = jasmine.createSpy('insertCharHandler')
|
||||
metaZHandler = jasmine.createSpy('metaZHandler')
|
||||
fragment.on 'deleteChar', deleteCharHandler
|
||||
fragment.on 'insertChar', insertCharHandler
|
||||
|
||||
it "adds a 'keystrokes' string to the event object", ->
|
||||
event = keydownEvent('x', altKey: true, metaKey: true)
|
||||
keymap.handleKeyEvent(event)
|
||||
expect(event.keystrokes).toBe 'alt-meta-x'
|
||||
|
||||
event = keydownEvent(',', metaKey: true)
|
||||
event.which = 188
|
||||
keymap.handleKeyEvent(event)
|
||||
expect(event.keystrokes).toBe 'meta-,'
|
||||
fragment.on 'metaZPressed', metaZHandler
|
||||
|
||||
describe "when no binding matches the event's keystroke", ->
|
||||
it "does not return false so the event continues to propagate", ->
|
||||
@@ -47,10 +41,11 @@ describe "Keymap", ->
|
||||
|
||||
describe "when a non-English keyboard language is used", ->
|
||||
it "uses the physical character pressed instead of the character it maps to in the current language", ->
|
||||
event = keydownEvent('U+03B6', metaKey: true) # This is the 'z' key using the Greek keyboard layout
|
||||
event.which = 122
|
||||
keymap.handleKeyEvent(event)
|
||||
expect(event.keystrokes).toBe 'meta-z'
|
||||
event = keydownEvent('U+03B6', metaKey: true, which: 122, target: fragment[0]) # This is the 'z' key using the Greek keyboard layout
|
||||
result = keymap.handleKeyEvent(event)
|
||||
|
||||
expect(result).toBe(false)
|
||||
expect(metaZHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when at least one binding fully matches the event's keystroke", ->
|
||||
describe "when the event's target node matches a selector with a matching binding", ->
|
||||
@@ -67,9 +62,6 @@ describe "Keymap", ->
|
||||
keymap.handleKeyEvent(event)
|
||||
expect(deleteCharHandler).not.toHaveBeenCalled()
|
||||
expect(insertCharHandler).toHaveBeenCalled()
|
||||
commandEvent = insertCharHandler.argsForCall[0][0]
|
||||
expect(commandEvent.keyEvent).toBe event
|
||||
expect(event.keystrokes).toBe 'x'
|
||||
|
||||
describe "when the event's target node *descends* from a selector with a matching binding", ->
|
||||
it "triggers the command event associated with that binding on the target node and returns false", ->
|
||||
@@ -88,7 +80,7 @@ describe "Keymap", ->
|
||||
|
||||
describe "when the event's target node descends from multiple nodes that match selectors with a binding", ->
|
||||
beforeEach ->
|
||||
keymap.bindKeys '.child-node', 'x': 'foo'
|
||||
keymap.bindKeys 'name', '.child-node', 'x': 'foo'
|
||||
|
||||
it "only triggers bindings on selectors associated with the closest ancestor node", ->
|
||||
fooHandler = jasmine.createSpy 'fooHandler'
|
||||
@@ -125,10 +117,10 @@ describe "Keymap", ->
|
||||
describe "when the event bubbles to a node that matches multiple selectors", ->
|
||||
describe "when the matching selectors differ in specificity", ->
|
||||
it "triggers the binding for the most specific selector", ->
|
||||
keymap.bindKeys 'div .child-node', 'x': 'foo'
|
||||
keymap.bindKeys '.command-mode .child-node !important', 'x': 'baz'
|
||||
keymap.bindKeys '.command-mode .child-node', 'x': 'quux'
|
||||
keymap.bindKeys '.child-node', 'x': 'bar'
|
||||
keymap.bindKeys 'name', 'div .child-node', 'x': 'foo'
|
||||
keymap.bindKeys 'name', '.command-mode .child-node !important', 'x': 'baz'
|
||||
keymap.bindKeys 'name', '.command-mode .child-node', 'x': 'quux'
|
||||
keymap.bindKeys 'name', '.child-node', 'x': 'bar'
|
||||
|
||||
fooHandler = jasmine.createSpy 'fooHandler'
|
||||
barHandler = jasmine.createSpy 'barHandler'
|
||||
@@ -146,8 +138,8 @@ describe "Keymap", ->
|
||||
|
||||
describe "when the matching selectors have the same specificity", ->
|
||||
it "triggers the bindings for the most recently declared selector", ->
|
||||
keymap.bindKeys '.child-node', 'x': 'foo', 'y': 'baz'
|
||||
keymap.bindKeys '.child-node', 'x': 'bar'
|
||||
keymap.bindKeys 'name', '.child-node', 'x': 'foo', 'y': 'baz'
|
||||
keymap.bindKeys 'name', '.child-node', 'x': 'bar'
|
||||
|
||||
fooHandler = jasmine.createSpy 'fooHandler'
|
||||
barHandler = jasmine.createSpy 'barHandler'
|
||||
@@ -168,7 +160,8 @@ describe "Keymap", ->
|
||||
describe "when the event's target is the document body", ->
|
||||
it "triggers the mapped event on the rootView", ->
|
||||
window.rootView = new RootView
|
||||
keymap.bindKeys 'body', 'x': 'foo'
|
||||
rootView.attachToDom()
|
||||
keymap.bindKeys 'name', 'body', 'x': 'foo'
|
||||
fooHandler = jasmine.createSpy("fooHandler")
|
||||
rootView.on 'foo', fooHandler
|
||||
|
||||
@@ -180,7 +173,7 @@ describe "Keymap", ->
|
||||
|
||||
describe "when the event matches a 'native!' binding", ->
|
||||
it "returns true, allowing the browser's native key handling to process the event", ->
|
||||
keymap.bindKeys '.grandchild-node', 'x': 'native!'
|
||||
keymap.bindKeys 'name', '.grandchild-node', 'x': 'native!'
|
||||
nativeHandler = jasmine.createSpy("nativeHandler")
|
||||
fragment.on 'native!', nativeHandler
|
||||
expect(keymap.handleKeyEvent(keydownEvent('x', target: fragment.find('.grandchild-node')[0]))).toBe true
|
||||
@@ -190,7 +183,7 @@ describe "Keymap", ->
|
||||
[quitHandler, closeOtherWindowsHandler] = []
|
||||
|
||||
beforeEach ->
|
||||
keymap.bindKeys "*",
|
||||
keymap.bindKeys 'name', "*",
|
||||
'ctrl-x ctrl-c': 'quit'
|
||||
'ctrl-x 1': 'close-other-windows'
|
||||
|
||||
@@ -220,7 +213,7 @@ describe "Keymap", ->
|
||||
expect(closeOtherWindowsHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when a second keystroke added to the first doesn't match any bindings", ->
|
||||
it "clears the queued keystrokes without triggering any events", ->
|
||||
it "clears the queued keystroke without triggering any events", ->
|
||||
expect(keymap.handleKeyEvent(keydownEvent('x', target: fragment[0], ctrlKey: true))).toBe false
|
||||
expect(keymap.handleKeyEvent(keydownEvent('c', target: fragment[0]))).toBe false
|
||||
expect(quitHandler).not.toHaveBeenCalled()
|
||||
@@ -230,7 +223,7 @@ describe "Keymap", ->
|
||||
|
||||
describe "when the event's target node descends from multiple nodes that match selectors with a partial binding match", ->
|
||||
it "allows any of the bindings to be triggered upon a second keystroke, favoring the most specific selector", ->
|
||||
keymap.bindKeys ".grandchild-node", 'ctrl-x ctrl-c': 'more-specific-quit'
|
||||
keymap.bindKeys 'name', ".grandchild-node", 'ctrl-x ctrl-c': 'more-specific-quit'
|
||||
grandchildNode = fragment.find('.grandchild-node')[0]
|
||||
moreSpecificQuitHandler = jasmine.createSpy('moreSpecificQuitHandler')
|
||||
fragment.on 'more-specific-quit', moreSpecificQuitHandler
|
||||
@@ -254,39 +247,17 @@ describe "Keymap", ->
|
||||
describe "when there is a complete binding with a more specific selector", ->
|
||||
it "favors the more specific complete match", ->
|
||||
|
||||
describe "when a tab keystroke does not match any bindings", ->
|
||||
it "returns false to prevent the browser from transferring focus", ->
|
||||
expect(keymap.handleKeyEvent(keydownEvent('U+0009', target: fragment[0]))).toBe false
|
||||
|
||||
describe ".keystrokesByCommandForSelector(selector)", ->
|
||||
it "returns a hash of all commands and their keybindings", ->
|
||||
keymap.bindKeys 'body', 'a': 'letter'
|
||||
keymap.bindKeys '.editor', 'b': 'letter'
|
||||
keymap.bindKeys '.editor', '1': 'number'
|
||||
keymap.bindKeys '.editor', 'meta-alt-1': 'number-with-modifiers'
|
||||
|
||||
expect(keymap.keystrokesByCommandForSelector()).toEqual
|
||||
'letter': ['b', 'a']
|
||||
'number': ['1']
|
||||
'number-with-modifiers': ['alt-meta-1']
|
||||
|
||||
expect(keymap.keystrokesByCommandForSelector('.editor')).toEqual
|
||||
'letter': ['b']
|
||||
'number': ['1']
|
||||
'number-with-modifiers': ['alt-meta-1']
|
||||
|
||||
|
||||
describe ".bindKeys(selector, bindings)", ->
|
||||
describe ".bindKeys(name, selector, bindings)", ->
|
||||
it "normalizes the key patterns in the hash to put the modifiers in alphabetical order", ->
|
||||
fooHandler = jasmine.createSpy('fooHandler')
|
||||
fragment.on 'foo', fooHandler
|
||||
keymap.bindKeys '*', 'ctrl-alt-delete': 'foo'
|
||||
keymap.bindKeys 'name', '*', 'ctrl-alt-delete': 'foo'
|
||||
result = keymap.handleKeyEvent(keydownEvent('delete', ctrlKey: true, altKey: true, target: fragment[0]))
|
||||
expect(result).toBe(false)
|
||||
expect(fooHandler).toHaveBeenCalled()
|
||||
|
||||
fooHandler.reset()
|
||||
keymap.bindKeys '*', 'ctrl-alt--': 'foo'
|
||||
keymap.bindKeys 'name', '*', 'ctrl-alt--': 'foo'
|
||||
result = keymap.handleKeyEvent(keydownEvent('-', ctrlKey: true, altKey: true, target: fragment[0]))
|
||||
expect(result).toBe(false)
|
||||
expect(fooHandler).toHaveBeenCalled()
|
||||
@@ -299,15 +270,17 @@ describe "Keymap", ->
|
||||
'.brown':
|
||||
'ctrl-h': 'harvest'
|
||||
|
||||
expect(keymap.bindingsForElement($$ -> @div class: 'green')).toEqual { 'ctrl-c': 'cultivate' }
|
||||
expect(keymap.bindingsForElement($$ -> @div class: 'brown')).toEqual { 'ctrl-h': 'harvest' }
|
||||
keymap.add 'medical',
|
||||
'.green':
|
||||
'ctrl-v': 'vomit'
|
||||
|
||||
expect(keymap.keyBindingsMatchingElement($$ -> @div class: 'green')).toHaveLength 2
|
||||
expect(keymap.keyBindingsMatchingElement($$ -> @div class: 'brown')).toHaveLength 1
|
||||
|
||||
keymap.remove('nature')
|
||||
|
||||
expect(keymap.bindingsForElement($$ -> @div class: 'green')).toEqual {}
|
||||
expect(keymap.bindingsForElement($$ -> @div class: 'brown')).toEqual {}
|
||||
expect(keymap.bindingSetsByFirstKeystroke['ctrl-c']).toEqual []
|
||||
expect(keymap.bindingSetsByFirstKeystroke['ctrl-h']).toEqual []
|
||||
expect(keymap.keyBindingsMatchingElement($$ -> @div class: 'green')).toHaveLength 1
|
||||
expect(keymap.keyBindingsMatchingElement($$ -> @div class: 'brown')).toEqual []
|
||||
|
||||
describe ".keystrokeStringForEvent(event)", ->
|
||||
describe "when no modifiers are pressed", ->
|
||||
@@ -332,54 +305,22 @@ describe "Keymap", ->
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('left', shiftKey: true))).toBe 'shift-left'
|
||||
expect(keymap.keystrokeStringForEvent(keydownEvent('Left', shiftKey: true))).toBe 'shift-left'
|
||||
|
||||
describe ".bindingsForElement(element)", ->
|
||||
describe ".keyBindingsMatchingElement(element)", ->
|
||||
it "returns the matching bindings for the element", ->
|
||||
keymap.bindKeys '.command-mode', 'c': 'c'
|
||||
keymap.bindKeys '.grandchild-node', 'g': 'g'
|
||||
keymap.bindKeys 'name', '.command-mode', 'c': 'c'
|
||||
keymap.bindKeys 'name', '.grandchild-node', 'g': 'g'
|
||||
|
||||
bindings = keymap.bindingsForElement(fragment.find('.grandchild-node'))
|
||||
expect(Object.keys(bindings).length).toBe 2
|
||||
expect(bindings['c']).toEqual "c"
|
||||
expect(bindings['g']).toEqual "g"
|
||||
bindings = keymap.keyBindingsMatchingElement(fragment.find('.grandchild-node'))
|
||||
expect(bindings).toHaveLength 2
|
||||
expect(bindings[0].command).toEqual "g"
|
||||
expect(bindings[1].command).toEqual "c"
|
||||
|
||||
describe "when multiple bindings match a keystroke", ->
|
||||
it "only returns bindings that match the most specific selector", ->
|
||||
keymap.bindKeys '.command-mode', 'g': 'command-mode'
|
||||
keymap.bindKeys '.command-mode .grandchild-node', 'g': 'command-and-grandchild-node'
|
||||
keymap.bindKeys '.grandchild-node', 'g': 'grandchild-node'
|
||||
keymap.bindKeys 'name', '.command-mode', 'g': 'command-mode'
|
||||
keymap.bindKeys 'name', '.command-mode .grandchild-node', 'g': 'command-and-grandchild-node'
|
||||
keymap.bindKeys 'name', '.grandchild-node', 'g': 'grandchild-node'
|
||||
|
||||
bindings = keymap.bindingsForElement(fragment.find('.grandchild-node'))
|
||||
expect(Object.keys(bindings).length).toBe 1
|
||||
expect(bindings['g']).toEqual "command-and-grandchild-node"
|
||||
|
||||
describe ".getAllKeyMappings", ->
|
||||
it "returns the all bindings", ->
|
||||
keymap.bindKeys path.join('~', '.atom', 'packages', 'dummy', 'keymaps', 'a.cson'), '.command-mode', 'k': 'c'
|
||||
|
||||
mappings = keymap.getAllKeyMappings()
|
||||
expect(mappings.length).toBe 1
|
||||
expect(mappings[0].source).toEqual 'dummy'
|
||||
expect(mappings[0].keystrokes).toEqual 'k'
|
||||
expect(mappings[0].command).toEqual 'c'
|
||||
expect(mappings[0].selector).toEqual '.command-mode'
|
||||
|
||||
describe ".determineSource", ->
|
||||
describe "for a package", ->
|
||||
it "returns '<package-name>'", ->
|
||||
expect(keymap.determineSource(path.join('~', '.atom', 'packages', 'dummy', 'keymaps', 'a.cson'))).toEqual 'dummy'
|
||||
|
||||
describe "for a linked package", ->
|
||||
it "returns '<package-name>'", ->
|
||||
expect(keymap.determineSource(path.join('Users', 'john', 'github', 'dummy', 'keymaps', 'a.cson'))).toEqual 'dummy'
|
||||
|
||||
describe "for a user defined keymap", ->
|
||||
it "returns 'User'", ->
|
||||
expect(keymap.determineSource(path.join('~', '.atom', 'keymaps', 'a.cson'))).toEqual 'User'
|
||||
|
||||
describe "for a core keymap", ->
|
||||
it "returns 'Core'", ->
|
||||
expect(keymap.determineSource(path.join('Applications', 'Atom.app', '..', 'node_modules', 'dummy', 'keymaps', 'a.cson'))).toEqual 'Core'
|
||||
|
||||
describe "for a linked core keymap", ->
|
||||
it "returns 'Core'", ->
|
||||
expect(keymap.determineSource(path.join('Users', 'john', 'github', 'atom', 'keymaps', 'a.cson'))).toEqual 'Core'
|
||||
bindings = keymap.keyBindingsMatchingElement(fragment.find('.grandchild-node'))
|
||||
expect(bindings).toHaveLength 3
|
||||
expect(bindings[0].command).toEqual "command-and-grandchild-node"
|
||||
|
||||
@@ -137,7 +137,7 @@ describe "RootView", ->
|
||||
commandHandler = jasmine.createSpy('commandHandler')
|
||||
rootView.on('foo-command', commandHandler)
|
||||
|
||||
atom.keymap.bindKeys('*', 'x': 'foo-command')
|
||||
atom.keymap.bindKeys('name', '*', 'x': 'foo-command')
|
||||
|
||||
describe "when a keydown event is triggered in the RootView", ->
|
||||
it "triggers matching keybindings for that event", ->
|
||||
|
||||
@@ -23,7 +23,7 @@ atom.themes.requireStylesheet '../static/jasmine'
|
||||
fixturePackagesPath = path.resolve(__dirname, './fixtures/packages')
|
||||
atom.packages.packageDirPaths.unshift(fixturePackagesPath)
|
||||
atom.keymap.loadBundledKeymaps()
|
||||
[bindingSetsToRestore, bindingSetsByFirstKeystrokeToRestore] = []
|
||||
keyBindingsToRestore = atom.keymap.getKeyBindings()
|
||||
|
||||
$(window).on 'core:close', -> window.close()
|
||||
$(window).on 'unload', ->
|
||||
@@ -50,6 +50,7 @@ beforeEach ->
|
||||
projectPath = specProjectPath ? path.join(@specDirectory, 'fixtures')
|
||||
atom.project = atom.getWindowState().set('project', new Project(path: projectPath))
|
||||
window.project = atom.project
|
||||
atom.keymap.keyBindings = _.clone(keyBindingsToRestore)
|
||||
|
||||
window.resetTimeouts()
|
||||
atom.packages.packageStates = {}
|
||||
@@ -64,10 +65,6 @@ beforeEach ->
|
||||
resolvePackagePath(packageName)
|
||||
resolvePackagePath = _.bind(spy.originalValue, atom.packages)
|
||||
|
||||
# used to reset keymap after each spec
|
||||
bindingSetsToRestore = _.clone(atom.keymap.bindingSets)
|
||||
bindingSetsByFirstKeystrokeToRestore = _.clone(atom.keymap.bindingSetsByFirstKeystroke)
|
||||
|
||||
# prevent specs from modifying Atom's menus
|
||||
spyOn(atom.menu, 'sendToBrowserProcess')
|
||||
|
||||
@@ -106,8 +103,6 @@ beforeEach ->
|
||||
addCustomMatchers(this)
|
||||
|
||||
afterEach ->
|
||||
atom.keymap.bindingSets = bindingSetsToRestore
|
||||
atom.keymap.bindingSetsByFirstKeystroke = bindingSetsByFirstKeystrokeToRestore
|
||||
atom.deactivatePackages()
|
||||
atom.menu.template = []
|
||||
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
{$} = require './space-pen-extensions'
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
{specificity} = require 'clear-cut'
|
||||
PEG = require 'pegjs'
|
||||
|
||||
### Internal ###
|
||||
|
||||
module.exports =
|
||||
class BindingSet
|
||||
|
||||
@parser: null
|
||||
|
||||
selector: null
|
||||
commandsByKeystrokes: null
|
||||
parser: null
|
||||
name: null
|
||||
|
||||
constructor: (selector, commandsByKeystrokes, @index, @name) ->
|
||||
keystrokePattern = fs.readFileSync(require.resolve('./keystroke-pattern.pegjs'), 'utf8')
|
||||
BindingSet.parser ?= PEG.buildParser(keystrokePattern)
|
||||
@specificity = specificity(selector)
|
||||
@selector = selector.replace(/!important/g, '')
|
||||
@commandsByKeystrokes = @normalizeCommandsByKeystrokes(commandsByKeystrokes)
|
||||
|
||||
# Private:
|
||||
getName: ->
|
||||
@name
|
||||
|
||||
# Private:
|
||||
getSelector: ->
|
||||
@selector
|
||||
|
||||
# Private:
|
||||
getCommandsByKeystrokes: ->
|
||||
@commandsByKeystrokes
|
||||
|
||||
commandForEvent: (event) ->
|
||||
for keystrokes, command of @commandsByKeystrokes
|
||||
return command if event.keystrokes == keystrokes
|
||||
null
|
||||
|
||||
matchesKeystrokePrefix: (event) ->
|
||||
eventKeystrokes = event.keystrokes.split(' ')
|
||||
for keystrokes, command of @commandsByKeystrokes
|
||||
bindingKeystrokes = keystrokes.split(' ')
|
||||
continue unless eventKeystrokes.length < bindingKeystrokes.length
|
||||
return true if _.isEqual(eventKeystrokes, bindingKeystrokes[0...eventKeystrokes.length])
|
||||
false
|
||||
|
||||
normalizeCommandsByKeystrokes: (commandsByKeystrokes) ->
|
||||
normalizedCommandsByKeystrokes = {}
|
||||
for keystrokes, command of commandsByKeystrokes
|
||||
normalizedCommandsByKeystrokes[@normalizeKeystrokes(keystrokes)] = command
|
||||
normalizedCommandsByKeystrokes
|
||||
|
||||
normalizeKeystrokes: (keystrokes) ->
|
||||
normalizedKeystrokes = keystrokes.split(/\s+/).map (keystroke) =>
|
||||
@normalizeKeystroke(keystroke)
|
||||
normalizedKeystrokes.join(' ')
|
||||
|
||||
normalizeKeystroke: (keystroke) ->
|
||||
keys = BindingSet.parser.parse(keystroke)
|
||||
modifiers = keys[0...-1]
|
||||
modifiers.sort()
|
||||
[modifiers..., _.last(keys)].join('-')
|
||||
@@ -22,7 +22,7 @@ class ApplicationMenu
|
||||
# The Object which describes the menu to display.
|
||||
# * keystrokesByCommand:
|
||||
# An Object where the keys are commands and the values are Arrays containing
|
||||
# the keystrokes.
|
||||
# the keystroke.
|
||||
update: (template, keystrokesByCommand) ->
|
||||
@translateTemplate(template, keystrokesByCommand)
|
||||
@substituteVersion(template)
|
||||
@@ -97,14 +97,14 @@ class ApplicationMenu
|
||||
]
|
||||
]
|
||||
|
||||
# Private: Combines a menu template with the appropriate keystrokes.
|
||||
# Private: Combines a menu template with the appropriate keystroke.
|
||||
#
|
||||
# * template:
|
||||
# An Object conforming to atom-shell's menu api but lacking accelerator and
|
||||
# click properties.
|
||||
# * keystrokesByCommand:
|
||||
# An Object where the keys are commands and the values are Arrays containing
|
||||
# the keystrokes.
|
||||
# the keystroke.
|
||||
#
|
||||
# Returns a complete menu configuration object for atom-shell's menu API.
|
||||
translateTemplate: (template, keystrokesByCommand) ->
|
||||
@@ -123,15 +123,15 @@ class ApplicationMenu
|
||||
# The name of the command.
|
||||
# * keystrokesByCommand:
|
||||
# An Object where the keys are commands and the values are Arrays containing
|
||||
# the keystrokes.
|
||||
# the keystroke.
|
||||
#
|
||||
# Returns a String containing the keystroke in a format that can be interpreted
|
||||
# by atom shell to provide nice icons where available.
|
||||
acceleratorForCommand: (command, keystrokesByCommand) ->
|
||||
keystroke = keystrokesByCommand[command]?[0]
|
||||
return null unless keystroke
|
||||
firstKeystroke = keystrokesByCommand[command]?[0]
|
||||
return null unless firstKeystroke
|
||||
|
||||
modifiers = keystroke.split('-')
|
||||
modifiers = firstKeystroke.split('-')
|
||||
key = modifiers.pop()
|
||||
|
||||
modifiers.push("Shift") if key != key.toLowerCase()
|
||||
|
||||
@@ -1806,13 +1806,6 @@ class Editor extends View
|
||||
else
|
||||
' '
|
||||
|
||||
bindToKeyedEvent: (key, event, callback) ->
|
||||
binding = {}
|
||||
binding[key] = event
|
||||
atom.keymap.bindKeys '.editor', binding
|
||||
@on event, =>
|
||||
callback(this, event)
|
||||
|
||||
replaceSelectedText: (replaceFn) ->
|
||||
selection = @getSelection()
|
||||
return false if selection.isEmpty()
|
||||
|
||||
48
src/key-binding.coffee
Normal file
48
src/key-binding.coffee
Normal file
@@ -0,0 +1,48 @@
|
||||
{$} = require './space-pen-extensions'
|
||||
_ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
{specificity} = require 'clear-cut'
|
||||
PEG = require 'pegjs'
|
||||
|
||||
### Internal ###
|
||||
|
||||
module.exports =
|
||||
class KeyBinding
|
||||
@parser: null
|
||||
@currentIndex: 1
|
||||
|
||||
@normalizeKeystroke: (keystroke) ->
|
||||
normalizedKeystroke = keystroke.split(/\s+/).map (keystroke) =>
|
||||
keys = @getParser().parse(keystroke)
|
||||
modifiers = keys[0...-1]
|
||||
modifiers.sort()
|
||||
[modifiers..., _.last(keys)].join('-')
|
||||
normalizedKeystroke.join(' ')
|
||||
|
||||
@getParser: ->
|
||||
if not KeyBinding.parser
|
||||
keystrokePattern = fs.readFileSync(require.resolve('./keystroke-pattern.pegjs'), 'utf8')
|
||||
KeyBinding.parser = PEG.buildParser(keystrokePattern)
|
||||
|
||||
KeyBinding.parser
|
||||
|
||||
constructor: (source, command, keystroke, selector) ->
|
||||
@source = source
|
||||
@command = command
|
||||
@keystroke = KeyBinding.normalizeKeystroke(keystroke)
|
||||
@selector = selector.replace(/!important/g, '')
|
||||
@specificity = specificity(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
|
||||
@@ -3,7 +3,7 @@ _ = require 'underscore-plus'
|
||||
fs = require 'fs-plus'
|
||||
path = require 'path'
|
||||
CSON = require 'season'
|
||||
BindingSet = require './binding-set'
|
||||
KeyBinding = require './key-binding'
|
||||
{Emitter} = require 'emissary'
|
||||
|
||||
Modifiers = ['alt', 'control', 'ctrl', 'shift', 'meta']
|
||||
@@ -25,166 +25,46 @@ module.exports =
|
||||
class Keymap
|
||||
Emitter.includeInto(this)
|
||||
|
||||
bindingSets: null
|
||||
nextBindingSetIndex: 0
|
||||
bindingSetsByFirstKeystroke: null
|
||||
queuedKeystrokes: null
|
||||
|
||||
constructor: ({@resourcePath, @configDirPath})->
|
||||
@bindingSets = []
|
||||
@bindingSetsByFirstKeystroke = {}
|
||||
@keyBindings = []
|
||||
|
||||
loadBundledKeymaps: ->
|
||||
@loadDirectory(path.join(@resourcePath, 'keymaps'))
|
||||
@emit('bundled-keymaps-loaded')
|
||||
# Public: Returns an array of all {KeyBinding}s.
|
||||
getKeyBindings: ->
|
||||
_.clone(@keyBindings)
|
||||
|
||||
loadUserKeymap: ->
|
||||
userKeymapPath = CSON.resolve(path.join(@configDirPath, 'keymap'))
|
||||
@load(userKeymapPath) if userKeymapPath
|
||||
|
||||
loadDirectory: (directoryPath) ->
|
||||
@load(filePath) for filePath in fs.listSync(directoryPath, ['.cson', '.json'])
|
||||
|
||||
load: (path) ->
|
||||
@add(path, CSON.readFileSync(path))
|
||||
|
||||
add: (args...) ->
|
||||
name = args.shift() if args.length > 1
|
||||
keymap = args.shift()
|
||||
for selector, bindings of keymap
|
||||
@bindKeys(name, selector, bindings)
|
||||
|
||||
remove: (name) ->
|
||||
for bindingSet in @bindingSets.filter((bindingSet) -> bindingSet.name is name)
|
||||
_.remove(@bindingSets, bindingSet)
|
||||
for keystrokes of bindingSet.commandsByKeystrokes
|
||||
keystroke = keystrokes.split(' ')[0]
|
||||
_.remove(@bindingSetsByFirstKeystroke[keystroke], bindingSet)
|
||||
|
||||
# Public: Returns an array of objects that represent every keystroke to
|
||||
# command mapping. Each object contains the following keys `source`,
|
||||
# `selector`, `command`, `keystrokes`.
|
||||
getAllKeyMappings: ->
|
||||
mappings = []
|
||||
for bindingSet in @bindingSets
|
||||
selector = bindingSet.getSelector()
|
||||
source = @determineSource(bindingSet.getName())
|
||||
for keystrokes, command of bindingSet.getCommandsByKeystrokes()
|
||||
mappings.push {keystrokes, command, selector, source}
|
||||
|
||||
mappings
|
||||
|
||||
# Private: Returns a user friendly description of where a keybinding was
|
||||
# loaded from.
|
||||
# Public: Returns a array of {KeyBinding}s (sorted by selector specificity)
|
||||
# that match a keystroke and element.
|
||||
#
|
||||
# * filePath:
|
||||
# The absolute path from which the keymap was loaded
|
||||
# * keystroke:
|
||||
# The string representing the keys pressed (e.g. ctrl-P).
|
||||
# * element:
|
||||
# The DOM node that will match a {KeyBinding}'s selector.
|
||||
keyBindingsForKeystrokeMatchingElement: (keystroke, element) ->
|
||||
keyBindings = @keyBindingsForKeystroke(keystroke)
|
||||
@keyBindingsMatchingElement(element, keyBindings)
|
||||
|
||||
# Public: Returns an array of {KeyBinding}s that match a keystroke
|
||||
# * keystroke:
|
||||
# The string representing the keys pressed (e.g. ctrl-P)
|
||||
keyBindingsForKeystroke: (keystroke) ->
|
||||
keystroke = KeyBinding.normalizeKeystroke(keystroke)
|
||||
keyBindings = @keyBindings.filter (keyBinding) -> keyBinding.matches(keystroke)
|
||||
|
||||
# Public: Returns a array of {KeyBinding}s (sorted by selector specificity)
|
||||
# whos selector matches the element.
|
||||
#
|
||||
# Returns one of:
|
||||
# * `Core` indicates it comes from a bundled package.
|
||||
# * `User` indicates that it was defined by a user.
|
||||
# * `<package-name>` the package which defined it.
|
||||
# * `Unknown` if an invalid path was passed in.
|
||||
determineSource: (filePath) ->
|
||||
return 'Unknown' unless filePath
|
||||
# * element:
|
||||
# The DOM node that will match a {KeyBinding}'s selector.
|
||||
keyBindingsMatchingElement: (element, keyBindings=@keyBindings) ->
|
||||
keyBindings = keyBindings.filter ({selector}) -> $(element).closest(selector).length > 0
|
||||
keyBindings.sort (a, b) -> a.compare(b)
|
||||
|
||||
pathParts = filePath.split(path.sep)
|
||||
if _.contains(pathParts, 'node_modules') or _.contains(pathParts, 'atom') or _.contains(pathParts, 'src')
|
||||
'Core'
|
||||
else if _.contains(pathParts, '.atom') and _.contains(pathParts, 'keymaps') and !_.contains(pathParts, 'packages')
|
||||
'User'
|
||||
else
|
||||
packageNameIndex = pathParts.length - 3
|
||||
pathParts[packageNameIndex]
|
||||
|
||||
bindKeys: (args...) ->
|
||||
name = args.shift() if args.length > 2
|
||||
[selector, bindings] = args
|
||||
bindingSet = new BindingSet(selector, bindings, @nextBindingSetIndex++, name)
|
||||
@bindingSets.unshift(bindingSet)
|
||||
for keystrokes of bindingSet.commandsByKeystrokes
|
||||
keystroke = keystrokes.split(' ')[0] # only index by first keystroke
|
||||
@bindingSetsByFirstKeystroke[keystroke] ?= []
|
||||
@bindingSetsByFirstKeystroke[keystroke].push(bindingSet)
|
||||
|
||||
unbindKeys: (selector, bindings) ->
|
||||
bindingSet = _.detect @bindingSets, (bindingSet) ->
|
||||
bindingSet.selector is selector and bindingSet.bindings is bindings
|
||||
|
||||
if bindingSet
|
||||
_.remove(@bindingSets, 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 is 'native!'
|
||||
return true
|
||||
else 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
|
||||
if currentKeystroke in Modifiers
|
||||
@queuedKeystrokes
|
||||
else
|
||||
@queuedKeystrokes + ' ' + currentKeystroke
|
||||
else
|
||||
currentKeystroke
|
||||
|
||||
keystrokeStringForEvent: (event) ->
|
||||
# Public: Returns a keystroke string derived from an event.
|
||||
# * event:
|
||||
# A DOM or jQuery event
|
||||
# * previousKeystroke:
|
||||
# An optional string used for multiKeystrokes
|
||||
keystrokeStringForEvent: (event, previousKeystroke) ->
|
||||
if event.originalEvent.keyIdentifier.indexOf('U+') == 0
|
||||
hexCharCode = event.originalEvent.keyIdentifier[2..]
|
||||
charCode = parseInt(hexCharCode, 16)
|
||||
@@ -207,16 +87,73 @@ class Keymap
|
||||
else
|
||||
key = key.toLowerCase()
|
||||
|
||||
[modifiers..., key].join('-')
|
||||
keystroke = [modifiers..., key].join('-')
|
||||
|
||||
keystrokesByCommandForSelector: (selector)->
|
||||
keystrokesByCommand = {}
|
||||
for bindingSet in @bindingSets
|
||||
for keystroke, command of bindingSet.commandsByKeystrokes
|
||||
continue if selector? and selector != bindingSet.selector
|
||||
keystrokesByCommand[command] ?= []
|
||||
keystrokesByCommand[command].push keystroke
|
||||
keystrokesByCommand
|
||||
if previousKeystroke
|
||||
if keystroke in Modifiers
|
||||
previousKeystroke
|
||||
else
|
||||
"#{previousKeystroke} #{keystroke}"
|
||||
else
|
||||
keystroke
|
||||
|
||||
loadBundledKeymaps: ->
|
||||
@loadDirectory(path.join(@resourcePath, 'keymaps'))
|
||||
@emit('bundled-keymaps-loaded')
|
||||
|
||||
loadUserKeymap: ->
|
||||
userKeymapPath = CSON.resolve(path.join(@configDirPath, 'keymap'))
|
||||
@load(userKeymapPath) if userKeymapPath
|
||||
|
||||
loadDirectory: (directoryPath) ->
|
||||
@load(filePath) for filePath in fs.listSync(directoryPath, ['.cson', '.json'])
|
||||
|
||||
load: (path) ->
|
||||
@add(path, CSON.readFileSync(path))
|
||||
|
||||
add: (source, keyMappingsBySelector) ->
|
||||
for selector, keyMappings of keyMappingsBySelector
|
||||
@bindKeys(source, selector, keyMappings)
|
||||
|
||||
remove: (source) ->
|
||||
@keyBindings = @keyBindings.filter (keyBinding) -> keyBinding.source isnt source
|
||||
|
||||
bindKeys: (source, selector, keyMappings) ->
|
||||
for keystroke, command of keyMappings
|
||||
@keyBindings.push new KeyBinding(source, command, keystroke, selector)
|
||||
|
||||
handleKeyEvent: (event) ->
|
||||
element = event.target
|
||||
element = rootView if element == document.body
|
||||
keystroke = @keystrokeStringForEvent(event, @queuedKeystroke)
|
||||
keyBindings = @keyBindingsForKeystrokeMatchingElement(keystroke, element)
|
||||
|
||||
if keyBindings.length == 0 and @queuedKeystroke
|
||||
@queuedKeystroke = null
|
||||
return false
|
||||
else
|
||||
@queuedKeystroke = null
|
||||
|
||||
for keyBinding in keyBindings
|
||||
partialMatch = keyBinding.keystroke isnt keystroke
|
||||
if partialMatch
|
||||
@queuedKeystroke = keystroke
|
||||
shouldBubble = false
|
||||
else
|
||||
if keyBinding.command is 'native!'
|
||||
shouldBubble = true
|
||||
else if @triggerCommandEvent(element, keyBinding.command)
|
||||
shouldBubble = false
|
||||
|
||||
break if shouldBubble?
|
||||
|
||||
shouldBubble ? true
|
||||
|
||||
triggerCommandEvent: (element, commandName) ->
|
||||
commandEvent = $.Event(commandName)
|
||||
commandEvent.abortKeyBinding = -> commandEvent.stopImmediatePropagation()
|
||||
$(element).trigger(commandEvent)
|
||||
not commandEvent.isImmediatePropagationStopped()
|
||||
|
||||
isAscii: (charCode) ->
|
||||
0 <= charCode <= 127
|
||||
|
||||
@@ -29,9 +29,11 @@ class MenuManager
|
||||
|
||||
# Public: Refreshes the currently visible menu.
|
||||
update: ->
|
||||
keystrokesByCommand = atom.keymap.keystrokesByCommandForSelector('body')
|
||||
_.extend(keystrokesByCommand, atom.keymap.keystrokesByCommandForSelector('.editor'))
|
||||
_.extend(keystrokesByCommand, atom.keymap.keystrokesByCommandForSelector('.editor:not(.mini)'))
|
||||
keystrokesByCommand = {}
|
||||
selectors = ['body', '.editor', '.editor:not(.mini)']
|
||||
for binding in atom.keymap.getKeyBindings() when binding.selector in selectors
|
||||
keystrokesByCommand[binding.command] ?= []
|
||||
keystrokesByCommand[binding.command].push binding.keystroke
|
||||
@sendToBrowserProcess(@template, keystrokesByCommand)
|
||||
|
||||
# Private
|
||||
@@ -55,7 +57,7 @@ class MenuManager
|
||||
# Private: OSX can't handle displaying accelerators for multiple keystrokes.
|
||||
# If they are sent across, it will stop processing accelerators for the rest
|
||||
# of the menu items.
|
||||
filterMultipleKeystrokes: (keystrokesByCommand) ->
|
||||
filterMultipleKeystroke: (keystrokesByCommand) ->
|
||||
filtered = {}
|
||||
for key, bindings of keystrokesByCommand
|
||||
for binding in bindings
|
||||
@@ -67,5 +69,5 @@ class MenuManager
|
||||
|
||||
# Private
|
||||
sendToBrowserProcess: (template, keystrokesByCommand) ->
|
||||
keystrokesByCommand = @filterMultipleKeystrokes(keystrokesByCommand)
|
||||
keystrokesByCommand = @filterMultipleKeystroke(keystrokesByCommand)
|
||||
ipc.sendChannel 'update-application-menu', template, keystrokesByCommand
|
||||
|
||||
@@ -54,7 +54,8 @@ class WindowEventHandler
|
||||
|
||||
@subscribeToCommand $(document), 'core:focus-previous', @focusPrevious
|
||||
|
||||
@subscribe $(document), 'keydown', atom.keymap.handleKeyEvent
|
||||
@subscribe $(document), 'keydown', (event) ->
|
||||
atom.keymap.handleKeyEvent(event)
|
||||
|
||||
@subscribe $(document), 'drop', (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
Reference in New Issue
Block a user