From 2d6ddcedfdbf5f457f911701db8661a9d27af0f7 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Thu, 22 Dec 2011 16:24:09 -0800 Subject: [PATCH] Add window.bindKey which matches a pattern to an action. --- spec/atom/window-spec.coffee | 47 ++++++++++++++++++++++++++++++++++++ spec/spec-helper.coffee | 8 +++--- src/atom/window.coffee | 32 ++++++++++++++++++------ 3 files changed, 77 insertions(+), 10 deletions(-) diff --git a/spec/atom/window-spec.coffee b/spec/atom/window-spec.coffee index bad4cc78d..1d89f5ed7 100644 --- a/spec/atom/window-spec.coffee +++ b/spec/atom/window-spec.coffee @@ -8,6 +8,53 @@ describe "Window", -> afterEach -> window.shutdown() + describe 'bindKey', -> + it 'maps keypresses that match a pattern to an action', -> + action1 = jasmine.createSpy 'action1' + action2 = jasmine.createSpy 'action2' + + window.bindKey 'meta+1', action1 + window.bindKey 'meta+2', action2 + + window.keydown 'meta+1' + expect(action1).toHaveBeenCalled() + expect(action2).not.toHaveBeenCalled() + action1.reset() + + window.keydown 'meta+2' + expect(action1).not.toHaveBeenCalled() + expect(action2).toHaveBeenCalled() + action2.reset() + + window.keydown 'meta+3' + expect(action1).not.toHaveBeenCalled() + expect(action2).not.toHaveBeenCalled() + + describe 'keyEventMatchesPattern', -> + it 'returns true if the modifiers and letter in the pattern match the key event', -> + expectMatch = (pattern) -> + expect(window.keyEventMatchesPattern(window.createKeyEvent(pattern), pattern)).toBeTruthy() + + expectNoMatch = (eventPattern, patternToTest) -> + event = window.createKeyEvent(eventPattern) + expect(window.keyEventMatchesPattern(event, patternToTest)).toBeFalsy() + + expectMatch 'meta+a' + expectMatch 'meta+1' + expectMatch 'alt+1' + expectMatch 'ctrl+1' + expectMatch 'shift+1' + expectMatch 'shift+a' + expectMatch 'meta+alt+1' + expectMatch 'meta+alt+ctrl+1' + expectMatch 'meta+alt+ctrl+shift+1' + + expectNoMatch 'meta+alt+ctrl+shift+1', 'meta+1' + expectNoMatch 'meta+1', 'meta+alt+1' + expectNoMatch 'meta+a', 'meta+b' + expectNoMatch 'meta+a', 'meta+b' + expectNoMatch 'meta+1', 'alt+1' + describe 'meta+s', -> it 'saves the buffer', -> spyOn(window.editor, 'save') diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 67980e7ae..3b3b4a0c7 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -4,13 +4,15 @@ _ = require 'underscore' window.atom = new (require 'app') window.keydown = (pattern) -> + + $(document).trigger @createKeyEvent pattern + +window.createKeyEvent = (pattern) -> keys = pattern.split '+' - event = $.Event "keydown", + $.Event "keydown", ctrlKey: 'ctrl' in keys altKey: 'alt' in keys shiftKey: 'shift' in keys metaKey: 'meta' in keys which: _.last(keys).toUpperCase().charCodeAt 0 - $(document).trigger event - diff --git a/src/atom/window.coffee b/src/atom/window.coffee index 1baa74c0b..699d2be1d 100644 --- a/src/atom/window.coffee +++ b/src/atom/window.coffee @@ -10,26 +10,44 @@ Editor = require 'editor' windowAdditions = editor: null + keyBindings: null layout: null startup: -> + @keyBindings = {} @layout = Layout.attach() @editor = new Editor $atomController.url?.toString() + @registerKeydownHandler() @bindKeys() shutdown: -> @layout.remove() @editor.shutdown() - @unbindKeys() bindKeys: -> - $(document).bind 'keydown', (event) => - if String.fromCharCode(event.which) == 'S' and event.metaKey - @editor.save() - false + @bindKey 'meta+s', => @editor.save() - unbindKeys: -> - $(document).unbind 'keydown' + bindKey: (pattern, action) -> + @keyBindings[pattern] = action + + keyEventMatchesPattern: (event, pattern) -> + [modifiers..., key] = pattern.split '+' + patternModifiers = + ctrlKey: 'ctrl' in modifiers + altKey: 'alt' in modifiers + shiftKey: 'shift' in modifiers + metaKey: 'meta' in modifiers + + patternModifiers.ctrlKey == event.ctrlKey and + patternModifiers.altKey == event.altKey and + patternModifiers.shiftKey == event.shiftKey and + patternModifiers.metaKey == event.metaKey and + event.which == key.toUpperCase().charCodeAt 0 + + registerKeydownHandler: -> + $(document).bind 'keydown', (event) => + for pattern, action of @keyBindings + action() if @keyEventMatchesPattern(event, pattern) showConsole: -> $atomController.webView.inspector.showConsole true