From 92bb9ca6afb2ef70946f4a8e15208f14778423b7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 6 Sep 2016 15:41:55 -0600 Subject: [PATCH 01/24] Update dependencies --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 1d683c6..4f05fde 100644 --- a/package.json +++ b/package.json @@ -43,8 +43,8 @@ "coffee-script": "1.7.0", "coffeelint": "1.14.2", "debounce": "1.0.0", - "devtool": "1.9.1", - "electron-rebuild": "1.1.3", + "devtool": "2.2.0", + "electron-rebuild": "1.2.1", "eslint": "2.2.0", "eslint-config-standard": "5.1.0", "eslint-plugin-promise": "1.0.8", @@ -55,7 +55,6 @@ "grunt-coffeelint": "0.0.6", "grunt-contrib-coffee": "0.9.0", "grunt-shell": "0.2.2", - "jasmine-focused": "1.0.4", "lolex": "1.4.0", "mocha": "2.4.5", "rimraf": "2.2.2", From cd17867847afddaecc70ccadf917576ed971a800 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 7 Sep 2016 17:31:19 -0600 Subject: [PATCH 02/24] WIP: Use KeyboardLayout module to translate keyboard events with the .code property to keystrokes --- spec/helpers/dvorak-keymap.js | 380 ++++++++++++++++++++++++++++++++ spec/keymap-manager-spec.coffee | 133 +++-------- src/helpers.coffee | 158 ++++--------- 3 files changed, 458 insertions(+), 213 deletions(-) create mode 100644 spec/helpers/dvorak-keymap.js diff --git a/spec/helpers/dvorak-keymap.js b/spec/helpers/dvorak-keymap.js new file mode 100644 index 0000000..89fa3de --- /dev/null +++ b/spec/helpers/dvorak-keymap.js @@ -0,0 +1,380 @@ +module.exports = { + "Space": { + "unmodified": " ", + "withShift": " ", + "withAltGr": " ", + "withShiftAltGr": " " + }, + "Digit0": { + "unmodified": "0", + "withShift": ")", + "withAltGr": "º", + "withShiftAltGr": "‚" + }, + "Digit1": { + "unmodified": "1", + "withShift": "!", + "withAltGr": "¡", + "withShiftAltGr": "⁄" + }, + "Digit2": { + "unmodified": "2", + "withShift": "@", + "withAltGr": "™", + "withShiftAltGr": "€" + }, + "Digit3": { + "unmodified": "3", + "withShift": "#", + "withAltGr": "£", + "withShiftAltGr": "‹" + }, + "Digit4": { + "unmodified": "4", + "withShift": "$", + "withAltGr": "¢", + "withShiftAltGr": "›" + }, + "Digit5": { + "unmodified": "5", + "withShift": "%", + "withAltGr": "∞", + "withShiftAltGr": "fi" + }, + "Digit6": { + "unmodified": "6", + "withShift": "^", + "withAltGr": "§", + "withShiftAltGr": "fl" + }, + "Digit7": { + "unmodified": "7", + "withShift": "&", + "withAltGr": "¶", + "withShiftAltGr": "‡" + }, + "Digit8": { + "unmodified": "8", + "withShift": "*", + "withAltGr": "•", + "withShiftAltGr": "°" + }, + "Digit9": { + "unmodified": "9", + "withShift": "(", + "withAltGr": "ª", + "withShiftAltGr": "·" + }, + "KeyA": { + "unmodified": "a", + "withShift": "A", + "withAltGr": "å", + "withShiftAltGr": "Å" + }, + "KeyB": { + "unmodified": "x", + "withShift": "X", + "withAltGr": "≈", + "withShiftAltGr": "˛" + }, + "KeyC": { + "unmodified": "j", + "withShift": "J", + "withAltGr": "∆", + "withShiftAltGr": "Ô" + }, + "KeyD": { + "unmodified": "e", + "withShift": "E", + "withAltGr": "", + "withShiftAltGr": "´" + }, + "KeyE": { + "unmodified": ".", + "withShift": ">", + "withAltGr": "≥", + "withShiftAltGr": "˘" + }, + "KeyF": { + "unmodified": "u", + "withShift": "U", + "withAltGr": "", + "withShiftAltGr": "¨" + }, + "KeyG": { + "unmodified": "i", + "withShift": "I", + "withAltGr": "", + "withShiftAltGr": "ˆ" + }, + "KeyH": { + "unmodified": "d", + "withShift": "D", + "withAltGr": "∂", + "withShiftAltGr": "Î" + }, + "KeyI": { + "unmodified": "c", + "withShift": "C", + "withAltGr": "ç", + "withShiftAltGr": "Ç" + }, + "KeyJ": { + "unmodified": "h", + "withShift": "H", + "withAltGr": "˙", + "withShiftAltGr": "Ó" + }, + "KeyK": { + "unmodified": "t", + "withShift": "T", + "withAltGr": "†", + "withShiftAltGr": "ˇ" + }, + "KeyL": { + "unmodified": "n", + "withShift": "N", + "withAltGr": "", + "withShiftAltGr": "˜" + }, + "KeyM": { + "unmodified": "m", + "withShift": "M", + "withAltGr": "µ", + "withShiftAltGr": "Â" + }, + "KeyN": { + "unmodified": "b", + "withShift": "B", + "withAltGr": "∫", + "withShiftAltGr": "ı" + }, + "KeyO": { + "unmodified": "r", + "withShift": "R", + "withAltGr": "®", + "withShiftAltGr": "‰" + }, + "KeyP": { + "unmodified": "l", + "withShift": "L", + "withAltGr": "¬", + "withShiftAltGr": "Ò" + }, + "KeyQ": { + "unmodified": "'", + "withShift": "\"", + "withAltGr": "æ", + "withShiftAltGr": "Æ" + }, + "KeyR": { + "unmodified": "p", + "withShift": "P", + "withAltGr": "π", + "withShiftAltGr": "∏" + }, + "KeyS": { + "unmodified": "o", + "withShift": "O", + "withAltGr": "ø", + "withShiftAltGr": "Ø" + }, + "KeyT": { + "unmodified": "y", + "withShift": "Y", + "withAltGr": "¥", + "withShiftAltGr": "Á" + }, + "KeyU": { + "unmodified": "g", + "withShift": "G", + "withAltGr": "©", + "withShiftAltGr": "˝" + }, + "KeyV": { + "unmodified": "k", + "withShift": "K", + "withAltGr": "˚", + "withShiftAltGr": "" + }, + "KeyW": { + "unmodified": ",", + "withShift": "<", + "withAltGr": "≤", + "withShiftAltGr": "¯" + }, + "KeyX": { + "unmodified": "q", + "withShift": "Q", + "withAltGr": "œ", + "withShiftAltGr": "Œ" + }, + "KeyY": { + "unmodified": "f", + "withShift": "F", + "withAltGr": "ƒ", + "withShiftAltGr": "Ï" + }, + "KeyZ": { + "unmodified": ";", + "withShift": ":", + "withAltGr": "…", + "withShiftAltGr": "Ú" + }, + "Numpad0": { + "unmodified": "0", + "withShift": "0", + "withAltGr": "0", + "withShiftAltGr": "0" + }, + "Numpad1": { + "unmodified": "1", + "withShift": "1", + "withAltGr": "1", + "withShiftAltGr": "1" + }, + "Numpad2": { + "unmodified": "2", + "withShift": "2", + "withAltGr": "2", + "withShiftAltGr": "2" + }, + "Numpad3": { + "unmodified": "3", + "withShift": "3", + "withAltGr": "3", + "withShiftAltGr": "3" + }, + "Numpad4": { + "unmodified": "4", + "withShift": "4", + "withAltGr": "4", + "withShiftAltGr": "4" + }, + "Numpad5": { + "unmodified": "5", + "withShift": "5", + "withAltGr": "5", + "withShiftAltGr": "5" + }, + "Numpad6": { + "unmodified": "6", + "withShift": "6", + "withAltGr": "6", + "withShiftAltGr": "6" + }, + "Numpad7": { + "unmodified": "7", + "withShift": "7", + "withAltGr": "7", + "withShiftAltGr": "7" + }, + "Numpad8": { + "unmodified": "8", + "withShift": "8", + "withAltGr": "8", + "withShiftAltGr": "8" + }, + "Numpad9": { + "unmodified": "9", + "withShift": "9", + "withAltGr": "9", + "withShiftAltGr": "9" + }, + "NumpadMultiply": { + "unmodified": "*", + "withShift": "*", + "withAltGr": "*", + "withShiftAltGr": "*" + }, + "NumpadAdd": { + "unmodified": "+", + "withShift": "+", + "withAltGr": "+", + "withShiftAltGr": "+" + }, + "NumpadSubtract": { + "unmodified": "-", + "withShift": "-", + "withAltGr": "-", + "withShiftAltGr": "-" + }, + "NumpadDecimal": { + "unmodified": ".", + "withShift": ".", + "withAltGr": ".", + "withShiftAltGr": "." + }, + "NumpadDivide": { + "unmodified": "/", + "withShift": "/", + "withAltGr": "/", + "withShiftAltGr": "/" + }, + "Semicolon": { + "unmodified": "s", + "withShift": "S", + "withAltGr": "ß", + "withShiftAltGr": "Í" + }, + "Equal": { + "unmodified": "]", + "withShift": "}", + "withAltGr": "‘", + "withShiftAltGr": "’" + }, + "NumpadComma": { + "unmodified": "w", + "withShift": "W", + "withAltGr": "∑", + "withShiftAltGr": "„" + }, + "Minus": { + "unmodified": "[", + "withShift": "{", + "withAltGr": "“", + "withShiftAltGr": "”" + }, + "Period": { + "unmodified": "v", + "withShift": "V", + "withAltGr": "√", + "withShiftAltGr": "◊" + }, + "Slash": { + "unmodified": "z", + "withShift": "Z", + "withAltGr": "Ω", + "withShiftAltGr": "¸" + }, + "Backquote": { + "unmodified": "`", + "withShift": "~", + "withAltGr": "", + "withShiftAltGr": "`" + }, + "BracketLeft": { + "unmodified": "/", + "withShift": "?", + "withAltGr": "÷", + "withShiftAltGr": "¿" + }, + "IntlYen": { + "unmodified": "\\", + "withShift": "|", + "withAltGr": "«", + "withShiftAltGr": "»" + }, + "BracketRight": { + "unmodified": "=", + "withShift": "+", + "withAltGr": "≠", + "withShiftAltGr": "±" + }, + "Quote": { + "unmodified": "-", + "withShift": "_", + "withAltGr": "–", + "withShiftAltGr": "—" + } +} diff --git a/spec/keymap-manager-spec.coffee b/spec/keymap-manager-spec.coffee index bdf2dca..0598ce5 100644 --- a/spec/keymap-manager-spec.coffee +++ b/spec/keymap-manager-spec.coffee @@ -579,122 +579,47 @@ describe "KeymapManager", -> assert.equal(keymapManager.findKeyBindings(command: 'y').length, 1) assert.equal(keymapManager.findKeyBindings(command: 'z').length, 0) - describe "::keystrokeForKeyboardEvent(event)", -> - describe "when no modifiers are pressed", -> + describe.only "::keystrokeForKeyboardEvent(event)", -> + KeyboardLayout = require('keyboard-layout') + currentKeymap = null + + beforeEach -> + currentKeymap = null + stub(KeyboardLayout, 'charactersForKeyCode', (code) -> currentKeymap[code]) + + describe "when no extra modifiers are pressed", -> it "returns a string that identifies the unmodified keystroke", -> - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('a')), 'a') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('[')), '[') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('*')), '*') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('left')), 'left') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('\b')), 'backspace') + currentKeymap = require('./helpers/dvorak-keymap') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyA'}), 'a') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Minus'}), '[') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Digit8', shiftKey: true}), '*') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'ArrowLeft'}), 'left') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Backspace'}), 'backspace') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'delete'}), 'delete') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'PageUp'}), 'pageup') describe "when a modifier key is combined with a non-modifier key", -> it "returns a string that identifies the modified keystroke", -> - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('a', alt: true)), 'alt-a') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('[', cmd: true)), 'cmd-[') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('*', ctrl: true)), 'ctrl-*') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('left', ctrl: true, alt: true, cmd: true)), 'ctrl-alt-cmd-left') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('A', shift: true)), 'shift-A') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('a', ctrl: true, shift: true)), 'ctrl-shift-A') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('{', shift: true)), '{') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('left', shift: true)), 'shift-left') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('Left', shift: true)), 'shift-left') + currentKeymap = require('./helpers/dvorak-keymap') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyA', altKey: true}), 'alt-a') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Minus', metaKey: true}), 'cmd-[') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Digit8', ctrlKey: true, shiftKey: true}), 'ctrl-*') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'ArrowLeft', ctrlKey: true, altKey: true, metaKey: true}), 'ctrl-alt-cmd-left') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyA', shiftKey: true}), 'shift-A') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyA', ctrlKey: true, shiftKey: true}), 'ctrl-shift-A') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Minus', shiftKey: true}), '{') describe "when a numpad key is pressed", -> it "returns a string that identifies the key as the appropriate num-key", -> - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0041', keyCode: 97, location: 3)), '1') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0045', keyCode: 101, location: 3)), '5') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0049', keyCode: 105, location: 3)), '9') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('PageDown', keyCode: 34, location: 3)), 'pagedown') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('PageUp', keyCode: 33, location: 3)), 'pageup') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+004B', keyCode: 107, location: 3)), '+') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+007F', keyCode: 46, location: 3)), 'delete') + currentKeymap = require('./helpers/dvorak-keymap') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Numpad1'}), '1') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Numpad5'}), '5') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'NumpadAdd'}), '+') 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", -> assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+03B6', cmd: true, keyCode: 122)), 'cmd-z') - describe "when KeymapManager::dvorakQwertyWorkaroundEnabled is true", -> - it "uses event.keyCode instead of event.keyIdentifier when event.keyIdentifier is numeric", -> - keymapManager.dvorakQwertyWorkaroundEnabled = true - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+004A', cmd: true, keyCode: 67)), 'cmd-c') - - it "maps the keyCode for delete (46) to the ASCII code for delete (127)", -> - keymapManager.dvorakQwertyWorkaroundEnabled = true - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+007F', keyCode: 46)), 'delete') - - describe "on Windows and Linux", -> - originalPlatform = null - - beforeEach -> - originalPlatform = process.platform - - afterEach -> - Object.defineProperty process, 'platform', value: originalPlatform - - it "corrects a Chromium bug where the keyIdentifier is incorrect for certain keypress events", -> - testTranslations = -> - # Number row - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0030', ctrl: true)), 'ctrl-0') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0031', ctrl: true)), 'ctrl-1') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0032', ctrl: true)), 'ctrl-2') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0033', ctrl: true)), 'ctrl-3') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0034', ctrl: true)), 'ctrl-4') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0035', ctrl: true)), 'ctrl-5') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0036', ctrl: true)), 'ctrl-6') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0037', ctrl: true)), 'ctrl-7') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0038', ctrl: true)), 'ctrl-8') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0039', ctrl: true)), 'ctrl-9') - - # Number row shifted - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0030', ctrl: true, shift: true)), 'ctrl-)') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0031', ctrl: true, shift: true)), 'ctrl-!') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0032', ctrl: true, shift: true)), 'ctrl-@') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0033', ctrl: true, shift: true)), 'ctrl-#') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0034', ctrl: true, shift: true)), 'ctrl-$') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0035', ctrl: true, shift: true)), 'ctrl-%') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0036', ctrl: true, shift: true)), 'ctrl-^') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0037', ctrl: true, shift: true)), 'ctrl-&') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0038', ctrl: true, shift: true)), 'ctrl-*') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+0039', ctrl: true, shift: true)), 'ctrl-(') - - # Other symbols - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00ba', ctrl: true)), 'ctrl-;') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00bb', ctrl: true)), 'ctrl-=') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00bc', ctrl: true)), 'ctrl-,') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00bd', ctrl: true)), 'ctrl--') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00be', ctrl: true)), 'ctrl-.') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00bf', ctrl: true)), 'ctrl-/') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00db', ctrl: true)), 'ctrl-[') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00dc', ctrl: true)), 'ctrl-\\') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00dd', ctrl: true)), 'ctrl-]') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00de', ctrl: true)), 'ctrl-\'') - - # Other symbols shifted - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00ba', ctrl: true, shift: true)), 'ctrl-:') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00bb', ctrl: true, shift: true)), 'ctrl-+') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00bc', ctrl: true, shift: true)), 'ctrl-<') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00bd', ctrl: true, shift: true)), 'ctrl-_') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00be', ctrl: true, shift: true)), 'ctrl->') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00bf', ctrl: true, shift: true)), 'ctrl-?') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00db', ctrl: true, shift: true)), 'ctrl-{') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00dc', ctrl: true, shift: true)), 'ctrl-|') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00dd', ctrl: true, shift: true)), 'ctrl-}') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00de', ctrl: true, shift: true)), 'ctrl-"') - - # Single modifiers - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00A0', shift: true)), 'shift') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00A1', shift: true)), 'shift') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00A2', ctrl: true)), 'ctrl') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00A3', ctrl: true)), 'ctrl') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00A4', alt: true)), 'alt') - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+00A5', alt: true)), 'alt') - - Object.defineProperty process, 'platform', value: 'win32' - testTranslations() - Object.defineProperty process, 'platform', value: 'linux' - testTranslations() - describe "::findKeyBindings({command, target, keystrokes})", -> [elementA, elementB] = [] beforeEach -> diff --git a/src/helpers.coffee b/src/helpers.coffee index 570ef05..f9f22bc 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -1,8 +1,7 @@ {calculateSpecificity} = require 'clear-cut' +KeyboardLayout = require 'keyboard-layout' -AtomModifiers = new Set -AtomModifiers.add(modifier) for modifier in ['ctrl', 'alt', 'shift', 'cmd'] - +Modifiers = new Set(['ctrl', 'alt', 'shift', 'cmd']) AtomModifierRegex = /(ctrl|alt|shift|cmd)$/ WhitespaceRegex = /\s+/ LowerCaseLetterRegex = /^[a-z]$/ @@ -10,100 +9,20 @@ UpperCaseLetterRegex = /^[A-Z]$/ ExactMatch = 'exact' KeydownExactMatch = 'keydownExact' PartialMatch = 'partial' - -KeyboardEventModifiers = new Set -KeyboardEventModifiers.add(modifier) for modifier in ['Control', 'Alt', 'Shift', 'Meta'] - -WindowsAndLinuxKeyIdentifierTranslations = - 'U+00A0': 'Shift' - 'U+00A1': 'Shift' - 'U+00A2': 'Control' - 'U+00A3': 'Control' - 'U+00A4': 'Alt' - 'U+00A5': 'Alt' - 'Win': 'Meta' - -WindowsAndLinuxCharCodeTranslations = - 48: - shifted: 41 # ")" - unshifted: 48 # "0" - 49: - shifted: 33 # "!" - unshifted: 49 # "1" - 50: - shifted: 64 # "@" - unshifted: 50 # "2" - 51: - shifted: 35 # "#" - unshifted: 51 # "3" - 52: - shifted: 36 # "$" - unshifted: 52 # "4" - 53: - shifted: 37 # "%" - unshifted: 53 # "5" - 54: - shifted: 94 # "^" - unshifted: 54 # "6" - 55: - shifted: 38 # "&" - unshifted: 55 # "7" - 56: - shifted: 42 # "*" - unshifted: 56 # "8" - 57: - shifted: 40 # "(" - unshifted: 57 # "9" - 186: - shifted: 58 # ":" - unshifted: 59 # ";" - 187: - shifted: 43 # "+" - unshifted: 61 # "=" - 188: - shifted: 60 # "<" - unshifted: 44 # "," - 189: - shifted: 95 # "_" - unshifted: 45 # "-" - 190: - shifted: 62 # ">" - unshifted: 46 # "." - 191: - shifted: 63 # "?" - unshifted: 47 # "/" - 192: - shifted: 126 # "~" - unshifted: 96 # "`" - 219: - shifted: 123 # "{" - unshifted: 91 # "[" - 220: - shifted: 124 # "|" - unshifted: 92 # "\" - 221: - shifted: 125 # "}" - unshifted: 93 # "]" - 222: - shifted: 34 # '"' - unshifted: 39 # "'" - -NumPadToASCII = - 79: 47 # "/" - 74: 42 # "*" - 77: 45 # "-" - 75: 43 # "+" - 78: 46 # "." - 96: 48 # "0" - 65: 49 # "1" - 66: 50 # "2" - 67: 51 # "3" - 68: 52 # "4" - 69: 53 # "5" - 70: 54 # "6" - 71: 55 # "7" - 72: 56 # "8" - 73: 57 # "9" +NonPrintableKeyNamesByCode = { + 'AltLeft': 'alt', + 'AltRight': 'alt', + 'ControlLeft': 'ctrl', + 'ControlRight': 'ctrl', + 'MetaLeft': 'cmd', + 'MetaRight': 'cmd', + 'ShiftLeft': 'shift', + 'ShiftRight': 'shift', + 'ArrowDown': 'down', + 'ArrowUp': 'up', + 'ArrowLeft': 'left', + 'ArrowRight': 'right' +} exports.normalizeKeystrokes = (keystrokes) -> normalizedKeystrokes = [] @@ -115,23 +34,43 @@ exports.normalizeKeystrokes = (keystrokes) -> normalizedKeystrokes.join(' ') exports.keystrokeForKeyboardEvent = (event, dvorakQwertyWorkaroundEnabled) -> - key = keyForKeyboardEvent(event, dvorakQwertyWorkaroundEnabled) + key = NonPrintableKeyNamesByCode[event.code] + unless key? + if characters = KeyboardLayout.charactersForKeyCode(event.code) + key = characters.unmodified + unless key? + key = event.code.toLowerCase() keystroke = '' - if event.ctrlKey or key is 'Control' + if event.ctrlKey or key is 'ctrl' keystroke += 'ctrl' - if event.altKey or key is 'Alt' - keystroke += '-' if keystroke - keystroke += 'alt' - if event.shiftKey or key is 'Shift' - # Don't push 'shift' when modifying symbolic characters like '{' + + if event.shiftKey + if event.altKey + if characters? + key = characters.withShiftAltGr + keystroke += '-' if keystroke.length > 0 + keystroke += 'alt' + else + if characters? + key = characters.withShift unless /^[^A-Za-z]$/.test(key) keystroke += '-' if keystroke keystroke += 'shift' + else if event.altKey + appendAltModifier = true + if characters? + if characters.withAltGr.charCodeAt(0) <= 127 + key = characters.withAltGr + appendAltModifier = false + if appendAltModifier + keystroke += '-' if keystroke.length > 0 + keystroke += 'alt' + if event.metaKey or key is 'Meta' keystroke += '-' if keystroke keystroke += 'cmd' - if key? and not KeyboardEventModifiers.has(key) + if key? and not Modifiers.has(key) keystroke += '-' if keystroke keystroke += key @@ -146,7 +85,7 @@ exports.characterForKeyboardEvent = (event, dvorakQwertyWorkaroundEnabled) -> exports.calculateSpecificity = calculateSpecificity exports.isAtomModifier = (keystroke) -> - AtomModifiers.has(keystroke) or AtomModifierRegex.test(keystroke) + Modifiers.has(keystroke) or AtomModifierRegex.test(keystroke) exports.keydownEvent = (key, options) -> return keyboardEvent(key, 'keydown', options) @@ -247,7 +186,7 @@ normalizeKeystroke = (keystroke) -> modifiers = new Set for key, i in keys - if AtomModifiers.has(key) + if Modifiers.has(key) modifiers.add(key) else # only the last key can be a non-modifier @@ -287,12 +226,13 @@ parseKeystroke = (keystroke) -> keys.push(keystroke.substring(keyStart)) if keyStart < keystroke.length keys -keyForKeyboardEvent = (event, dvorakQwertyWorkaroundEnabled) -> +keyForKeyboardEvent = (event) -> + keyIdentifier = event.keyIdentifier if process.platform in ['linux', 'win32'] keyIdentifier = translateKeyIdentifierForWindowsAndLinuxChromiumBug(keyIdentifier) - return keyIdentifier if KeyboardEventModifiers.has(keyIdentifier) + return keyIdentifier if KEYBOARD_EVENT_MODIFIERS.has(keyIdentifier) charCode = charCodeFromKeyIdentifier(keyIdentifier) From d4d817d169e64f7893672b6e4995ece276eb89e8 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 8 Sep 2016 18:29:20 -0600 Subject: [PATCH 03/24] =?UTF-8?q?Don=E2=80=99t=20shadow=20ASCII=20characte?= =?UTF-8?q?rs=20with=20alt-bindings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If alt- or shift-alt- produces an ASCII character on the current layout, interpret the keystroke as that character. If ctrl or cmd are also pressed, don’t use the alternative character for the binding. For example, on a Swiss layout: alt-g is interpreted as @ ctrl-alt-g is still interpreted as ctrl-alt-g --- spec/helpers/swiss-german-keymap.js | 380 ++++++++++++++++++++++++++++ spec/keymap-manager-spec.coffee | 11 +- src/helpers.coffee | 16 +- 3 files changed, 395 insertions(+), 12 deletions(-) create mode 100644 spec/helpers/swiss-german-keymap.js diff --git a/spec/helpers/swiss-german-keymap.js b/spec/helpers/swiss-german-keymap.js new file mode 100644 index 0000000..5f203aa --- /dev/null +++ b/spec/helpers/swiss-german-keymap.js @@ -0,0 +1,380 @@ +module.exports = { + "Space": { + "unmodified": " ", + "withShift": " ", + "withAltGr": " ", + "withShiftAltGr": " " + }, + "Digit0": { + "unmodified": "0", + "withShift": "=", + "withAltGr": "≠", + "withShiftAltGr": "Ú" + }, + "Digit1": { + "unmodified": "1", + "withShift": "+", + "withAltGr": "±", + "withShiftAltGr": "∞" + }, + "Digit2": { + "unmodified": "2", + "withShift": "\"", + "withAltGr": "“", + "withShiftAltGr": "”" + }, + "Digit3": { + "unmodified": "3", + "withShift": "*", + "withAltGr": "#", + "withShiftAltGr": "‹" + }, + "Digit4": { + "unmodified": "4", + "withShift": "ç", + "withAltGr": "Ç", + "withShiftAltGr": "⁄" + }, + "Digit5": { + "unmodified": "5", + "withShift": "%", + "withAltGr": "[", + "withShiftAltGr": "[" + }, + "Digit6": { + "unmodified": "6", + "withShift": "&", + "withAltGr": "]", + "withShiftAltGr": "]" + }, + "Digit7": { + "unmodified": "7", + "withShift": "/", + "withAltGr": "|", + "withShiftAltGr": "\\" + }, + "Digit8": { + "unmodified": "8", + "withShift": "(", + "withAltGr": "{", + "withShiftAltGr": "Ò" + }, + "Digit9": { + "unmodified": "9", + "withShift": ")", + "withAltGr": "}", + "withShiftAltGr": "Ô" + }, + "KeyA": { + "unmodified": "a", + "withShift": "A", + "withAltGr": "å", + "withShiftAltGr": "Å" + }, + "KeyB": { + "unmodified": "b", + "withShift": "B", + "withAltGr": "∫", + "withShiftAltGr": "" + }, + "KeyC": { + "unmodified": "c", + "withShift": "C", + "withAltGr": "©", + "withShiftAltGr": "" + }, + "KeyD": { + "unmodified": "d", + "withShift": "D", + "withAltGr": "∂", + "withShiftAltGr": "fl" + }, + "KeyE": { + "unmodified": "e", + "withShift": "E", + "withAltGr": "€", + "withShiftAltGr": "Ë" + }, + "KeyF": { + "unmodified": "f", + "withShift": "F", + "withAltGr": "ƒ", + "withShiftAltGr": "‡" + }, + "KeyG": { + "unmodified": "g", + "withShift": "G", + "withAltGr": "@", + "withShiftAltGr": "‚" + }, + "KeyH": { + "unmodified": "h", + "withShift": "H", + "withAltGr": "ª", + "withShiftAltGr": "·" + }, + "KeyI": { + "unmodified": "i", + "withShift": "I", + "withAltGr": "¡", + "withShiftAltGr": "ı" + }, + "KeyJ": { + "unmodified": "j", + "withShift": "J", + "withAltGr": "º", + "withShiftAltGr": "˜" + }, + "KeyK": { + "unmodified": "k", + "withShift": "K", + "withAltGr": "∆", + "withShiftAltGr": "¯" + }, + "KeyL": { + "unmodified": "l", + "withShift": "L", + "withAltGr": "¬", + "withShiftAltGr": "ˆ" + }, + "KeyM": { + "unmodified": "m", + "withShift": "M", + "withAltGr": "µ", + "withShiftAltGr": "˚" + }, + "KeyN": { + "unmodified": "n", + "withShift": "N", + "withAltGr": "", + "withShiftAltGr": "˙" + }, + "KeyO": { + "unmodified": "o", + "withShift": "O", + "withAltGr": "ø", + "withShiftAltGr": "Ø" + }, + "KeyP": { + "unmodified": "p", + "withShift": "P", + "withAltGr": "π", + "withShiftAltGr": "∏" + }, + "KeyQ": { + "unmodified": "q", + "withShift": "Q", + "withAltGr": "œ", + "withShiftAltGr": "Œ" + }, + "KeyR": { + "unmodified": "r", + "withShift": "R", + "withAltGr": "®", + "withShiftAltGr": "È" + }, + "KeyS": { + "unmodified": "s", + "withShift": "S", + "withAltGr": "ß", + "withShiftAltGr": "fi" + }, + "KeyT": { + "unmodified": "t", + "withShift": "T", + "withAltGr": "†", + "withShiftAltGr": "Î" + }, + "KeyU": { + "unmodified": "u", + "withShift": "U", + "withAltGr": "°", + "withShiftAltGr": "Ù" + }, + "KeyV": { + "unmodified": "v", + "withShift": "V", + "withAltGr": "√", + "withShiftAltGr": "◊" + }, + "KeyW": { + "unmodified": "w", + "withShift": "W", + "withAltGr": "∑", + "withShiftAltGr": "Á" + }, + "KeyX": { + "unmodified": "x", + "withShift": "X", + "withAltGr": "≈", + "withShiftAltGr": "™" + }, + "KeyY": { + "unmodified": "z", + "withShift": "Z", + "withAltGr": "Ω", + "withShiftAltGr": "Í" + }, + "KeyZ": { + "unmodified": "y", + "withShift": "Y", + "withAltGr": "¥", + "withShiftAltGr": "Ÿ" + }, + "Numpad0": { + "unmodified": "0", + "withShift": "0", + "withAltGr": "0", + "withShiftAltGr": "0" + }, + "Numpad1": { + "unmodified": "1", + "withShift": "1", + "withAltGr": "1", + "withShiftAltGr": "1" + }, + "Numpad2": { + "unmodified": "2", + "withShift": "2", + "withAltGr": "2", + "withShiftAltGr": "2" + }, + "Numpad3": { + "unmodified": "3", + "withShift": "3", + "withAltGr": "3", + "withShiftAltGr": "3" + }, + "Numpad4": { + "unmodified": "4", + "withShift": "4", + "withAltGr": "4", + "withShiftAltGr": "4" + }, + "Numpad5": { + "unmodified": "5", + "withShift": "5", + "withAltGr": "5", + "withShiftAltGr": "5" + }, + "Numpad6": { + "unmodified": "6", + "withShift": "6", + "withAltGr": "6", + "withShiftAltGr": "6" + }, + "Numpad7": { + "unmodified": "7", + "withShift": "7", + "withAltGr": "7", + "withShiftAltGr": "7" + }, + "Numpad8": { + "unmodified": "8", + "withShift": "8", + "withAltGr": "8", + "withShiftAltGr": "8" + }, + "Numpad9": { + "unmodified": "9", + "withShift": "9", + "withAltGr": "9", + "withShiftAltGr": "9" + }, + "NumpadMultiply": { + "unmodified": "*", + "withShift": "*", + "withAltGr": "*", + "withShiftAltGr": "*" + }, + "NumpadAdd": { + "unmodified": "+", + "withShift": "+", + "withAltGr": "+", + "withShiftAltGr": "+" + }, + "NumpadSubtract": { + "unmodified": "-", + "withShift": "-", + "withAltGr": "-", + "withShiftAltGr": "-" + }, + "NumpadDecimal": { + "unmodified": ".", + "withShift": ",", + "withAltGr": ".", + "withShiftAltGr": "." + }, + "NumpadDivide": { + "unmodified": "/", + "withShift": "/", + "withAltGr": "/", + "withShiftAltGr": "/" + }, + "Semicolon": { + "unmodified": "ö", + "withShift": "é", + "withAltGr": "¢", + "withShiftAltGr": "˘" + }, + "Equal": { + "unmodified": "", + "withShift": "", + "withAltGr": "", + "withShiftAltGr": "^" + }, + "NumpadComma": { + "unmodified": ",", + "withShift": ";", + "withAltGr": "«", + "withShiftAltGr": "»" + }, + "Minus": { + "unmodified": "'", + "withShift": "?", + "withAltGr": "¿", + "withShiftAltGr": "" + }, + "Period": { + "unmodified": ".", + "withShift": ":", + "withAltGr": "…", + "withShiftAltGr": "÷" + }, + "Slash": { + "unmodified": "-", + "withShift": "_", + "withAltGr": "–", + "withShiftAltGr": "—" + }, + "Backquote": { + "unmodified": "<", + "withShift": ">", + "withAltGr": "≤", + "withShiftAltGr": "≥" + }, + "BracketLeft": { + "unmodified": "ü", + "withShift": "è", + "withAltGr": "§", + "withShiftAltGr": "ÿ" + }, + "IntlYen": { + "unmodified": "$", + "withShift": "£", + "withAltGr": "¶", + "withShiftAltGr": "•" + }, + "BracketRight": { + "unmodified": "", + "withShift": "!", + "withAltGr": "‘", + "withShiftAltGr": "’" + }, + "Quote": { + "unmodified": "ä", + "withShift": "à", + "withAltGr": "æ", + "withShiftAltGr": "Æ" + } +} diff --git a/spec/keymap-manager-spec.coffee b/spec/keymap-manager-spec.coffee index 0598ce5..2842870 100644 --- a/spec/keymap-manager-spec.coffee +++ b/spec/keymap-manager-spec.coffee @@ -616,9 +616,14 @@ describe "KeymapManager", -> assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Numpad5'}), '5') assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'NumpadAdd'}), '+') - 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", -> - assert.equal(keymapManager.keystrokeForKeyboardEvent(buildKeydownEvent('U+03B6', cmd: true, keyCode: 122)), 'cmd-z') + describe "international layouts", -> + it "allows normal ASCII characters (<= 127) to be typed via an alt modifier", -> + currentKeymap = require('./helpers/swiss-german-keymap') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyG', altKey: true}), '@') + # Only uses alt variants for basic latin + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyG', altKey: true, shiftKey: true}), 'alt-shift-g') + # Only uses alt variants when no other modifiers are used + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyG', ctrlKey: true, altKey: true}), 'ctrl-alt-g') describe "::findKeyBindings({command, target, keystrokes})", -> [elementA, elementB] = [] diff --git a/src/helpers.coffee b/src/helpers.coffee index f9f22bc..fdc4adf 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -47,10 +47,11 @@ exports.keystrokeForKeyboardEvent = (event, dvorakQwertyWorkaroundEnabled) -> if event.shiftKey if event.altKey - if characters? + if characters? and characters.withShiftAltGr.charCodeAt(0) <= 127 and not event.ctrlKey and not event.metaKey key = characters.withShiftAltGr - keystroke += '-' if keystroke.length > 0 - keystroke += 'alt' + else + keystroke += '-' if keystroke.length > 0 + keystroke += 'alt' else if characters? key = characters.withShift @@ -58,12 +59,9 @@ exports.keystrokeForKeyboardEvent = (event, dvorakQwertyWorkaroundEnabled) -> keystroke += '-' if keystroke keystroke += 'shift' else if event.altKey - appendAltModifier = true - if characters? - if characters.withAltGr.charCodeAt(0) <= 127 - key = characters.withAltGr - appendAltModifier = false - if appendAltModifier + if characters? and characters.withAltGr.charCodeAt(0) <= 127 and not event.ctrlKey and not event.metaKey + key = characters.withAltGr + else keystroke += '-' if keystroke.length > 0 keystroke += 'alt' From 290790647ea7be76e33f005e426176c7de95949f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 9 Sep 2016 10:48:05 -0600 Subject: [PATCH 04/24] Reorganize keymaps in spec --- spec/helpers/{dvorak-keymap.js => keymaps/dvorak.json} | 2 +- .../swiss-german.json} | 2 +- spec/keymap-manager-spec.coffee | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) rename spec/helpers/{dvorak-keymap.js => keymaps/dvorak.json} (99%) rename spec/helpers/{swiss-german-keymap.js => keymaps/swiss-german.json} (99%) diff --git a/spec/helpers/dvorak-keymap.js b/spec/helpers/keymaps/dvorak.json similarity index 99% rename from spec/helpers/dvorak-keymap.js rename to spec/helpers/keymaps/dvorak.json index 89fa3de..880bc5b 100644 --- a/spec/helpers/dvorak-keymap.js +++ b/spec/helpers/keymaps/dvorak.json @@ -1,4 +1,4 @@ -module.exports = { +{ "Space": { "unmodified": " ", "withShift": " ", diff --git a/spec/helpers/swiss-german-keymap.js b/spec/helpers/keymaps/swiss-german.json similarity index 99% rename from spec/helpers/swiss-german-keymap.js rename to spec/helpers/keymaps/swiss-german.json index 5f203aa..2e39c43 100644 --- a/spec/helpers/swiss-german-keymap.js +++ b/spec/helpers/keymaps/swiss-german.json @@ -1,4 +1,4 @@ -module.exports = { +{ "Space": { "unmodified": " ", "withShift": " ", diff --git a/spec/keymap-manager-spec.coffee b/spec/keymap-manager-spec.coffee index 2842870..37848fb 100644 --- a/spec/keymap-manager-spec.coffee +++ b/spec/keymap-manager-spec.coffee @@ -579,7 +579,7 @@ describe "KeymapManager", -> assert.equal(keymapManager.findKeyBindings(command: 'y').length, 1) assert.equal(keymapManager.findKeyBindings(command: 'z').length, 0) - describe.only "::keystrokeForKeyboardEvent(event)", -> + describe "::keystrokeForKeyboardEvent(event)", -> KeyboardLayout = require('keyboard-layout') currentKeymap = null @@ -589,7 +589,7 @@ describe "KeymapManager", -> describe "when no extra modifiers are pressed", -> it "returns a string that identifies the unmodified keystroke", -> - currentKeymap = require('./helpers/dvorak-keymap') + currentKeymap = require('./helpers/keymaps/dvorak') assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyA'}), 'a') assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Minus'}), '[') assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Digit8', shiftKey: true}), '*') @@ -600,7 +600,7 @@ describe "KeymapManager", -> describe "when a modifier key is combined with a non-modifier key", -> it "returns a string that identifies the modified keystroke", -> - currentKeymap = require('./helpers/dvorak-keymap') + currentKeymap = require('./helpers/keymaps/dvorak') assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyA', altKey: true}), 'alt-a') assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Minus', metaKey: true}), 'cmd-[') assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Digit8', ctrlKey: true, shiftKey: true}), 'ctrl-*') @@ -611,14 +611,14 @@ describe "KeymapManager", -> describe "when a numpad key is pressed", -> it "returns a string that identifies the key as the appropriate num-key", -> - currentKeymap = require('./helpers/dvorak-keymap') + currentKeymap = require('./helpers/keymaps/dvorak') assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Numpad1'}), '1') assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Numpad5'}), '5') assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'NumpadAdd'}), '+') describe "international layouts", -> it "allows normal ASCII characters (<= 127) to be typed via an alt modifier", -> - currentKeymap = require('./helpers/swiss-german-keymap') + currentKeymap = require('./helpers/keymaps/swiss-german') assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyG', altKey: true}), '@') # Only uses alt variants for basic latin assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyG', altKey: true, shiftKey: true}), 'alt-shift-g') From 05da51b9cbdffaa81aa84a533a91a11623cc0deb Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 9 Sep 2016 10:50:13 -0600 Subject: [PATCH 05/24] Reinterpret non-latin keys when modifiers are used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enables cmd-d on a Greek keyboard rather than cmd-δ, which matches the behavior os OS X. Non-ASCII characters that still fall in the Latin character set are not converted, and we only apply the conversion when a modifier is depressed. --- spec/helpers/keymaps/greek.json | 380 ++++++++++++++++++++++++++++++ spec/helpers/keymaps/turkish.json | 380 ++++++++++++++++++++++++++++++ spec/keymap-manager-spec.coffee | 11 + src/helpers.coffee | 17 ++ src/us-keymap.coffee | 380 ++++++++++++++++++++++++++++++ 5 files changed, 1168 insertions(+) create mode 100644 spec/helpers/keymaps/greek.json create mode 100644 spec/helpers/keymaps/turkish.json create mode 100644 src/us-keymap.coffee diff --git a/spec/helpers/keymaps/greek.json b/spec/helpers/keymaps/greek.json new file mode 100644 index 0000000..1fd47ff --- /dev/null +++ b/spec/helpers/keymaps/greek.json @@ -0,0 +1,380 @@ +{ + "Space": { + "unmodified": " ", + "withShift": " ", + "withAltGr": " ", + "withShiftAltGr": " " + }, + "Digit0": { + "unmodified": "0", + "withShift": ")", + "withAltGr": "°", + "withShiftAltGr": "ύ" + }, + "Digit1": { + "unmodified": "1", + "withShift": "!", + "withAltGr": "¹", + "withShiftAltGr": "έ" + }, + "Digit2": { + "unmodified": "2", + "withShift": "@", + "withAltGr": "²", + "withShiftAltGr": "ί" + }, + "Digit3": { + "unmodified": "3", + "withShift": "#", + "withAltGr": "³", + "withShiftAltGr": "ή" + }, + "Digit4": { + "unmodified": "4", + "withShift": "$", + "withAltGr": "£", + "withShiftAltGr": "ό" + }, + "Digit5": { + "unmodified": "5", + "withShift": "%", + "withAltGr": "§", + "withShiftAltGr": "Ώ" + }, + "Digit6": { + "unmodified": "6", + "withShift": "^", + "withAltGr": "¶", + "withShiftAltGr": "^" + }, + "Digit7": { + "unmodified": "7", + "withShift": "&", + "withAltGr": "°", + "withShiftAltGr": "" + }, + "Digit8": { + "unmodified": "8", + "withShift": "*", + "withAltGr": "•", + "withShiftAltGr": "Ρ" + }, + "Digit9": { + "unmodified": "9", + "withShift": "(", + "withAltGr": "“", + "withShiftAltGr": "Κ" + }, + "KeyA": { + "unmodified": "α", + "withShift": "Α", + "withAltGr": "…", + "withShiftAltGr": "ά" + }, + "KeyB": { + "unmodified": "β", + "withShift": "Β", + "withAltGr": "", + "withShiftAltGr": "" + }, + "KeyC": { + "unmodified": "ψ", + "withShift": "Ψ", + "withAltGr": "ç", + "withShiftAltGr": "Χ" + }, + "KeyD": { + "unmodified": "δ", + "withShift": "Δ", + "withAltGr": "÷", + "withShiftAltGr": "" + }, + "KeyE": { + "unmodified": "ε", + "withShift": "Ε", + "withAltGr": "€", + "withShiftAltGr": "Έ" + }, + "KeyF": { + "unmodified": "φ", + "withShift": "Φ", + "withAltGr": "≠", + "withShiftAltGr": "Π" + }, + "KeyG": { + "unmodified": "γ", + "withShift": "Γ", + "withAltGr": "©", + "withShiftAltGr": "Ϊ" + }, + "KeyH": { + "unmodified": "η", + "withShift": "Η", + "withAltGr": "½", + "withShiftAltGr": "≠" + }, + "KeyI": { + "unmodified": "ι", + "withShift": "Ι", + "withAltGr": "†", + "withShiftAltGr": "Ν" + }, + "KeyJ": { + "unmodified": "ξ", + "withShift": "Ξ", + "withAltGr": "≤", + "withShiftAltGr": "§" + }, + "KeyK": { + "unmodified": "κ", + "withShift": "Κ", + "withAltGr": "≥", + "withShiftAltGr": "°" + }, + "KeyL": { + "unmodified": "λ", + "withShift": "Λ", + "withAltGr": "¬", + "withShiftAltGr": "·" + }, + "KeyM": { + "unmodified": "μ", + "withShift": "Μ", + "withAltGr": "’", + "withShiftAltGr": "Ύ" + }, + "KeyN": { + "unmodified": "ν", + "withShift": "Ν", + "withAltGr": "‘", + "withShiftAltGr": "Ό" + }, + "KeyO": { + "unmodified": "ο", + "withShift": "Ο", + "withAltGr": "œ", + "withShiftAltGr": "Τ" + }, + "KeyP": { + "unmodified": "π", + "withShift": "Π", + "withAltGr": "≈", + "withShiftAltGr": "" + }, + "KeyQ": { + "unmodified": ";", + "withShift": ":", + "withAltGr": "·", + "withShiftAltGr": "―" + }, + "KeyR": { + "unmodified": "ρ", + "withShift": "Ρ", + "withAltGr": "®", + "withShiftAltGr": "Δ" + }, + "KeyS": { + "unmodified": "σ", + "withShift": "Σ", + "withAltGr": "ß", + "withShiftAltGr": "ρ" + }, + "KeyT": { + "unmodified": "τ", + "withShift": "Τ", + "withAltGr": "™", + "withShiftAltGr": "" + }, + "KeyU": { + "unmodified": "θ", + "withShift": "Θ", + "withAltGr": "­", + "withShiftAltGr": "Ξ" + }, + "KeyV": { + "unmodified": "ω", + "withShift": "Ω", + "withAltGr": "±", + "withShiftAltGr": "Ά" + }, + "KeyW": { + "unmodified": "ς", + "withShift": "", + "withAltGr": "―", + "withShiftAltGr": "Β" + }, + "KeyX": { + "unmodified": "χ", + "withShift": "Χ", + "withAltGr": "", + "withShiftAltGr": "" + }, + "KeyY": { + "unmodified": "υ", + "withShift": "Υ", + "withAltGr": "¥", + "withShiftAltGr": "" + }, + "KeyZ": { + "unmodified": "ζ", + "withShift": "Ζ", + "withAltGr": "§", + "withShiftAltGr": "" + }, + "Numpad0": { + "unmodified": "0", + "withShift": "0", + "withAltGr": "0", + "withShiftAltGr": "0" + }, + "Numpad1": { + "unmodified": "1", + "withShift": "1", + "withAltGr": "1", + "withShiftAltGr": "1" + }, + "Numpad2": { + "unmodified": "2", + "withShift": "2", + "withAltGr": "2", + "withShiftAltGr": "2" + }, + "Numpad3": { + "unmodified": "3", + "withShift": "3", + "withAltGr": "3", + "withShiftAltGr": "3" + }, + "Numpad4": { + "unmodified": "4", + "withShift": "4", + "withAltGr": "4", + "withShiftAltGr": "4" + }, + "Numpad5": { + "unmodified": "5", + "withShift": "5", + "withAltGr": "5", + "withShiftAltGr": "5" + }, + "Numpad6": { + "unmodified": "6", + "withShift": "6", + "withAltGr": "6", + "withShiftAltGr": "6" + }, + "Numpad7": { + "unmodified": "7", + "withShift": "7", + "withAltGr": "7", + "withShiftAltGr": "7" + }, + "Numpad8": { + "unmodified": "8", + "withShift": "8", + "withAltGr": "8", + "withShiftAltGr": "8" + }, + "Numpad9": { + "unmodified": "9", + "withShift": "9", + "withAltGr": "9", + "withShiftAltGr": "9" + }, + "NumpadMultiply": { + "unmodified": "*", + "withShift": "*", + "withAltGr": "*", + "withShiftAltGr": "*" + }, + "NumpadAdd": { + "unmodified": "+", + "withShift": "+", + "withAltGr": "+", + "withShiftAltGr": "+" + }, + "NumpadSubtract": { + "unmodified": "-", + "withShift": "-", + "withAltGr": "-", + "withShiftAltGr": "-" + }, + "NumpadDecimal": { + "unmodified": ".", + "withShift": ".", + "withAltGr": ".", + "withShiftAltGr": "." + }, + "NumpadDivide": { + "unmodified": "/", + "withShift": "/", + "withAltGr": "/", + "withShiftAltGr": "/" + }, + "Semicolon": { + "unmodified": "", + "withShift": "", + "withAltGr": "", + "withShiftAltGr": ":" + }, + "Equal": { + "unmodified": "=", + "withShift": "+", + "withAltGr": "½", + "withShiftAltGr": "+" + }, + "NumpadComma": { + "unmodified": ",", + "withShift": "<", + "withAltGr": "«", + "withShiftAltGr": "" + }, + "Minus": { + "unmodified": "-", + "withShift": "_", + "withAltGr": "±", + "withShiftAltGr": "_" + }, + "Period": { + "unmodified": ".", + "withShift": ">", + "withAltGr": "»", + "withShiftAltGr": "ώ" + }, + "Slash": { + "unmodified": "/", + "withShift": "?", + "withAltGr": "/", + "withShiftAltGr": "?" + }, + "Backquote": { + "unmodified": "`", + "withShift": "~", + "withAltGr": "`", + "withShiftAltGr": "Μ" + }, + "BracketLeft": { + "unmodified": "[", + "withShift": "{", + "withAltGr": "«", + "withShiftAltGr": "{" + }, + "IntlYen": { + "unmodified": "\\", + "withShift": "|", + "withAltGr": "¦", + "withShiftAltGr": "Ζ" + }, + "BracketRight": { + "unmodified": "]", + "withShift": "}", + "withAltGr": "»", + "withShiftAltGr": "}" + }, + "Quote": { + "unmodified": "'", + "withShift": "\"", + "withAltGr": "'", + "withShiftAltGr": "\"" + } +} diff --git a/spec/helpers/keymaps/turkish.json b/spec/helpers/keymaps/turkish.json new file mode 100644 index 0000000..266f402 --- /dev/null +++ b/spec/helpers/keymaps/turkish.json @@ -0,0 +1,380 @@ +{ + "Space": { + "unmodified": " ", + "withShift": " ", + "withAltGr": " ", + "withShiftAltGr": " " + }, + "Digit0": { + "unmodified": "0", + "withShift": ":", + "withAltGr": "º", + "withShiftAltGr": "÷" + }, + "Digit1": { + "unmodified": "1", + "withShift": "!", + "withAltGr": "¡", + "withShiftAltGr": "·" + }, + "Digit2": { + "unmodified": "2", + "withShift": "*", + "withAltGr": "™", + "withShiftAltGr": "€" + }, + "Digit3": { + "unmodified": "3", + "withShift": "\"", + "withAltGr": "“", + "withShiftAltGr": "”" + }, + "Digit4": { + "unmodified": "4", + "withShift": "'", + "withAltGr": "‘", + "withShiftAltGr": "’" + }, + "Digit5": { + "unmodified": "5", + "withShift": "(", + "withAltGr": "[", + "withShiftAltGr": "{" + }, + "Digit6": { + "unmodified": "6", + "withShift": "/", + "withAltGr": "|", + "withShiftAltGr": "\\" + }, + "Digit7": { + "unmodified": "7", + "withShift": ")", + "withAltGr": "]", + "withShiftAltGr": "}" + }, + "Digit8": { + "unmodified": "8", + "withShift": "_", + "withAltGr": "•", + "withShiftAltGr": "°" + }, + "Digit9": { + "unmodified": "9", + "withShift": "%", + "withAltGr": "«", + "withShiftAltGr": "»" + }, + "KeyA": { + "unmodified": "u", + "withShift": "U", + "withAltGr": "", + "withShiftAltGr": "Ë" + }, + "KeyB": { + "unmodified": "ç", + "withShift": "Ç", + "withAltGr": "¯", + "withShiftAltGr": "˙" + }, + "KeyC": { + "unmodified": "v", + "withShift": "V", + "withAltGr": "√", + "withShiftAltGr": "◊" + }, + "KeyD": { + "unmodified": "e", + "withShift": "E", + "withAltGr": "", + "withShiftAltGr": "‰" + }, + "KeyE": { + "unmodified": "ğ", + "withShift": "Ğ", + "withAltGr": "#", + "withShiftAltGr": "´" + }, + "KeyF": { + "unmodified": "a", + "withShift": "A", + "withAltGr": "å", + "withShiftAltGr": "Å" + }, + "KeyG": { + "unmodified": "ü", + "withShift": "Ü", + "withAltGr": "@", + "withShiftAltGr": "ª" + }, + "KeyH": { + "unmodified": "t", + "withShift": "T", + "withAltGr": "₺", + "withShiftAltGr": "Ê" + }, + "KeyI": { + "unmodified": "n", + "withShift": "N", + "withAltGr": "", + "withShiftAltGr": "ˆ" + }, + "KeyJ": { + "unmodified": "k", + "withShift": "K", + "withAltGr": "", + "withShiftAltGr": "©" + }, + "KeyK": { + "unmodified": "m", + "withShift": "M", + "withAltGr": "µ", + "withShiftAltGr": "˜" + }, + "KeyL": { + "unmodified": "l", + "withShift": "L", + "withAltGr": "¬", + "withShiftAltGr": "£" + }, + "KeyM": { + "unmodified": "s", + "withShift": "S", + "withAltGr": "§", + "withShiftAltGr": "~" + }, + "KeyN": { + "unmodified": "z", + "withShift": "Z", + "withAltGr": "Ω", + "withShiftAltGr": "Û" + }, + "KeyO": { + "unmodified": "h", + "withShift": "H", + "withAltGr": "", + "withShiftAltGr": "Ó" + }, + "KeyP": { + "unmodified": "p", + "withShift": "P", + "withAltGr": "π", + "withShiftAltGr": "∏" + }, + "KeyQ": { + "unmodified": "f", + "withShift": "F", + "withAltGr": "ƒ", + "withShiftAltGr": "Ï" + }, + "KeyR": { + "unmodified": "ı", + "withShift": "I", + "withAltGr": "^", + "withShiftAltGr": "È" + }, + "KeyS": { + "unmodified": "i", + "withShift": "İ", + "withAltGr": "", + "withShiftAltGr": "∞" + }, + "KeyT": { + "unmodified": "o", + "withShift": "O", + "withAltGr": "ø", + "withShiftAltGr": "Ø" + }, + "KeyU": { + "unmodified": "r", + "withShift": "R", + "withAltGr": "®", + "withShiftAltGr": "Â" + }, + "KeyV": { + "unmodified": "c", + "withShift": "C", + "withAltGr": "ç", + "withShiftAltGr": "˚" + }, + "KeyW": { + "unmodified": "g", + "withShift": "G", + "withAltGr": "¶", + "withShiftAltGr": "`" + }, + "KeyX": { + "unmodified": "ö", + "withShift": "Ö", + "withAltGr": "¨", + "withShiftAltGr": "Ÿ" + }, + "KeyY": { + "unmodified": "d", + "withShift": "D", + "withAltGr": "∂", + "withShiftAltGr": "Î" + }, + "KeyZ": { + "unmodified": "j", + "withShift": "J", + "withAltGr": "∆", + "withShiftAltGr": "Ô" + }, + "Numpad0": { + "unmodified": "0", + "withShift": "0", + "withAltGr": "0", + "withShiftAltGr": "0" + }, + "Numpad1": { + "unmodified": "1", + "withShift": "1", + "withAltGr": "1", + "withShiftAltGr": "1" + }, + "Numpad2": { + "unmodified": "2", + "withShift": "2", + "withAltGr": "2", + "withShiftAltGr": "2" + }, + "Numpad3": { + "unmodified": "3", + "withShift": "3", + "withAltGr": "3", + "withShiftAltGr": "3" + }, + "Numpad4": { + "unmodified": "4", + "withShift": "4", + "withAltGr": "4", + "withShiftAltGr": "4" + }, + "Numpad5": { + "unmodified": "5", + "withShift": "5", + "withAltGr": "5", + "withShiftAltGr": "5" + }, + "Numpad6": { + "unmodified": "6", + "withShift": "6", + "withAltGr": "6", + "withShiftAltGr": "6" + }, + "Numpad7": { + "unmodified": "7", + "withShift": "7", + "withAltGr": "7", + "withShiftAltGr": "7" + }, + "Numpad8": { + "unmodified": "8", + "withShift": "8", + "withAltGr": "8", + "withShiftAltGr": "8" + }, + "Numpad9": { + "unmodified": "9", + "withShift": "9", + "withAltGr": "9", + "withShiftAltGr": "9" + }, + "NumpadMultiply": { + "unmodified": "*", + "withShift": "*", + "withAltGr": "*", + "withShiftAltGr": "*" + }, + "NumpadAdd": { + "unmodified": "+", + "withShift": "+", + "withAltGr": "+", + "withShiftAltGr": "+" + }, + "NumpadSubtract": { + "unmodified": "-", + "withShift": "-", + "withAltGr": "-", + "withShiftAltGr": "-" + }, + "NumpadDecimal": { + "unmodified": ",", + "withShift": ",", + "withAltGr": ",", + "withShiftAltGr": "," + }, + "NumpadDivide": { + "unmodified": "/", + "withShift": "/", + "withAltGr": "/", + "withShiftAltGr": "/" + }, + "Semicolon": { + "unmodified": "y", + "withShift": "Y", + "withAltGr": "¥", + "withShiftAltGr": "Á" + }, + "Equal": { + "unmodified": "q", + "withShift": "Q", + "withAltGr": "œ", + "withShiftAltGr": "Œ" + }, + "NumpadComma": { + "unmodified": "b", + "withShift": "B", + "withAltGr": "∫", + "withShiftAltGr": "ß" + }, + "Minus": { + "unmodified": "x", + "withShift": "X", + "withAltGr": "≈", + "withShiftAltGr": "Ù" + }, + "Period": { + "unmodified": ".", + "withShift": "?", + "withAltGr": "&", + "withShiftAltGr": "¿" + }, + "Slash": { + "unmodified": ",", + "withShift": "-", + "withAltGr": "–", + "withShiftAltGr": "—" + }, + "Backquote": { + "unmodified": "w", + "withShift": "W", + "withAltGr": "∑", + "withShiftAltGr": "„" + }, + "BracketLeft": { + "unmodified": ";", + "withShift": "$", + "withAltGr": "…", + "withShiftAltGr": "¢" + }, + "IntlYen": { + "unmodified": "=", + "withShift": "+", + "withAltGr": "≠", + "withShiftAltGr": "±" + }, + "BracketRight": { + "unmodified": ">", + "withShift": "<", + "withAltGr": "≥", + "withShiftAltGr": "≤" + }, + "Quote": { + "unmodified": "ş", + "withShift": "Ş", + "withAltGr": "æ", + "withShiftAltGr": "Æ" + } +} diff --git a/spec/keymap-manager-spec.coffee b/spec/keymap-manager-spec.coffee index 37848fb..3f8ad95 100644 --- a/spec/keymap-manager-spec.coffee +++ b/spec/keymap-manager-spec.coffee @@ -625,6 +625,17 @@ describe "KeymapManager", -> # Only uses alt variants when no other modifiers are used assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyG', ctrlKey: true, altKey: true}), 'ctrl-alt-g') + it "converts non-latin keycaps to their U.S. counterpart for purposes of binding", -> + currentKeymap = require('./helpers/keymaps/greek') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyX'}), 'χ') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyX', shiftKey: true}), 'Χ') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyX', metaKey: true}), 'cmd-x') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyX', metaKey: true, shiftKey: true}), 'shift-cmd-X') + + # Don't use U.S. counterpart for latin characters + currentKeymap = require('./helpers/keymaps/turkish') + assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyX', metaKey: true}), 'cmd-ö') + describe "::findKeyBindings({command, target, keystrokes})", -> [elementA, elementB] = [] beforeEach -> diff --git a/src/helpers.coffee b/src/helpers.coffee index fdc4adf..4efcd04 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -23,6 +23,7 @@ NonPrintableKeyNamesByCode = { 'ArrowLeft': 'left', 'ArrowRight': 'right' } +EndOFLatinCharCodeRange = 0x024F exports.normalizeKeystrokes = (keystrokes) -> normalizedKeystrokes = [] @@ -41,6 +42,16 @@ exports.keystrokeForKeyboardEvent = (event, dvorakQwertyWorkaroundEnabled) -> unless key? key = event.code.toLowerCase() + # Use US equivalent character for non-latin characters in keystrokes with modifiers + keyIsNonLatin = key.length is 1 and key.charCodeAt(0) > EndOFLatinCharCodeRange + keystrokeHasModifiers = (event.ctrlKey or event.altKey or event.metaKey) + if keyIsNonLatin and keystrokeHasModifiers + if characters = usCharactersForKeyCode(event.code) + if event.shiftKey + key = characters.withShift + else + key = characters.unmodified + keystroke = '' if event.ctrlKey or key is 'ctrl' keystroke += 'ctrl' @@ -68,6 +79,7 @@ exports.keystrokeForKeyboardEvent = (event, dvorakQwertyWorkaroundEnabled) -> if event.metaKey or key is 'Meta' keystroke += '-' if keystroke keystroke += 'cmd' + if key? and not Modifiers.has(key) keystroke += '-' if keystroke keystroke += key @@ -293,3 +305,8 @@ isASCII = (charCode) -> numpadToASCII = (charCode) -> NumPadToASCII[charCode] ? charCode + +usKeymap = null +usCharactersForKeyCode = (code) -> + usKeymap ?= require('./us-keymap') + usKeymap[code] diff --git a/src/us-keymap.coffee b/src/us-keymap.coffee new file mode 100644 index 0000000..1bee929 --- /dev/null +++ b/src/us-keymap.coffee @@ -0,0 +1,380 @@ +module.exports = { + "Space": { + "unmodified": " ", + "withShift": " ", + "withAltGr": " ", + "withShiftAltGr": " " + }, + "Digit0": { + "unmodified": "0", + "withShift": ")", + "withAltGr": "º", + "withShiftAltGr": "‚" + }, + "Digit1": { + "unmodified": "1", + "withShift": "!", + "withAltGr": "¡", + "withShiftAltGr": "⁄" + }, + "Digit2": { + "unmodified": "2", + "withShift": "@", + "withAltGr": "™", + "withShiftAltGr": "€" + }, + "Digit3": { + "unmodified": "3", + "withShift": "#", + "withAltGr": "£", + "withShiftAltGr": "‹" + }, + "Digit4": { + "unmodified": "4", + "withShift": "$", + "withAltGr": "¢", + "withShiftAltGr": "›" + }, + "Digit5": { + "unmodified": "5", + "withShift": "%", + "withAltGr": "∞", + "withShiftAltGr": "fi" + }, + "Digit6": { + "unmodified": "6", + "withShift": "^", + "withAltGr": "§", + "withShiftAltGr": "fl" + }, + "Digit7": { + "unmodified": "7", + "withShift": "&", + "withAltGr": "¶", + "withShiftAltGr": "‡" + }, + "Digit8": { + "unmodified": "8", + "withShift": "*", + "withAltGr": "•", + "withShiftAltGr": "°" + }, + "Digit9": { + "unmodified": "9", + "withShift": "(", + "withAltGr": "ª", + "withShiftAltGr": "·" + }, + "KeyA": { + "unmodified": "a", + "withShift": "A", + "withAltGr": "å", + "withShiftAltGr": "Å" + }, + "KeyB": { + "unmodified": "b", + "withShift": "B", + "withAltGr": "∫", + "withShiftAltGr": "ı" + }, + "KeyC": { + "unmodified": "c", + "withShift": "C", + "withAltGr": "ç", + "withShiftAltGr": "Ç" + }, + "KeyD": { + "unmodified": "d", + "withShift": "D", + "withAltGr": "∂", + "withShiftAltGr": "Î" + }, + "KeyE": { + "unmodified": "e", + "withShift": "E", + "withAltGr": "", + "withShiftAltGr": "´" + }, + "KeyF": { + "unmodified": "f", + "withShift": "F", + "withAltGr": "ƒ", + "withShiftAltGr": "Ï" + }, + "KeyG": { + "unmodified": "g", + "withShift": "G", + "withAltGr": "©", + "withShiftAltGr": "˝" + }, + "KeyH": { + "unmodified": "h", + "withShift": "H", + "withAltGr": "˙", + "withShiftAltGr": "Ó" + }, + "KeyI": { + "unmodified": "i", + "withShift": "I", + "withAltGr": "", + "withShiftAltGr": "ˆ" + }, + "KeyJ": { + "unmodified": "j", + "withShift": "J", + "withAltGr": "∆", + "withShiftAltGr": "Ô" + }, + "KeyK": { + "unmodified": "k", + "withShift": "K", + "withAltGr": "˚", + "withShiftAltGr": "" + }, + "KeyL": { + "unmodified": "l", + "withShift": "L", + "withAltGr": "¬", + "withShiftAltGr": "Ò" + }, + "KeyM": { + "unmodified": "m", + "withShift": "M", + "withAltGr": "µ", + "withShiftAltGr": "Â" + }, + "KeyN": { + "unmodified": "n", + "withShift": "N", + "withAltGr": "", + "withShiftAltGr": "˜" + }, + "KeyO": { + "unmodified": "o", + "withShift": "O", + "withAltGr": "ø", + "withShiftAltGr": "Ø" + }, + "KeyP": { + "unmodified": "p", + "withShift": "P", + "withAltGr": "π", + "withShiftAltGr": "∏" + }, + "KeyQ": { + "unmodified": "q", + "withShift": "Q", + "withAltGr": "œ", + "withShiftAltGr": "Œ" + }, + "KeyR": { + "unmodified": "r", + "withShift": "R", + "withAltGr": "®", + "withShiftAltGr": "‰" + }, + "KeyS": { + "unmodified": "s", + "withShift": "S", + "withAltGr": "ß", + "withShiftAltGr": "Í" + }, + "KeyT": { + "unmodified": "t", + "withShift": "T", + "withAltGr": "†", + "withShiftAltGr": "ˇ" + }, + "KeyU": { + "unmodified": "u", + "withShift": "U", + "withAltGr": "", + "withShiftAltGr": "¨" + }, + "KeyV": { + "unmodified": "v", + "withShift": "V", + "withAltGr": "√", + "withShiftAltGr": "◊" + }, + "KeyW": { + "unmodified": "w", + "withShift": "W", + "withAltGr": "∑", + "withShiftAltGr": "„" + }, + "KeyX": { + "unmodified": "x", + "withShift": "X", + "withAltGr": "≈", + "withShiftAltGr": "˛" + }, + "KeyY": { + "unmodified": "y", + "withShift": "Y", + "withAltGr": "¥", + "withShiftAltGr": "Á" + }, + "KeyZ": { + "unmodified": "z", + "withShift": "Z", + "withAltGr": "Ω", + "withShiftAltGr": "¸" + }, + "Numpad0": { + "unmodified": "0", + "withShift": "0", + "withAltGr": "0", + "withShiftAltGr": "0" + }, + "Numpad1": { + "unmodified": "1", + "withShift": "1", + "withAltGr": "1", + "withShiftAltGr": "1" + }, + "Numpad2": { + "unmodified": "2", + "withShift": "2", + "withAltGr": "2", + "withShiftAltGr": "2" + }, + "Numpad3": { + "unmodified": "3", + "withShift": "3", + "withAltGr": "3", + "withShiftAltGr": "3" + }, + "Numpad4": { + "unmodified": "4", + "withShift": "4", + "withAltGr": "4", + "withShiftAltGr": "4" + }, + "Numpad5": { + "unmodified": "5", + "withShift": "5", + "withAltGr": "5", + "withShiftAltGr": "5" + }, + "Numpad6": { + "unmodified": "6", + "withShift": "6", + "withAltGr": "6", + "withShiftAltGr": "6" + }, + "Numpad7": { + "unmodified": "7", + "withShift": "7", + "withAltGr": "7", + "withShiftAltGr": "7" + }, + "Numpad8": { + "unmodified": "8", + "withShift": "8", + "withAltGr": "8", + "withShiftAltGr": "8" + }, + "Numpad9": { + "unmodified": "9", + "withShift": "9", + "withAltGr": "9", + "withShiftAltGr": "9" + }, + "NumpadMultiply": { + "unmodified": "*", + "withShift": "*", + "withAltGr": "*", + "withShiftAltGr": "*" + }, + "NumpadAdd": { + "unmodified": "+", + "withShift": "+", + "withAltGr": "+", + "withShiftAltGr": "+" + }, + "NumpadSubtract": { + "unmodified": "-", + "withShift": "-", + "withAltGr": "-", + "withShiftAltGr": "-" + }, + "NumpadDecimal": { + "unmodified": ".", + "withShift": ".", + "withAltGr": ".", + "withShiftAltGr": "." + }, + "NumpadDivide": { + "unmodified": "/", + "withShift": "/", + "withAltGr": "/", + "withShiftAltGr": "/" + }, + "Semicolon": { + "unmodified": ";", + "withShift": ":", + "withAltGr": "…", + "withShiftAltGr": "Ú" + }, + "Equal": { + "unmodified": "=", + "withShift": "+", + "withAltGr": "≠", + "withShiftAltGr": "±" + }, + "NumpadComma": { + "unmodified": ",", + "withShift": "<", + "withAltGr": "≤", + "withShiftAltGr": "¯" + }, + "Minus": { + "unmodified": "-", + "withShift": "_", + "withAltGr": "–", + "withShiftAltGr": "—" + }, + "Period": { + "unmodified": ".", + "withShift": ">", + "withAltGr": "≥", + "withShiftAltGr": "˘" + }, + "Slash": { + "unmodified": "/", + "withShift": "?", + "withAltGr": "÷", + "withShiftAltGr": "¿" + }, + "Backquote": { + "unmodified": "`", + "withShift": "~", + "withAltGr": "", + "withShiftAltGr": "`" + }, + "BracketLeft": { + "unmodified": "[", + "withShift": "{", + "withAltGr": "“", + "withShiftAltGr": "”" + }, + "IntlYen": { + "unmodified": "\\", + "withShift": "|", + "withAltGr": "«", + "withShiftAltGr": "»" + }, + "BracketRight": { + "unmodified": "]", + "withShift": "}", + "withAltGr": "‘", + "withShiftAltGr": "’" + }, + "Quote": { + "unmodified": "'", + "withShift": "\"", + "withAltGr": "æ", + "withShiftAltGr": "Æ" + } +} From 2fbabdeb65f19a6732b001d7e1673295f596dc4a Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 9 Sep 2016 12:25:24 -0700 Subject: [PATCH 06/24] Avoid passing keystroke string to buildKeydownEvent in spec --- spec/keymap-manager-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/keymap-manager-spec.coffee b/spec/keymap-manager-spec.coffee index 3f8ad95..1b2a967 100644 --- a/spec/keymap-manager-spec.coffee +++ b/spec/keymap-manager-spec.coffee @@ -316,7 +316,7 @@ describe "KeymapManager", -> workspace.addEventListener 'control-dog', -> events.push('control-dog') - keymapManager.handleKeyboardEvent(buildKeydownEvent('ctrl-d', target: editor)) + keymapManager.handleKeyboardEvent(buildKeydownEvent('d', ctrl: true, target: editor)) keymapManager.handleKeyboardEvent(buildKeydownEvent('o', target: editor)) getFakeClock().tick(keymapManager.getPartialMatchTimeout()) From 805336f06d947af6db8f8a6c71e660abbf2a0e96 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 9 Sep 2016 12:26:19 -0700 Subject: [PATCH 07/24] Use KeyboardLayout.getCurrentKeymap, not .charactersForKeyCode --- spec/keymap-manager-spec.coffee | 2 +- src/helpers.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/keymap-manager-spec.coffee b/spec/keymap-manager-spec.coffee index 1b2a967..e69fc20 100644 --- a/spec/keymap-manager-spec.coffee +++ b/spec/keymap-manager-spec.coffee @@ -585,7 +585,7 @@ describe "KeymapManager", -> beforeEach -> currentKeymap = null - stub(KeyboardLayout, 'charactersForKeyCode', (code) -> currentKeymap[code]) + stub(KeyboardLayout, 'getCurrentKeymap', -> currentKeymap) describe "when no extra modifiers are pressed", -> it "returns a string that identifies the unmodified keystroke", -> diff --git a/src/helpers.coffee b/src/helpers.coffee index 4efcd04..5543985 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -37,7 +37,7 @@ exports.normalizeKeystrokes = (keystrokes) -> exports.keystrokeForKeyboardEvent = (event, dvorakQwertyWorkaroundEnabled) -> key = NonPrintableKeyNamesByCode[event.code] unless key? - if characters = KeyboardLayout.charactersForKeyCode(event.code) + if characters = KeyboardLayout.getCurrentKeymap()[event.code] key = characters.unmodified unless key? key = event.code.toLowerCase() From a508c42511f9d209546c8e0f0b0b3f4271fac177 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 9 Sep 2016 12:28:47 -0700 Subject: [PATCH 08/24] Don't use US equivalent for events w/ alt as the only modifier Signed-off-by: Nathan Sobo --- src/helpers.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers.coffee b/src/helpers.coffee index 5543985..8536f4e 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -44,7 +44,7 @@ exports.keystrokeForKeyboardEvent = (event, dvorakQwertyWorkaroundEnabled) -> # Use US equivalent character for non-latin characters in keystrokes with modifiers keyIsNonLatin = key.length is 1 and key.charCodeAt(0) > EndOFLatinCharCodeRange - keystrokeHasModifiers = (event.ctrlKey or event.altKey or event.metaKey) + keystrokeHasModifiers = (event.ctrlKey or event.metaKey) if keyIsNonLatin and keystrokeHasModifiers if characters = usCharactersForKeyCode(event.code) if event.shiftKey From dc618982c6bd6ed98d9f1b6bec5d599f6325f076 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 9 Sep 2016 12:28:54 -0700 Subject: [PATCH 09/24] Implement text input replay using KeyboardLayout.getCurrentKeymap() Signed-off-by: Nathan Sobo --- src/helpers.coffee | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/helpers.coffee b/src/helpers.coffee index 8536f4e..d478fdc 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -87,10 +87,18 @@ exports.keystrokeForKeyboardEvent = (event, dvorakQwertyWorkaroundEnabled) -> keystroke = normalizeKeystroke("^#{keystroke}") if event.type is 'keyup' keystroke -exports.characterForKeyboardEvent = (event, dvorakQwertyWorkaroundEnabled) -> - unless event.ctrlKey or event.altKey or event.metaKey - if key = keyForKeyboardEvent(event, dvorakQwertyWorkaroundEnabled) - key if key.length is 1 +exports.characterForKeyboardEvent = (event, allowModifiers = false) -> + unless event.ctrlKey or event.metaKey + if characters = KeyboardLayout.getCurrentKeymap()[event.code] + if event.shiftKey + if event.altKey + return characters.withShiftAltGr + else + return characters.withShift + else if event.altKey + return characters.withAltGr + else + return characters.unmodified exports.calculateSpecificity = calculateSpecificity From 4df69d1bdc98ef620cbbd7408cdf7de318d1ccac Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 9 Sep 2016 12:28:57 -0700 Subject: [PATCH 10/24] Switch buildKeydownEvent to use new keyboard event APIs Signed-off-by: Nathan Sobo --- src/helpers.coffee | 51 +++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/src/helpers.coffee b/src/helpers.coffee index d478fdc..cb1ad7b 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -112,38 +112,37 @@ exports.keyupEvent = (key, options) -> return keyboardEvent(key, 'keyup', options) keyboardEvent = (key, eventType, {ctrl, shift, alt, cmd, keyCode, target, location}={}) -> - event = document.createEvent('KeyboardEvent') + ctrlKey = ctrl ? false + altKey = alt ? false + shiftKey = shift ? false + metaKey = cmd ? false bubbles = true cancelable = true - view = null + code = Object.keys(NonPrintableKeyNamesByCode).find (candidateCode) -> + NonPrintableKeyNamesByCode[candidateCode] is key + + unless code? + for candidateCode, characters of KeyboardLayout.getCurrentKeymap() + if characters.unmodified is key + code = candidateCode + else if characters.withShift is key + code = candidateCode + shiftKey = true + else if characters.withAltGr is key + code = candidateCode + altKey = true + else if characters.withShiftAltGr is key + code = candidateCode + altKey = true + shiftKey = true + + event = new KeyboardEvent(eventType, { + code, ctrlKey, altKey, shiftKey, metaKey, bubbles, cancelable + }) - key = key.toUpperCase() if LowerCaseLetterRegex.test(key) - if key.length is 1 - keyIdentifier = "U+#{key.charCodeAt(0).toString(16)}" - else - switch key - when 'ctrl' - keyIdentifier = 'Control' - ctrl = true if eventType isnt 'keyup' - when 'alt' - keyIdentifier = 'Alt' - alt = true if eventType isnt 'keyup' - when 'shift' - keyIdentifier = 'Shift' - shift = true if eventType isnt 'keyup' - when 'cmd' - keyIdentifier = 'Meta' - cmd = true if eventType isnt 'keyup' - else - keyIdentifier = key[0].toUpperCase() + key[1..] - - location ?= KeyboardEvent.DOM_KEY_LOCATION_STANDARD - event.initKeyboardEvent(eventType, bubbles, cancelable, view, keyIdentifier, location, ctrl, alt, shift, cmd) if target? Object.defineProperty(event, 'target', get: -> target) Object.defineProperty(event, 'path', get: -> [target]) - Object.defineProperty(event, 'keyCode', get: -> keyCode) - Object.defineProperty(event, 'which', get: -> keyCode) event # bindingKeystrokes and userKeystrokes are arrays of keystrokes From 924409a714314eb13a388ed8911be66f1250333f Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 13 Sep 2016 15:45:12 -0700 Subject: [PATCH 11/24] Use KeyboardEvent.key property as much as possible The only time that we can't use KeyboardEvent.key is on macOS when the option key is held down. In that case, the .key property will contain an alternative character. In order to match alt bindings, we need to know the character that the key would have typed if option were not held down. We determine this character using the keyboard-layout module. Signed-off-by: Nathan Sobo --- spec/helpers/helpers.js | 11 +- spec/helpers/keymaps/dvorak.json | 380 ------------------------- spec/helpers/keymaps/greek.json | 252 ++++++++-------- spec/helpers/keymaps/swiss-german.json | 252 ++++++++-------- spec/helpers/keymaps/turkish.json | 252 ++++++++-------- spec/keymap-manager-spec.coffee | 114 +++++--- src/helpers.coffee | 125 ++++---- src/us-keymap.coffee | 252 ++++------------ 8 files changed, 574 insertions(+), 1064 deletions(-) delete mode 100644 spec/helpers/keymaps/dvorak.json diff --git a/spec/helpers/helpers.js b/spec/helpers/helpers.js index 76825ee..6d3be54 100644 --- a/spec/helpers/helpers.js +++ b/spec/helpers/helpers.js @@ -5,7 +5,11 @@ import lolex from 'lolex' import sinon from 'sinon' -let sinonSandbox, fakeClock +let sinonSandbox, fakeClock, processPlatform, originalProcessPlatform + +originalProcessPlatform = process.platform +processPlatform = process.platform +Object.defineProperty(process, 'platform', {get: () => processPlatform}) beforeEach(function () { document.body.innerHTML = '' @@ -16,6 +20,7 @@ beforeEach(function () { afterEach(function () { fakeClock.uninstall() sinonSandbox.restore() + processPlatform = originalProcessPlatform }) export function appendContent (element) { @@ -30,3 +35,7 @@ export function stub () { export function getFakeClock () { return fakeClock } + +export function mockProcessPlatform (platform) { + processPlatform = platform +} diff --git a/spec/helpers/keymaps/dvorak.json b/spec/helpers/keymaps/dvorak.json deleted file mode 100644 index 880bc5b..0000000 --- a/spec/helpers/keymaps/dvorak.json +++ /dev/null @@ -1,380 +0,0 @@ -{ - "Space": { - "unmodified": " ", - "withShift": " ", - "withAltGr": " ", - "withShiftAltGr": " " - }, - "Digit0": { - "unmodified": "0", - "withShift": ")", - "withAltGr": "º", - "withShiftAltGr": "‚" - }, - "Digit1": { - "unmodified": "1", - "withShift": "!", - "withAltGr": "¡", - "withShiftAltGr": "⁄" - }, - "Digit2": { - "unmodified": "2", - "withShift": "@", - "withAltGr": "™", - "withShiftAltGr": "€" - }, - "Digit3": { - "unmodified": "3", - "withShift": "#", - "withAltGr": "£", - "withShiftAltGr": "‹" - }, - "Digit4": { - "unmodified": "4", - "withShift": "$", - "withAltGr": "¢", - "withShiftAltGr": "›" - }, - "Digit5": { - "unmodified": "5", - "withShift": "%", - "withAltGr": "∞", - "withShiftAltGr": "fi" - }, - "Digit6": { - "unmodified": "6", - "withShift": "^", - "withAltGr": "§", - "withShiftAltGr": "fl" - }, - "Digit7": { - "unmodified": "7", - "withShift": "&", - "withAltGr": "¶", - "withShiftAltGr": "‡" - }, - "Digit8": { - "unmodified": "8", - "withShift": "*", - "withAltGr": "•", - "withShiftAltGr": "°" - }, - "Digit9": { - "unmodified": "9", - "withShift": "(", - "withAltGr": "ª", - "withShiftAltGr": "·" - }, - "KeyA": { - "unmodified": "a", - "withShift": "A", - "withAltGr": "å", - "withShiftAltGr": "Å" - }, - "KeyB": { - "unmodified": "x", - "withShift": "X", - "withAltGr": "≈", - "withShiftAltGr": "˛" - }, - "KeyC": { - "unmodified": "j", - "withShift": "J", - "withAltGr": "∆", - "withShiftAltGr": "Ô" - }, - "KeyD": { - "unmodified": "e", - "withShift": "E", - "withAltGr": "", - "withShiftAltGr": "´" - }, - "KeyE": { - "unmodified": ".", - "withShift": ">", - "withAltGr": "≥", - "withShiftAltGr": "˘" - }, - "KeyF": { - "unmodified": "u", - "withShift": "U", - "withAltGr": "", - "withShiftAltGr": "¨" - }, - "KeyG": { - "unmodified": "i", - "withShift": "I", - "withAltGr": "", - "withShiftAltGr": "ˆ" - }, - "KeyH": { - "unmodified": "d", - "withShift": "D", - "withAltGr": "∂", - "withShiftAltGr": "Î" - }, - "KeyI": { - "unmodified": "c", - "withShift": "C", - "withAltGr": "ç", - "withShiftAltGr": "Ç" - }, - "KeyJ": { - "unmodified": "h", - "withShift": "H", - "withAltGr": "˙", - "withShiftAltGr": "Ó" - }, - "KeyK": { - "unmodified": "t", - "withShift": "T", - "withAltGr": "†", - "withShiftAltGr": "ˇ" - }, - "KeyL": { - "unmodified": "n", - "withShift": "N", - "withAltGr": "", - "withShiftAltGr": "˜" - }, - "KeyM": { - "unmodified": "m", - "withShift": "M", - "withAltGr": "µ", - "withShiftAltGr": "Â" - }, - "KeyN": { - "unmodified": "b", - "withShift": "B", - "withAltGr": "∫", - "withShiftAltGr": "ı" - }, - "KeyO": { - "unmodified": "r", - "withShift": "R", - "withAltGr": "®", - "withShiftAltGr": "‰" - }, - "KeyP": { - "unmodified": "l", - "withShift": "L", - "withAltGr": "¬", - "withShiftAltGr": "Ò" - }, - "KeyQ": { - "unmodified": "'", - "withShift": "\"", - "withAltGr": "æ", - "withShiftAltGr": "Æ" - }, - "KeyR": { - "unmodified": "p", - "withShift": "P", - "withAltGr": "π", - "withShiftAltGr": "∏" - }, - "KeyS": { - "unmodified": "o", - "withShift": "O", - "withAltGr": "ø", - "withShiftAltGr": "Ø" - }, - "KeyT": { - "unmodified": "y", - "withShift": "Y", - "withAltGr": "¥", - "withShiftAltGr": "Á" - }, - "KeyU": { - "unmodified": "g", - "withShift": "G", - "withAltGr": "©", - "withShiftAltGr": "˝" - }, - "KeyV": { - "unmodified": "k", - "withShift": "K", - "withAltGr": "˚", - "withShiftAltGr": "" - }, - "KeyW": { - "unmodified": ",", - "withShift": "<", - "withAltGr": "≤", - "withShiftAltGr": "¯" - }, - "KeyX": { - "unmodified": "q", - "withShift": "Q", - "withAltGr": "œ", - "withShiftAltGr": "Œ" - }, - "KeyY": { - "unmodified": "f", - "withShift": "F", - "withAltGr": "ƒ", - "withShiftAltGr": "Ï" - }, - "KeyZ": { - "unmodified": ";", - "withShift": ":", - "withAltGr": "…", - "withShiftAltGr": "Ú" - }, - "Numpad0": { - "unmodified": "0", - "withShift": "0", - "withAltGr": "0", - "withShiftAltGr": "0" - }, - "Numpad1": { - "unmodified": "1", - "withShift": "1", - "withAltGr": "1", - "withShiftAltGr": "1" - }, - "Numpad2": { - "unmodified": "2", - "withShift": "2", - "withAltGr": "2", - "withShiftAltGr": "2" - }, - "Numpad3": { - "unmodified": "3", - "withShift": "3", - "withAltGr": "3", - "withShiftAltGr": "3" - }, - "Numpad4": { - "unmodified": "4", - "withShift": "4", - "withAltGr": "4", - "withShiftAltGr": "4" - }, - "Numpad5": { - "unmodified": "5", - "withShift": "5", - "withAltGr": "5", - "withShiftAltGr": "5" - }, - "Numpad6": { - "unmodified": "6", - "withShift": "6", - "withAltGr": "6", - "withShiftAltGr": "6" - }, - "Numpad7": { - "unmodified": "7", - "withShift": "7", - "withAltGr": "7", - "withShiftAltGr": "7" - }, - "Numpad8": { - "unmodified": "8", - "withShift": "8", - "withAltGr": "8", - "withShiftAltGr": "8" - }, - "Numpad9": { - "unmodified": "9", - "withShift": "9", - "withAltGr": "9", - "withShiftAltGr": "9" - }, - "NumpadMultiply": { - "unmodified": "*", - "withShift": "*", - "withAltGr": "*", - "withShiftAltGr": "*" - }, - "NumpadAdd": { - "unmodified": "+", - "withShift": "+", - "withAltGr": "+", - "withShiftAltGr": "+" - }, - "NumpadSubtract": { - "unmodified": "-", - "withShift": "-", - "withAltGr": "-", - "withShiftAltGr": "-" - }, - "NumpadDecimal": { - "unmodified": ".", - "withShift": ".", - "withAltGr": ".", - "withShiftAltGr": "." - }, - "NumpadDivide": { - "unmodified": "/", - "withShift": "/", - "withAltGr": "/", - "withShiftAltGr": "/" - }, - "Semicolon": { - "unmodified": "s", - "withShift": "S", - "withAltGr": "ß", - "withShiftAltGr": "Í" - }, - "Equal": { - "unmodified": "]", - "withShift": "}", - "withAltGr": "‘", - "withShiftAltGr": "’" - }, - "NumpadComma": { - "unmodified": "w", - "withShift": "W", - "withAltGr": "∑", - "withShiftAltGr": "„" - }, - "Minus": { - "unmodified": "[", - "withShift": "{", - "withAltGr": "“", - "withShiftAltGr": "”" - }, - "Period": { - "unmodified": "v", - "withShift": "V", - "withAltGr": "√", - "withShiftAltGr": "◊" - }, - "Slash": { - "unmodified": "z", - "withShift": "Z", - "withAltGr": "Ω", - "withShiftAltGr": "¸" - }, - "Backquote": { - "unmodified": "`", - "withShift": "~", - "withAltGr": "", - "withShiftAltGr": "`" - }, - "BracketLeft": { - "unmodified": "/", - "withShift": "?", - "withAltGr": "÷", - "withShiftAltGr": "¿" - }, - "IntlYen": { - "unmodified": "\\", - "withShift": "|", - "withAltGr": "«", - "withShiftAltGr": "»" - }, - "BracketRight": { - "unmodified": "=", - "withShift": "+", - "withAltGr": "≠", - "withShiftAltGr": "±" - }, - "Quote": { - "unmodified": "-", - "withShift": "_", - "withAltGr": "–", - "withShiftAltGr": "—" - } -} diff --git a/spec/helpers/keymaps/greek.json b/spec/helpers/keymaps/greek.json index 1fd47ff..80b9fcd 100644 --- a/spec/helpers/keymaps/greek.json +++ b/spec/helpers/keymaps/greek.json @@ -2,379 +2,379 @@ "Space": { "unmodified": " ", "withShift": " ", - "withAltGr": " ", - "withShiftAltGr": " " + "withOption": " ", + "withOptionShift": " " }, "Digit0": { "unmodified": "0", "withShift": ")", - "withAltGr": "°", - "withShiftAltGr": "ύ" + "withOption": "°", + "withOptionShift": "ύ" }, "Digit1": { "unmodified": "1", "withShift": "!", - "withAltGr": "¹", - "withShiftAltGr": "έ" + "withOption": "¹", + "withOptionShift": "έ" }, "Digit2": { "unmodified": "2", "withShift": "@", - "withAltGr": "²", - "withShiftAltGr": "ί" + "withOption": "²", + "withOptionShift": "ί" }, "Digit3": { "unmodified": "3", "withShift": "#", - "withAltGr": "³", - "withShiftAltGr": "ή" + "withOption": "³", + "withOptionShift": "ή" }, "Digit4": { "unmodified": "4", "withShift": "$", - "withAltGr": "£", - "withShiftAltGr": "ό" + "withOption": "£", + "withOptionShift": "ό" }, "Digit5": { "unmodified": "5", "withShift": "%", - "withAltGr": "§", - "withShiftAltGr": "Ώ" + "withOption": "§", + "withOptionShift": "Ώ" }, "Digit6": { "unmodified": "6", "withShift": "^", - "withAltGr": "¶", - "withShiftAltGr": "^" + "withOption": "¶", + "withOptionShift": "^" }, "Digit7": { "unmodified": "7", "withShift": "&", - "withAltGr": "°", - "withShiftAltGr": "" + "withOption": "°", + "withOptionShift": "" }, "Digit8": { "unmodified": "8", "withShift": "*", - "withAltGr": "•", - "withShiftAltGr": "Ρ" + "withOption": "•", + "withOptionShift": "Ρ" }, "Digit9": { "unmodified": "9", "withShift": "(", - "withAltGr": "“", - "withShiftAltGr": "Κ" + "withOption": "“", + "withOptionShift": "Κ" }, "KeyA": { "unmodified": "α", "withShift": "Α", - "withAltGr": "…", - "withShiftAltGr": "ά" + "withOption": "…", + "withOptionShift": "ά" }, "KeyB": { "unmodified": "β", "withShift": "Β", - "withAltGr": "", - "withShiftAltGr": "" + "withOption": "", + "withOptionShift": "" }, "KeyC": { "unmodified": "ψ", "withShift": "Ψ", - "withAltGr": "ç", - "withShiftAltGr": "Χ" + "withOption": "ç", + "withOptionShift": "Χ" }, "KeyD": { "unmodified": "δ", "withShift": "Δ", - "withAltGr": "÷", - "withShiftAltGr": "" + "withOption": "÷", + "withOptionShift": "" }, "KeyE": { "unmodified": "ε", "withShift": "Ε", - "withAltGr": "€", - "withShiftAltGr": "Έ" + "withOption": "€", + "withOptionShift": "Έ" }, "KeyF": { "unmodified": "φ", "withShift": "Φ", - "withAltGr": "≠", - "withShiftAltGr": "Π" + "withOption": "≠", + "withOptionShift": "Π" }, "KeyG": { "unmodified": "γ", "withShift": "Γ", - "withAltGr": "©", - "withShiftAltGr": "Ϊ" + "withOption": "©", + "withOptionShift": "Ϊ" }, "KeyH": { "unmodified": "η", "withShift": "Η", - "withAltGr": "½", - "withShiftAltGr": "≠" + "withOption": "½", + "withOptionShift": "≠" }, "KeyI": { "unmodified": "ι", "withShift": "Ι", - "withAltGr": "†", - "withShiftAltGr": "Ν" + "withOption": "†", + "withOptionShift": "Ν" }, "KeyJ": { "unmodified": "ξ", "withShift": "Ξ", - "withAltGr": "≤", - "withShiftAltGr": "§" + "withOption": "≤", + "withOptionShift": "§" }, "KeyK": { "unmodified": "κ", "withShift": "Κ", - "withAltGr": "≥", - "withShiftAltGr": "°" + "withOption": "≥", + "withOptionShift": "°" }, "KeyL": { "unmodified": "λ", "withShift": "Λ", - "withAltGr": "¬", - "withShiftAltGr": "·" + "withOption": "¬", + "withOptionShift": "·" }, "KeyM": { "unmodified": "μ", "withShift": "Μ", - "withAltGr": "’", - "withShiftAltGr": "Ύ" + "withOption": "’", + "withOptionShift": "Ύ" }, "KeyN": { "unmodified": "ν", "withShift": "Ν", - "withAltGr": "‘", - "withShiftAltGr": "Ό" + "withOption": "‘", + "withOptionShift": "Ό" }, "KeyO": { "unmodified": "ο", "withShift": "Ο", - "withAltGr": "œ", - "withShiftAltGr": "Τ" + "withOption": "œ", + "withOptionShift": "Τ" }, "KeyP": { "unmodified": "π", "withShift": "Π", - "withAltGr": "≈", - "withShiftAltGr": "" + "withOption": "≈", + "withOptionShift": "" }, "KeyQ": { "unmodified": ";", "withShift": ":", - "withAltGr": "·", - "withShiftAltGr": "―" + "withOption": "·", + "withOptionShift": "―" }, "KeyR": { "unmodified": "ρ", "withShift": "Ρ", - "withAltGr": "®", - "withShiftAltGr": "Δ" + "withOption": "®", + "withOptionShift": "Δ" }, "KeyS": { "unmodified": "σ", "withShift": "Σ", - "withAltGr": "ß", - "withShiftAltGr": "ρ" + "withOption": "ß", + "withOptionShift": "ρ" }, "KeyT": { "unmodified": "τ", "withShift": "Τ", - "withAltGr": "™", - "withShiftAltGr": "" + "withOption": "™", + "withOptionShift": "" }, "KeyU": { "unmodified": "θ", "withShift": "Θ", - "withAltGr": "­", - "withShiftAltGr": "Ξ" + "withOption": "­", + "withOptionShift": "Ξ" }, "KeyV": { "unmodified": "ω", "withShift": "Ω", - "withAltGr": "±", - "withShiftAltGr": "Ά" + "withOption": "±", + "withOptionShift": "Ά" }, "KeyW": { "unmodified": "ς", "withShift": "", - "withAltGr": "―", - "withShiftAltGr": "Β" + "withOption": "―", + "withOptionShift": "Β" }, "KeyX": { "unmodified": "χ", "withShift": "Χ", - "withAltGr": "", - "withShiftAltGr": "" + "withOption": "", + "withOptionShift": "" }, "KeyY": { "unmodified": "υ", "withShift": "Υ", - "withAltGr": "¥", - "withShiftAltGr": "" + "withOption": "¥", + "withOptionShift": "" }, "KeyZ": { "unmodified": "ζ", "withShift": "Ζ", - "withAltGr": "§", - "withShiftAltGr": "" + "withOption": "§", + "withOptionShift": "" }, "Numpad0": { "unmodified": "0", "withShift": "0", - "withAltGr": "0", - "withShiftAltGr": "0" + "withOption": "0", + "withOptionShift": "0" }, "Numpad1": { "unmodified": "1", "withShift": "1", - "withAltGr": "1", - "withShiftAltGr": "1" + "withOption": "1", + "withOptionShift": "1" }, "Numpad2": { "unmodified": "2", "withShift": "2", - "withAltGr": "2", - "withShiftAltGr": "2" + "withOption": "2", + "withOptionShift": "2" }, "Numpad3": { "unmodified": "3", "withShift": "3", - "withAltGr": "3", - "withShiftAltGr": "3" + "withOption": "3", + "withOptionShift": "3" }, "Numpad4": { "unmodified": "4", "withShift": "4", - "withAltGr": "4", - "withShiftAltGr": "4" + "withOption": "4", + "withOptionShift": "4" }, "Numpad5": { "unmodified": "5", "withShift": "5", - "withAltGr": "5", - "withShiftAltGr": "5" + "withOption": "5", + "withOptionShift": "5" }, "Numpad6": { "unmodified": "6", "withShift": "6", - "withAltGr": "6", - "withShiftAltGr": "6" + "withOption": "6", + "withOptionShift": "6" }, "Numpad7": { "unmodified": "7", "withShift": "7", - "withAltGr": "7", - "withShiftAltGr": "7" + "withOption": "7", + "withOptionShift": "7" }, "Numpad8": { "unmodified": "8", "withShift": "8", - "withAltGr": "8", - "withShiftAltGr": "8" + "withOption": "8", + "withOptionShift": "8" }, "Numpad9": { "unmodified": "9", "withShift": "9", - "withAltGr": "9", - "withShiftAltGr": "9" + "withOption": "9", + "withOptionShift": "9" }, "NumpadMultiply": { "unmodified": "*", "withShift": "*", - "withAltGr": "*", - "withShiftAltGr": "*" + "withOption": "*", + "withOptionShift": "*" }, "NumpadAdd": { "unmodified": "+", "withShift": "+", - "withAltGr": "+", - "withShiftAltGr": "+" + "withOption": "+", + "withOptionShift": "+" }, "NumpadSubtract": { "unmodified": "-", "withShift": "-", - "withAltGr": "-", - "withShiftAltGr": "-" + "withOption": "-", + "withOptionShift": "-" }, "NumpadDecimal": { "unmodified": ".", "withShift": ".", - "withAltGr": ".", - "withShiftAltGr": "." + "withOption": ".", + "withOptionShift": "." }, "NumpadDivide": { "unmodified": "/", "withShift": "/", - "withAltGr": "/", - "withShiftAltGr": "/" + "withOption": "/", + "withOptionShift": "/" }, "Semicolon": { "unmodified": "", "withShift": "", - "withAltGr": "", - "withShiftAltGr": ":" + "withOption": "", + "withOptionShift": ":" }, "Equal": { "unmodified": "=", "withShift": "+", - "withAltGr": "½", - "withShiftAltGr": "+" + "withOption": "½", + "withOptionShift": "+" }, "NumpadComma": { "unmodified": ",", "withShift": "<", - "withAltGr": "«", - "withShiftAltGr": "" + "withOption": "«", + "withOptionShift": "" }, "Minus": { "unmodified": "-", "withShift": "_", - "withAltGr": "±", - "withShiftAltGr": "_" + "withOption": "±", + "withOptionShift": "_" }, "Period": { "unmodified": ".", "withShift": ">", - "withAltGr": "»", - "withShiftAltGr": "ώ" + "withOption": "»", + "withOptionShift": "ώ" }, "Slash": { "unmodified": "/", "withShift": "?", - "withAltGr": "/", - "withShiftAltGr": "?" + "withOption": "/", + "withOptionShift": "?" }, "Backquote": { "unmodified": "`", "withShift": "~", - "withAltGr": "`", - "withShiftAltGr": "Μ" + "withOption": "`", + "withOptionShift": "Μ" }, "BracketLeft": { "unmodified": "[", "withShift": "{", - "withAltGr": "«", - "withShiftAltGr": "{" + "withOption": "«", + "withOptionShift": "{" }, "IntlYen": { "unmodified": "\\", "withShift": "|", - "withAltGr": "¦", - "withShiftAltGr": "Ζ" + "withOption": "¦", + "withOptionShift": "Ζ" }, "BracketRight": { "unmodified": "]", "withShift": "}", - "withAltGr": "»", - "withShiftAltGr": "}" + "withOption": "»", + "withOptionShift": "}" }, "Quote": { "unmodified": "'", "withShift": "\"", - "withAltGr": "'", - "withShiftAltGr": "\"" + "withOption": "'", + "withOptionShift": "\"" } } diff --git a/spec/helpers/keymaps/swiss-german.json b/spec/helpers/keymaps/swiss-german.json index 2e39c43..e1a0b31 100644 --- a/spec/helpers/keymaps/swiss-german.json +++ b/spec/helpers/keymaps/swiss-german.json @@ -2,379 +2,379 @@ "Space": { "unmodified": " ", "withShift": " ", - "withAltGr": " ", - "withShiftAltGr": " " + "withOption": " ", + "withOptionShift": " " }, "Digit0": { "unmodified": "0", "withShift": "=", - "withAltGr": "≠", - "withShiftAltGr": "Ú" + "withOption": "≠", + "withOptionShift": "Ú" }, "Digit1": { "unmodified": "1", "withShift": "+", - "withAltGr": "±", - "withShiftAltGr": "∞" + "withOption": "±", + "withOptionShift": "∞" }, "Digit2": { "unmodified": "2", "withShift": "\"", - "withAltGr": "“", - "withShiftAltGr": "”" + "withOption": "“", + "withOptionShift": "”" }, "Digit3": { "unmodified": "3", "withShift": "*", - "withAltGr": "#", - "withShiftAltGr": "‹" + "withOption": "#", + "withOptionShift": "‹" }, "Digit4": { "unmodified": "4", "withShift": "ç", - "withAltGr": "Ç", - "withShiftAltGr": "⁄" + "withOption": "Ç", + "withOptionShift": "⁄" }, "Digit5": { "unmodified": "5", "withShift": "%", - "withAltGr": "[", - "withShiftAltGr": "[" + "withOption": "[", + "withOptionShift": "[" }, "Digit6": { "unmodified": "6", "withShift": "&", - "withAltGr": "]", - "withShiftAltGr": "]" + "withOption": "]", + "withOptionShift": "]" }, "Digit7": { "unmodified": "7", "withShift": "/", - "withAltGr": "|", - "withShiftAltGr": "\\" + "withOption": "|", + "withOptionShift": "\\" }, "Digit8": { "unmodified": "8", "withShift": "(", - "withAltGr": "{", - "withShiftAltGr": "Ò" + "withOption": "{", + "withOptionShift": "Ò" }, "Digit9": { "unmodified": "9", "withShift": ")", - "withAltGr": "}", - "withShiftAltGr": "Ô" + "withOption": "}", + "withOptionShift": "Ô" }, "KeyA": { "unmodified": "a", "withShift": "A", - "withAltGr": "å", - "withShiftAltGr": "Å" + "withOption": "å", + "withOptionShift": "Å" }, "KeyB": { "unmodified": "b", "withShift": "B", - "withAltGr": "∫", - "withShiftAltGr": "" + "withOption": "∫", + "withOptionShift": "" }, "KeyC": { "unmodified": "c", "withShift": "C", - "withAltGr": "©", - "withShiftAltGr": "" + "withOption": "©", + "withOptionShift": "" }, "KeyD": { "unmodified": "d", "withShift": "D", - "withAltGr": "∂", - "withShiftAltGr": "fl" + "withOption": "∂", + "withOptionShift": "fl" }, "KeyE": { "unmodified": "e", "withShift": "E", - "withAltGr": "€", - "withShiftAltGr": "Ë" + "withOption": "€", + "withOptionShift": "Ë" }, "KeyF": { "unmodified": "f", "withShift": "F", - "withAltGr": "ƒ", - "withShiftAltGr": "‡" + "withOption": "ƒ", + "withOptionShift": "‡" }, "KeyG": { "unmodified": "g", "withShift": "G", - "withAltGr": "@", - "withShiftAltGr": "‚" + "withOption": "@", + "withOptionShift": "‚" }, "KeyH": { "unmodified": "h", "withShift": "H", - "withAltGr": "ª", - "withShiftAltGr": "·" + "withOption": "ª", + "withOptionShift": "·" }, "KeyI": { "unmodified": "i", "withShift": "I", - "withAltGr": "¡", - "withShiftAltGr": "ı" + "withOption": "¡", + "withOptionShift": "ı" }, "KeyJ": { "unmodified": "j", "withShift": "J", - "withAltGr": "º", - "withShiftAltGr": "˜" + "withOption": "º", + "withOptionShift": "˜" }, "KeyK": { "unmodified": "k", "withShift": "K", - "withAltGr": "∆", - "withShiftAltGr": "¯" + "withOption": "∆", + "withOptionShift": "¯" }, "KeyL": { "unmodified": "l", "withShift": "L", - "withAltGr": "¬", - "withShiftAltGr": "ˆ" + "withOption": "¬", + "withOptionShift": "ˆ" }, "KeyM": { "unmodified": "m", "withShift": "M", - "withAltGr": "µ", - "withShiftAltGr": "˚" + "withOption": "µ", + "withOptionShift": "˚" }, "KeyN": { "unmodified": "n", "withShift": "N", - "withAltGr": "", - "withShiftAltGr": "˙" + "withOption": "", + "withOptionShift": "˙" }, "KeyO": { "unmodified": "o", "withShift": "O", - "withAltGr": "ø", - "withShiftAltGr": "Ø" + "withOption": "ø", + "withOptionShift": "Ø" }, "KeyP": { "unmodified": "p", "withShift": "P", - "withAltGr": "π", - "withShiftAltGr": "∏" + "withOption": "π", + "withOptionShift": "∏" }, "KeyQ": { "unmodified": "q", "withShift": "Q", - "withAltGr": "œ", - "withShiftAltGr": "Œ" + "withOption": "œ", + "withOptionShift": "Œ" }, "KeyR": { "unmodified": "r", "withShift": "R", - "withAltGr": "®", - "withShiftAltGr": "È" + "withOption": "®", + "withOptionShift": "È" }, "KeyS": { "unmodified": "s", "withShift": "S", - "withAltGr": "ß", - "withShiftAltGr": "fi" + "withOption": "ß", + "withOptionShift": "fi" }, "KeyT": { "unmodified": "t", "withShift": "T", - "withAltGr": "†", - "withShiftAltGr": "Î" + "withOption": "†", + "withOptionShift": "Î" }, "KeyU": { "unmodified": "u", "withShift": "U", - "withAltGr": "°", - "withShiftAltGr": "Ù" + "withOption": "°", + "withOptionShift": "Ù" }, "KeyV": { "unmodified": "v", "withShift": "V", - "withAltGr": "√", - "withShiftAltGr": "◊" + "withOption": "√", + "withOptionShift": "◊" }, "KeyW": { "unmodified": "w", "withShift": "W", - "withAltGr": "∑", - "withShiftAltGr": "Á" + "withOption": "∑", + "withOptionShift": "Á" }, "KeyX": { "unmodified": "x", "withShift": "X", - "withAltGr": "≈", - "withShiftAltGr": "™" + "withOption": "≈", + "withOptionShift": "™" }, "KeyY": { "unmodified": "z", "withShift": "Z", - "withAltGr": "Ω", - "withShiftAltGr": "Í" + "withOption": "Ω", + "withOptionShift": "Í" }, "KeyZ": { "unmodified": "y", "withShift": "Y", - "withAltGr": "¥", - "withShiftAltGr": "Ÿ" + "withOption": "¥", + "withOptionShift": "Ÿ" }, "Numpad0": { "unmodified": "0", "withShift": "0", - "withAltGr": "0", - "withShiftAltGr": "0" + "withOption": "0", + "withOptionShift": "0" }, "Numpad1": { "unmodified": "1", "withShift": "1", - "withAltGr": "1", - "withShiftAltGr": "1" + "withOption": "1", + "withOptionShift": "1" }, "Numpad2": { "unmodified": "2", "withShift": "2", - "withAltGr": "2", - "withShiftAltGr": "2" + "withOption": "2", + "withOptionShift": "2" }, "Numpad3": { "unmodified": "3", "withShift": "3", - "withAltGr": "3", - "withShiftAltGr": "3" + "withOption": "3", + "withOptionShift": "3" }, "Numpad4": { "unmodified": "4", "withShift": "4", - "withAltGr": "4", - "withShiftAltGr": "4" + "withOption": "4", + "withOptionShift": "4" }, "Numpad5": { "unmodified": "5", "withShift": "5", - "withAltGr": "5", - "withShiftAltGr": "5" + "withOption": "5", + "withOptionShift": "5" }, "Numpad6": { "unmodified": "6", "withShift": "6", - "withAltGr": "6", - "withShiftAltGr": "6" + "withOption": "6", + "withOptionShift": "6" }, "Numpad7": { "unmodified": "7", "withShift": "7", - "withAltGr": "7", - "withShiftAltGr": "7" + "withOption": "7", + "withOptionShift": "7" }, "Numpad8": { "unmodified": "8", "withShift": "8", - "withAltGr": "8", - "withShiftAltGr": "8" + "withOption": "8", + "withOptionShift": "8" }, "Numpad9": { "unmodified": "9", "withShift": "9", - "withAltGr": "9", - "withShiftAltGr": "9" + "withOption": "9", + "withOptionShift": "9" }, "NumpadMultiply": { "unmodified": "*", "withShift": "*", - "withAltGr": "*", - "withShiftAltGr": "*" + "withOption": "*", + "withOptionShift": "*" }, "NumpadAdd": { "unmodified": "+", "withShift": "+", - "withAltGr": "+", - "withShiftAltGr": "+" + "withOption": "+", + "withOptionShift": "+" }, "NumpadSubtract": { "unmodified": "-", "withShift": "-", - "withAltGr": "-", - "withShiftAltGr": "-" + "withOption": "-", + "withOptionShift": "-" }, "NumpadDecimal": { "unmodified": ".", "withShift": ",", - "withAltGr": ".", - "withShiftAltGr": "." + "withOption": ".", + "withOptionShift": "." }, "NumpadDivide": { "unmodified": "/", "withShift": "/", - "withAltGr": "/", - "withShiftAltGr": "/" + "withOption": "/", + "withOptionShift": "/" }, "Semicolon": { "unmodified": "ö", "withShift": "é", - "withAltGr": "¢", - "withShiftAltGr": "˘" + "withOption": "¢", + "withOptionShift": "˘" }, "Equal": { "unmodified": "", "withShift": "", - "withAltGr": "", - "withShiftAltGr": "^" + "withOption": "", + "withOptionShift": "^" }, "NumpadComma": { "unmodified": ",", "withShift": ";", - "withAltGr": "«", - "withShiftAltGr": "»" + "withOption": "«", + "withOptionShift": "»" }, "Minus": { "unmodified": "'", "withShift": "?", - "withAltGr": "¿", - "withShiftAltGr": "" + "withOption": "¿", + "withOptionShift": "" }, "Period": { "unmodified": ".", "withShift": ":", - "withAltGr": "…", - "withShiftAltGr": "÷" + "withOption": "…", + "withOptionShift": "÷" }, "Slash": { "unmodified": "-", "withShift": "_", - "withAltGr": "–", - "withShiftAltGr": "—" + "withOption": "–", + "withOptionShift": "—" }, "Backquote": { "unmodified": "<", "withShift": ">", - "withAltGr": "≤", - "withShiftAltGr": "≥" + "withOption": "≤", + "withOptionShift": "≥" }, "BracketLeft": { "unmodified": "ü", "withShift": "è", - "withAltGr": "§", - "withShiftAltGr": "ÿ" + "withOption": "§", + "withOptionShift": "ÿ" }, "IntlYen": { "unmodified": "$", "withShift": "£", - "withAltGr": "¶", - "withShiftAltGr": "•" + "withOption": "¶", + "withOptionShift": "•" }, "BracketRight": { "unmodified": "", "withShift": "!", - "withAltGr": "‘", - "withShiftAltGr": "’" + "withOption": "‘", + "withOptionShift": "’" }, "Quote": { "unmodified": "ä", "withShift": "à", - "withAltGr": "æ", - "withShiftAltGr": "Æ" + "withOption": "æ", + "withOptionShift": "Æ" } } diff --git a/spec/helpers/keymaps/turkish.json b/spec/helpers/keymaps/turkish.json index 266f402..ce5d806 100644 --- a/spec/helpers/keymaps/turkish.json +++ b/spec/helpers/keymaps/turkish.json @@ -2,379 +2,379 @@ "Space": { "unmodified": " ", "withShift": " ", - "withAltGr": " ", - "withShiftAltGr": " " + "withOption": " ", + "withOptionShift": " " }, "Digit0": { "unmodified": "0", "withShift": ":", - "withAltGr": "º", - "withShiftAltGr": "÷" + "withOption": "º", + "withOptionShift": "÷" }, "Digit1": { "unmodified": "1", "withShift": "!", - "withAltGr": "¡", - "withShiftAltGr": "·" + "withOption": "¡", + "withOptionShift": "·" }, "Digit2": { "unmodified": "2", "withShift": "*", - "withAltGr": "™", - "withShiftAltGr": "€" + "withOption": "™", + "withOptionShift": "€" }, "Digit3": { "unmodified": "3", "withShift": "\"", - "withAltGr": "“", - "withShiftAltGr": "”" + "withOption": "“", + "withOptionShift": "”" }, "Digit4": { "unmodified": "4", "withShift": "'", - "withAltGr": "‘", - "withShiftAltGr": "’" + "withOption": "‘", + "withOptionShift": "’" }, "Digit5": { "unmodified": "5", "withShift": "(", - "withAltGr": "[", - "withShiftAltGr": "{" + "withOption": "[", + "withOptionShift": "{" }, "Digit6": { "unmodified": "6", "withShift": "/", - "withAltGr": "|", - "withShiftAltGr": "\\" + "withOption": "|", + "withOptionShift": "\\" }, "Digit7": { "unmodified": "7", "withShift": ")", - "withAltGr": "]", - "withShiftAltGr": "}" + "withOption": "]", + "withOptionShift": "}" }, "Digit8": { "unmodified": "8", "withShift": "_", - "withAltGr": "•", - "withShiftAltGr": "°" + "withOption": "•", + "withOptionShift": "°" }, "Digit9": { "unmodified": "9", "withShift": "%", - "withAltGr": "«", - "withShiftAltGr": "»" + "withOption": "«", + "withOptionShift": "»" }, "KeyA": { "unmodified": "u", "withShift": "U", - "withAltGr": "", - "withShiftAltGr": "Ë" + "withOption": "", + "withOptionShift": "Ë" }, "KeyB": { "unmodified": "ç", "withShift": "Ç", - "withAltGr": "¯", - "withShiftAltGr": "˙" + "withOption": "¯", + "withOptionShift": "˙" }, "KeyC": { "unmodified": "v", "withShift": "V", - "withAltGr": "√", - "withShiftAltGr": "◊" + "withOption": "√", + "withOptionShift": "◊" }, "KeyD": { "unmodified": "e", "withShift": "E", - "withAltGr": "", - "withShiftAltGr": "‰" + "withOption": "", + "withOptionShift": "‰" }, "KeyE": { "unmodified": "ğ", "withShift": "Ğ", - "withAltGr": "#", - "withShiftAltGr": "´" + "withOption": "#", + "withOptionShift": "´" }, "KeyF": { "unmodified": "a", "withShift": "A", - "withAltGr": "å", - "withShiftAltGr": "Å" + "withOption": "å", + "withOptionShift": "Å" }, "KeyG": { "unmodified": "ü", "withShift": "Ü", - "withAltGr": "@", - "withShiftAltGr": "ª" + "withOption": "@", + "withOptionShift": "ª" }, "KeyH": { "unmodified": "t", "withShift": "T", - "withAltGr": "₺", - "withShiftAltGr": "Ê" + "withOption": "₺", + "withOptionShift": "Ê" }, "KeyI": { "unmodified": "n", "withShift": "N", - "withAltGr": "", - "withShiftAltGr": "ˆ" + "withOption": "", + "withOptionShift": "ˆ" }, "KeyJ": { "unmodified": "k", "withShift": "K", - "withAltGr": "", - "withShiftAltGr": "©" + "withOption": "", + "withOptionShift": "©" }, "KeyK": { "unmodified": "m", "withShift": "M", - "withAltGr": "µ", - "withShiftAltGr": "˜" + "withOption": "µ", + "withOptionShift": "˜" }, "KeyL": { "unmodified": "l", "withShift": "L", - "withAltGr": "¬", - "withShiftAltGr": "£" + "withOption": "¬", + "withOptionShift": "£" }, "KeyM": { "unmodified": "s", "withShift": "S", - "withAltGr": "§", - "withShiftAltGr": "~" + "withOption": "§", + "withOptionShift": "~" }, "KeyN": { "unmodified": "z", "withShift": "Z", - "withAltGr": "Ω", - "withShiftAltGr": "Û" + "withOption": "Ω", + "withOptionShift": "Û" }, "KeyO": { "unmodified": "h", "withShift": "H", - "withAltGr": "", - "withShiftAltGr": "Ó" + "withOption": "", + "withOptionShift": "Ó" }, "KeyP": { "unmodified": "p", "withShift": "P", - "withAltGr": "π", - "withShiftAltGr": "∏" + "withOption": "π", + "withOptionShift": "∏" }, "KeyQ": { "unmodified": "f", "withShift": "F", - "withAltGr": "ƒ", - "withShiftAltGr": "Ï" + "withOption": "ƒ", + "withOptionShift": "Ï" }, "KeyR": { "unmodified": "ı", "withShift": "I", - "withAltGr": "^", - "withShiftAltGr": "È" + "withOption": "^", + "withOptionShift": "È" }, "KeyS": { "unmodified": "i", "withShift": "İ", - "withAltGr": "", - "withShiftAltGr": "∞" + "withOption": "", + "withOptionShift": "∞" }, "KeyT": { "unmodified": "o", "withShift": "O", - "withAltGr": "ø", - "withShiftAltGr": "Ø" + "withOption": "ø", + "withOptionShift": "Ø" }, "KeyU": { "unmodified": "r", "withShift": "R", - "withAltGr": "®", - "withShiftAltGr": "Â" + "withOption": "®", + "withOptionShift": "Â" }, "KeyV": { "unmodified": "c", "withShift": "C", - "withAltGr": "ç", - "withShiftAltGr": "˚" + "withOption": "ç", + "withOptionShift": "˚" }, "KeyW": { "unmodified": "g", "withShift": "G", - "withAltGr": "¶", - "withShiftAltGr": "`" + "withOption": "¶", + "withOptionShift": "`" }, "KeyX": { "unmodified": "ö", "withShift": "Ö", - "withAltGr": "¨", - "withShiftAltGr": "Ÿ" + "withOption": "¨", + "withOptionShift": "Ÿ" }, "KeyY": { "unmodified": "d", "withShift": "D", - "withAltGr": "∂", - "withShiftAltGr": "Î" + "withOption": "∂", + "withOptionShift": "Î" }, "KeyZ": { "unmodified": "j", "withShift": "J", - "withAltGr": "∆", - "withShiftAltGr": "Ô" + "withOption": "∆", + "withOptionShift": "Ô" }, "Numpad0": { "unmodified": "0", "withShift": "0", - "withAltGr": "0", - "withShiftAltGr": "0" + "withOption": "0", + "withOptionShift": "0" }, "Numpad1": { "unmodified": "1", "withShift": "1", - "withAltGr": "1", - "withShiftAltGr": "1" + "withOption": "1", + "withOptionShift": "1" }, "Numpad2": { "unmodified": "2", "withShift": "2", - "withAltGr": "2", - "withShiftAltGr": "2" + "withOption": "2", + "withOptionShift": "2" }, "Numpad3": { "unmodified": "3", "withShift": "3", - "withAltGr": "3", - "withShiftAltGr": "3" + "withOption": "3", + "withOptionShift": "3" }, "Numpad4": { "unmodified": "4", "withShift": "4", - "withAltGr": "4", - "withShiftAltGr": "4" + "withOption": "4", + "withOptionShift": "4" }, "Numpad5": { "unmodified": "5", "withShift": "5", - "withAltGr": "5", - "withShiftAltGr": "5" + "withOption": "5", + "withOptionShift": "5" }, "Numpad6": { "unmodified": "6", "withShift": "6", - "withAltGr": "6", - "withShiftAltGr": "6" + "withOption": "6", + "withOptionShift": "6" }, "Numpad7": { "unmodified": "7", "withShift": "7", - "withAltGr": "7", - "withShiftAltGr": "7" + "withOption": "7", + "withOptionShift": "7" }, "Numpad8": { "unmodified": "8", "withShift": "8", - "withAltGr": "8", - "withShiftAltGr": "8" + "withOption": "8", + "withOptionShift": "8" }, "Numpad9": { "unmodified": "9", "withShift": "9", - "withAltGr": "9", - "withShiftAltGr": "9" + "withOption": "9", + "withOptionShift": "9" }, "NumpadMultiply": { "unmodified": "*", "withShift": "*", - "withAltGr": "*", - "withShiftAltGr": "*" + "withOption": "*", + "withOptionShift": "*" }, "NumpadAdd": { "unmodified": "+", "withShift": "+", - "withAltGr": "+", - "withShiftAltGr": "+" + "withOption": "+", + "withOptionShift": "+" }, "NumpadSubtract": { "unmodified": "-", "withShift": "-", - "withAltGr": "-", - "withShiftAltGr": "-" + "withOption": "-", + "withOptionShift": "-" }, "NumpadDecimal": { "unmodified": ",", "withShift": ",", - "withAltGr": ",", - "withShiftAltGr": "," + "withOption": ",", + "withOptionShift": "," }, "NumpadDivide": { "unmodified": "/", "withShift": "/", - "withAltGr": "/", - "withShiftAltGr": "/" + "withOption": "/", + "withOptionShift": "/" }, "Semicolon": { "unmodified": "y", "withShift": "Y", - "withAltGr": "¥", - "withShiftAltGr": "Á" + "withOption": "¥", + "withOptionShift": "Á" }, "Equal": { "unmodified": "q", "withShift": "Q", - "withAltGr": "œ", - "withShiftAltGr": "Œ" + "withOption": "œ", + "withOptionShift": "Œ" }, "NumpadComma": { "unmodified": "b", "withShift": "B", - "withAltGr": "∫", - "withShiftAltGr": "ß" + "withOption": "∫", + "withOptionShift": "ß" }, "Minus": { "unmodified": "x", "withShift": "X", - "withAltGr": "≈", - "withShiftAltGr": "Ù" + "withOption": "≈", + "withOptionShift": "Ù" }, "Period": { "unmodified": ".", "withShift": "?", - "withAltGr": "&", - "withShiftAltGr": "¿" + "withOption": "&", + "withOptionShift": "¿" }, "Slash": { "unmodified": ",", "withShift": "-", - "withAltGr": "–", - "withShiftAltGr": "—" + "withOption": "–", + "withOptionShift": "—" }, "Backquote": { "unmodified": "w", "withShift": "W", - "withAltGr": "∑", - "withShiftAltGr": "„" + "withOption": "∑", + "withOptionShift": "„" }, "BracketLeft": { "unmodified": ";", "withShift": "$", - "withAltGr": "…", - "withShiftAltGr": "¢" + "withOption": "…", + "withOptionShift": "¢" }, "IntlYen": { "unmodified": "=", "withShift": "+", - "withAltGr": "≠", - "withShiftAltGr": "±" + "withOption": "≠", + "withOptionShift": "±" }, "BracketRight": { "unmodified": ">", "withShift": "<", - "withAltGr": "≥", - "withShiftAltGr": "≤" + "withOption": "≥", + "withOptionShift": "≤" }, "Quote": { "unmodified": "ş", "withShift": "Ş", - "withAltGr": "æ", - "withShiftAltGr": "Æ" + "withOption": "æ", + "withOptionShift": "Æ" } } diff --git a/spec/keymap-manager-spec.coffee b/spec/keymap-manager-spec.coffee index e69fc20..b0c7b44 100644 --- a/spec/keymap-manager-spec.coffee +++ b/spec/keymap-manager-spec.coffee @@ -3,9 +3,9 @@ debounce = require 'debounce' fs = require 'fs-plus' path = require 'path' temp = require 'temp' -{appendContent, stub, getFakeClock} = require './helpers/helpers' KeymapManager = require '../src/keymap-manager' {buildKeydownEvent, buildKeyupEvent} = KeymapManager +{appendContent, stub, getFakeClock, mockProcessPlatform} = require './helpers/helpers' describe "KeymapManager", -> keymapManager = null @@ -580,61 +580,91 @@ describe "KeymapManager", -> assert.equal(keymapManager.findKeyBindings(command: 'z').length, 0) describe "::keystrokeForKeyboardEvent(event)", -> - KeyboardLayout = require('keyboard-layout') - currentKeymap = null - - beforeEach -> - currentKeymap = null - stub(KeyboardLayout, 'getCurrentKeymap', -> currentKeymap) - describe "when no extra modifiers are pressed", -> it "returns a string that identifies the unmodified keystroke", -> - currentKeymap = require('./helpers/keymaps/dvorak') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyA'}), 'a') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Minus'}), '[') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Digit8', shiftKey: true}), '*') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'ArrowLeft'}), 'left') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Backspace'}), 'backspace') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'delete'}), 'delete') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'PageUp'}), 'pageup') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'a'}), 'a') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'A', shiftKey: true}), 'shift-A') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '['}), '[') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '*', shiftKey: true}), '*') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'ArrowLeft'}), 'left') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'Backspace'}), 'backspace') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'Delete'}), 'delete') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'PageUp'}), 'pageup') describe "when a modifier key is combined with a non-modifier key", -> it "returns a string that identifies the modified keystroke", -> - currentKeymap = require('./helpers/keymaps/dvorak') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyA', altKey: true}), 'alt-a') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Minus', metaKey: true}), 'cmd-[') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Digit8', ctrlKey: true, shiftKey: true}), 'ctrl-*') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'ArrowLeft', ctrlKey: true, altKey: true, metaKey: true}), 'ctrl-alt-cmd-left') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyA', shiftKey: true}), 'shift-A') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyA', ctrlKey: true, shiftKey: true}), 'ctrl-shift-A') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Minus', shiftKey: true}), '{') - - describe "when a numpad key is pressed", -> - it "returns a string that identifies the key as the appropriate num-key", -> - currentKeymap = require('./helpers/keymaps/dvorak') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Numpad1'}), '1') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'Numpad5'}), '5') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'NumpadAdd'}), '+') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'a', altKey: true}), 'alt-a') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '[', metaKey: true}), 'cmd-[') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '*', ctrlKey: true, shiftKey: true}), 'ctrl-*') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'ArrowLeft', ctrlKey: true, altKey: true, metaKey: true}), 'ctrl-alt-cmd-left') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'A', shiftKey: true}), 'shift-A') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'A', ctrlKey: true, shiftKey: true}), 'ctrl-shift-A') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '{', shiftKey: true}), '{') describe "international layouts", -> - it "allows normal ASCII characters (<= 127) to be typed via an alt modifier", -> + KeyboardLayout = require('keyboard-layout') + currentKeymap = null + + beforeEach -> + currentKeymap = null + stub(KeyboardLayout, 'getCurrentKeymap', -> currentKeymap) + + it "allows normal ASCII characters (<= 127) to be typed via an option modifier on macOS", -> + mockProcessPlatform('darwin') + currentKeymap = require('./helpers/keymaps/swiss-german') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyG', altKey: true}), '@') - # Only uses alt variants for basic latin - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyG', altKey: true, shiftKey: true}), 'alt-shift-g') - # Only uses alt variants when no other modifiers are used - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyG', ctrlKey: true, altKey: true}), 'ctrl-alt-g') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '@', code: 'KeyG', altKey: true}), '@') + # Does not use alt variant characters outside of basic ASCII range + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '‚', code: 'KeyG', altKey: true, shiftKey: true}), 'alt-shift-G') + # Does not use alt variant character if ctrl modifier is used + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '@', code: 'KeyG', ctrlKey: true, altKey: true}), 'ctrl-alt-g') + + it "allows arbitrary characters to be typed via an altgraph modifier on Windows and Linux", -> + mockProcessPlatform('win32') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '@', altKey: true, getModifierState: (key) -> key is 'AltGraph'}), '@') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '€', altKey: true, getModifierState: (key) -> key is 'AltGraph'}), '€') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'Ë', altKey: true, shiftKey: true, getModifierState: (key) -> key is 'AltGraph'}), 'shift-Ë') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'g', altKey: true, getModifierState: (key) -> false}), 'alt-g') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'e', altKey: true, getModifierState: (key) -> false}), 'alt-e') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'E', altKey: true, shiftKey: true, getModifierState: (key) -> false}), 'alt-shift-E') + + mockProcessPlatform('linux') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '@', altKey: true, getModifierState: (key) -> key is 'AltGraph'}), '@') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '€', altKey: true, getModifierState: (key) -> key is 'AltGraph'}), '€') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'Ë', altKey: true, shiftKey: true, getModifierState: (key) -> key is 'AltGraph'}), 'shift-Ë') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'g', altKey: true, getModifierState: (key) -> false}), 'alt-g') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'e', altKey: true, getModifierState: (key) -> false}), 'alt-e') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'E', altKey: true, shiftKey: true, getModifierState: (key) -> false}), 'alt-shift-E') it "converts non-latin keycaps to their U.S. counterpart for purposes of binding", -> + mockProcessPlatform('darwin') currentKeymap = require('./helpers/keymaps/greek') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyX'}), 'χ') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyX', shiftKey: true}), 'Χ') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyX', metaKey: true}), 'cmd-x') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyX', metaKey: true, shiftKey: true}), 'shift-cmd-X') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'δ', code: 'KeyD'}), 'δ') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'Δ', code: 'KeyD', shiftKey: true}), 'Δ') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '÷', altKey: true, code: 'KeyD'}), 'alt-d') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'δ', code: 'KeyD', metaKey: true}), 'cmd-d') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'Δ', code: 'KeyD', metaKey: true, shiftKey: true}), 'shift-cmd-D') # Don't use U.S. counterpart for latin characters currentKeymap = require('./helpers/keymaps/turkish') - assert.equal(keymapManager.keystrokeForKeyboardEvent({code: 'KeyX', metaKey: true}), 'cmd-ö') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'ö', code: 'KeyX', metaKey: true}), 'cmd-ö') + + currentKeymap = null + mockProcessPlatform('windows') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'δ', code: 'KeyD'}), 'δ') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'Δ', code: 'KeyD', shiftKey: true}), 'Δ') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'δ', code: 'KeyD', ctrlKey: true}), 'ctrl-d') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'Δ', code: 'KeyD', ctrlKey: true, shiftKey: true}), 'ctrl-shift-D') + # Don't use U.S. counterpart for latin characters + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'ö', code: 'KeyX', metaKey: true}), 'cmd-ö') + + mockProcessPlatform('linux') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'δ', code: 'KeyD'}), 'δ') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'Δ', code: 'KeyD', shiftKey: true}), 'Δ') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'δ', code: 'KeyD', ctrlKey: true}), 'ctrl-d') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'Δ', code: 'KeyD', ctrlKey: true, shiftKey: true}), 'ctrl-shift-D') + # Don't use U.S. counterpart for latin characters + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'ö', code: 'KeyX', metaKey: true}), 'cmd-ö') describe "::findKeyBindings({command, target, keystrokes})", -> [elementA, elementB] = [] diff --git a/src/helpers.coffee b/src/helpers.coffee index cb1ad7b..c7f9dd3 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -9,21 +9,20 @@ UpperCaseLetterRegex = /^[A-Z]$/ ExactMatch = 'exact' KeydownExactMatch = 'keydownExact' PartialMatch = 'partial' -NonPrintableKeyNamesByCode = { - 'AltLeft': 'alt', - 'AltRight': 'alt', - 'ControlLeft': 'ctrl', - 'ControlRight': 'ctrl', - 'MetaLeft': 'cmd', - 'MetaRight': 'cmd', - 'ShiftLeft': 'shift', - 'ShiftRight': 'shift', +NonCharacterKeyNamesByDOM3Key = { + 'Control': 'ctrl', + 'Meta': 'cmd', 'ArrowDown': 'down', 'ArrowUp': 'up', 'ArrowLeft': 'left', 'ArrowRight': 'right' } -EndOFLatinCharCodeRange = 0x024F + +isASCII = (character) -> character.charCodeAt(0) <= 127 + +isLatin = (character) -> character.charCodeAt(0) <= 0x024F + +isUpperCaseLatin = (character) -> isLatin(character) and character.toLowerCase() isnt character exports.normalizeKeystrokes = (keystrokes) -> normalizedKeystrokes = [] @@ -35,17 +34,37 @@ exports.normalizeKeystrokes = (keystrokes) -> normalizedKeystrokes.join(' ') exports.keystrokeForKeyboardEvent = (event, dvorakQwertyWorkaroundEnabled) -> - key = NonPrintableKeyNamesByCode[event.code] - unless key? - if characters = KeyboardLayout.getCurrentKeymap()[event.code] - key = characters.unmodified - unless key? - key = event.code.toLowerCase() + {ctrlKey, altKey, shiftKey, metaKey} = event + isNonCharacterKey = event.key.length > 1 + + if isNonCharacterKey + key = NonCharacterKeyNamesByDOM3Key[event.key] ? event.key.toLowerCase() + else + key = event.key + + if altKey + if process.platform is 'darwin' + # When the option key is down on macOS, we need to determine whether the + # the user intends to type an ASCII character that is only reachable by use + # of the option key (such as option-g to type @ on a Swiss-German layout) + # or used as a modifier to match against an alt-* binding. + # + # We check for event.code because test helpers produce events without it. + if event.code and (characters = KeyboardLayout.getCurrentKeymap()[event.code]) + if shiftKey + nonAltModifiedKey = characters.withShift + else + nonAltModifiedKey = characters.unmodified + + if not ctrlKey and not metaKey and isASCII(key) and key isnt nonAltModifiedKey + altKey = false + else + key = nonAltModifiedKey + else + altKey = false if event.getModifierState('AltGraph') # Use US equivalent character for non-latin characters in keystrokes with modifiers - keyIsNonLatin = key.length is 1 and key.charCodeAt(0) > EndOFLatinCharCodeRange - keystrokeHasModifiers = (event.ctrlKey or event.metaKey) - if keyIsNonLatin and keystrokeHasModifiers + if not isLatin(key) and (ctrlKey or altKey or metaKey) if characters = usCharactersForKeyCode(event.code) if event.shiftKey key = characters.withShift @@ -53,52 +72,30 @@ exports.keystrokeForKeyboardEvent = (event, dvorakQwertyWorkaroundEnabled) -> key = characters.unmodified keystroke = '' - if event.ctrlKey or key is 'ctrl' + if key is 'ctrl' or ctrlKey keystroke += 'ctrl' - if event.shiftKey - if event.altKey - if characters? and characters.withShiftAltGr.charCodeAt(0) <= 127 and not event.ctrlKey and not event.metaKey - key = characters.withShiftAltGr - else - keystroke += '-' if keystroke.length > 0 - keystroke += 'alt' - else - if characters? - key = characters.withShift - unless /^[^A-Za-z]$/.test(key) - keystroke += '-' if keystroke - keystroke += 'shift' - else if event.altKey - if characters? and characters.withAltGr.charCodeAt(0) <= 127 and not event.ctrlKey and not event.metaKey - key = characters.withAltGr - else - keystroke += '-' if keystroke.length > 0 - keystroke += 'alt' + if key is 'alt' or altKey + keystroke += '-' if keystroke.length > 0 + keystroke += 'alt' + + if key is 'shift' or (shiftKey and (isNonCharacterKey or isUpperCaseLatin(key))) + keystroke += '-' if keystroke + keystroke += 'shift' - if event.metaKey or key is 'Meta' + if key is 'cmd' or metaKey keystroke += '-' if keystroke keystroke += 'cmd' - if key? and not Modifiers.has(key) + unless Modifiers.has(key) keystroke += '-' if keystroke keystroke += key keystroke = normalizeKeystroke("^#{keystroke}") if event.type is 'keyup' keystroke -exports.characterForKeyboardEvent = (event, allowModifiers = false) -> - unless event.ctrlKey or event.metaKey - if characters = KeyboardLayout.getCurrentKeymap()[event.code] - if event.shiftKey - if event.altKey - return characters.withShiftAltGr - else - return characters.withShift - else if event.altKey - return characters.withAltGr - else - return characters.unmodified +exports.characterForKeyboardEvent = (event) -> + event.key unless event.ctrlKey or event.metaKey exports.calculateSpecificity = calculateSpecificity @@ -118,26 +115,9 @@ keyboardEvent = (key, eventType, {ctrl, shift, alt, cmd, keyCode, target, locati metaKey = cmd ? false bubbles = true cancelable = true - code = Object.keys(NonPrintableKeyNamesByCode).find (candidateCode) -> - NonPrintableKeyNamesByCode[candidateCode] is key - - unless code? - for candidateCode, characters of KeyboardLayout.getCurrentKeymap() - if characters.unmodified is key - code = candidateCode - else if characters.withShift is key - code = candidateCode - shiftKey = true - else if characters.withAltGr is key - code = candidateCode - altKey = true - else if characters.withShiftAltGr is key - code = candidateCode - altKey = true - shiftKey = true event = new KeyboardEvent(eventType, { - code, ctrlKey, altKey, shiftKey, metaKey, bubbles, cancelable + key, ctrlKey, altKey, shiftKey, metaKey, bubbles, cancelable }) if target? @@ -307,9 +287,6 @@ keyFromCharCode = (charCode) -> when 127 then 'delete' else String.fromCharCode(charCode) -isASCII = (charCode) -> - 0 <= charCode <= 127 - numpadToASCII = (charCode) -> NumPadToASCII[charCode] ? charCode diff --git a/src/us-keymap.coffee b/src/us-keymap.coffee index 1bee929..e0e3dc3 100644 --- a/src/us-keymap.coffee +++ b/src/us-keymap.coffee @@ -1,380 +1,254 @@ module.exports = { "Space": { "unmodified": " ", - "withShift": " ", - "withAltGr": " ", - "withShiftAltGr": " " + "withShift": " " }, "Digit0": { "unmodified": "0", - "withShift": ")", - "withAltGr": "º", - "withShiftAltGr": "‚" + "withShift": ")" }, "Digit1": { "unmodified": "1", - "withShift": "!", - "withAltGr": "¡", - "withShiftAltGr": "⁄" + "withShift": "!" }, "Digit2": { "unmodified": "2", - "withShift": "@", - "withAltGr": "™", - "withShiftAltGr": "€" + "withShift": "@" }, "Digit3": { "unmodified": "3", - "withShift": "#", - "withAltGr": "£", - "withShiftAltGr": "‹" + "withShift": "#" }, "Digit4": { "unmodified": "4", - "withShift": "$", - "withAltGr": "¢", - "withShiftAltGr": "›" + "withShift": "$" }, "Digit5": { "unmodified": "5", - "withShift": "%", - "withAltGr": "∞", - "withShiftAltGr": "fi" + "withShift": "%" }, "Digit6": { "unmodified": "6", - "withShift": "^", - "withAltGr": "§", - "withShiftAltGr": "fl" + "withShift": "^" }, "Digit7": { "unmodified": "7", - "withShift": "&", - "withAltGr": "¶", - "withShiftAltGr": "‡" + "withShift": "&" }, "Digit8": { "unmodified": "8", - "withShift": "*", - "withAltGr": "•", - "withShiftAltGr": "°" + "withShift": "*" }, "Digit9": { "unmodified": "9", - "withShift": "(", - "withAltGr": "ª", - "withShiftAltGr": "·" + "withShift": "(" }, "KeyA": { "unmodified": "a", - "withShift": "A", - "withAltGr": "å", - "withShiftAltGr": "Å" + "withShift": "A" }, "KeyB": { "unmodified": "b", - "withShift": "B", - "withAltGr": "∫", - "withShiftAltGr": "ı" + "withShift": "B" }, "KeyC": { "unmodified": "c", - "withShift": "C", - "withAltGr": "ç", - "withShiftAltGr": "Ç" + "withShift": "C" }, "KeyD": { "unmodified": "d", - "withShift": "D", - "withAltGr": "∂", - "withShiftAltGr": "Î" + "withShift": "D" }, "KeyE": { "unmodified": "e", - "withShift": "E", - "withAltGr": "", - "withShiftAltGr": "´" + "withShift": "E" }, "KeyF": { "unmodified": "f", - "withShift": "F", - "withAltGr": "ƒ", - "withShiftAltGr": "Ï" + "withShift": "F" }, "KeyG": { "unmodified": "g", - "withShift": "G", - "withAltGr": "©", - "withShiftAltGr": "˝" + "withShift": "G" }, "KeyH": { "unmodified": "h", - "withShift": "H", - "withAltGr": "˙", - "withShiftAltGr": "Ó" + "withShift": "H" }, "KeyI": { "unmodified": "i", - "withShift": "I", - "withAltGr": "", - "withShiftAltGr": "ˆ" + "withShift": "I" }, "KeyJ": { "unmodified": "j", - "withShift": "J", - "withAltGr": "∆", - "withShiftAltGr": "Ô" + "withShift": "J" }, "KeyK": { "unmodified": "k", - "withShift": "K", - "withAltGr": "˚", - "withShiftAltGr": "" + "withShift": "K" }, "KeyL": { "unmodified": "l", - "withShift": "L", - "withAltGr": "¬", - "withShiftAltGr": "Ò" + "withShift": "L" }, "KeyM": { "unmodified": "m", - "withShift": "M", - "withAltGr": "µ", - "withShiftAltGr": "Â" + "withShift": "M" }, "KeyN": { "unmodified": "n", - "withShift": "N", - "withAltGr": "", - "withShiftAltGr": "˜" + "withShift": "N" }, "KeyO": { "unmodified": "o", - "withShift": "O", - "withAltGr": "ø", - "withShiftAltGr": "Ø" + "withShift": "O" }, "KeyP": { "unmodified": "p", - "withShift": "P", - "withAltGr": "π", - "withShiftAltGr": "∏" + "withShift": "P" }, "KeyQ": { "unmodified": "q", - "withShift": "Q", - "withAltGr": "œ", - "withShiftAltGr": "Œ" + "withShift": "Q" }, "KeyR": { "unmodified": "r", - "withShift": "R", - "withAltGr": "®", - "withShiftAltGr": "‰" + "withShift": "R" }, "KeyS": { "unmodified": "s", - "withShift": "S", - "withAltGr": "ß", - "withShiftAltGr": "Í" + "withShift": "S" }, "KeyT": { "unmodified": "t", - "withShift": "T", - "withAltGr": "†", - "withShiftAltGr": "ˇ" + "withShift": "T" }, "KeyU": { "unmodified": "u", - "withShift": "U", - "withAltGr": "", - "withShiftAltGr": "¨" + "withShift": "U" }, "KeyV": { "unmodified": "v", - "withShift": "V", - "withAltGr": "√", - "withShiftAltGr": "◊" + "withShift": "V" }, "KeyW": { "unmodified": "w", - "withShift": "W", - "withAltGr": "∑", - "withShiftAltGr": "„" + "withShift": "W" }, "KeyX": { "unmodified": "x", - "withShift": "X", - "withAltGr": "≈", - "withShiftAltGr": "˛" + "withShift": "X" }, "KeyY": { "unmodified": "y", - "withShift": "Y", - "withAltGr": "¥", - "withShiftAltGr": "Á" + "withShift": "Y" }, "KeyZ": { "unmodified": "z", - "withShift": "Z", - "withAltGr": "Ω", - "withShiftAltGr": "¸" + "withShift": "Z" }, "Numpad0": { "unmodified": "0", - "withShift": "0", - "withAltGr": "0", - "withShiftAltGr": "0" + "withShift": "0" }, "Numpad1": { "unmodified": "1", - "withShift": "1", - "withAltGr": "1", - "withShiftAltGr": "1" + "withShift": "1" }, "Numpad2": { "unmodified": "2", - "withShift": "2", - "withAltGr": "2", - "withShiftAltGr": "2" + "withShift": "2" }, "Numpad3": { "unmodified": "3", - "withShift": "3", - "withAltGr": "3", - "withShiftAltGr": "3" + "withShift": "3" }, "Numpad4": { "unmodified": "4", - "withShift": "4", - "withAltGr": "4", - "withShiftAltGr": "4" + "withShift": "4" }, "Numpad5": { "unmodified": "5", - "withShift": "5", - "withAltGr": "5", - "withShiftAltGr": "5" + "withShift": "5" }, "Numpad6": { "unmodified": "6", - "withShift": "6", - "withAltGr": "6", - "withShiftAltGr": "6" + "withShift": "6" }, "Numpad7": { "unmodified": "7", - "withShift": "7", - "withAltGr": "7", - "withShiftAltGr": "7" + "withShift": "7" }, "Numpad8": { "unmodified": "8", - "withShift": "8", - "withAltGr": "8", - "withShiftAltGr": "8" + "withShift": "8" }, "Numpad9": { "unmodified": "9", - "withShift": "9", - "withAltGr": "9", - "withShiftAltGr": "9" + "withShift": "9" }, "NumpadMultiply": { "unmodified": "*", - "withShift": "*", - "withAltGr": "*", - "withShiftAltGr": "*" + "withShift": "*" }, "NumpadAdd": { "unmodified": "+", - "withShift": "+", - "withAltGr": "+", - "withShiftAltGr": "+" + "withShift": "+" }, "NumpadSubtract": { "unmodified": "-", - "withShift": "-", - "withAltGr": "-", - "withShiftAltGr": "-" + "withShift": "-" }, "NumpadDecimal": { "unmodified": ".", - "withShift": ".", - "withAltGr": ".", - "withShiftAltGr": "." + "withShift": "." }, "NumpadDivide": { "unmodified": "/", - "withShift": "/", - "withAltGr": "/", - "withShiftAltGr": "/" + "withShift": "/" }, "Semicolon": { "unmodified": ";", - "withShift": ":", - "withAltGr": "…", - "withShiftAltGr": "Ú" + "withShift": ":" }, "Equal": { "unmodified": "=", - "withShift": "+", - "withAltGr": "≠", - "withShiftAltGr": "±" + "withShift": "+" }, "NumpadComma": { "unmodified": ",", - "withShift": "<", - "withAltGr": "≤", - "withShiftAltGr": "¯" + "withShift": "<" }, "Minus": { "unmodified": "-", - "withShift": "_", - "withAltGr": "–", - "withShiftAltGr": "—" + "withShift": "_" }, "Period": { "unmodified": ".", - "withShift": ">", - "withAltGr": "≥", - "withShiftAltGr": "˘" + "withShift": ">" }, "Slash": { "unmodified": "/", - "withShift": "?", - "withAltGr": "÷", - "withShiftAltGr": "¿" + "withShift": "?" }, "Backquote": { "unmodified": "`", - "withShift": "~", - "withAltGr": "", - "withShiftAltGr": "`" + "withShift": "~" }, "BracketLeft": { "unmodified": "[", - "withShift": "{", - "withAltGr": "“", - "withShiftAltGr": "”" + "withShift": "{" }, "IntlYen": { "unmodified": "\\", - "withShift": "|", - "withAltGr": "«", - "withShiftAltGr": "»" + "withShift": "|" }, "BracketRight": { "unmodified": "]", - "withShift": "}", - "withAltGr": "‘", - "withShiftAltGr": "’" + "withShift": "}" }, "Quote": { "unmodified": "'", - "withShift": "\"", - "withAltGr": "æ", - "withShiftAltGr": "Æ" + "withShift": "\"" } } From b823c1e5e3a809ab51479d75a7d97dbc1538b3a9 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 13 Sep 2016 16:15:45 -0700 Subject: [PATCH 12/24] Restore special handling of the dvorak-querty-command layout Signed-off-by: Nathan Sobo --- spec/helpers/keymaps/dvorak-qwerty-cmd.json | 710 ++++++++++++++++++++ spec/keymap-manager-spec.coffee | 12 +- src/helpers.coffee | 6 +- 3 files changed, 725 insertions(+), 3 deletions(-) create mode 100644 spec/helpers/keymaps/dvorak-qwerty-cmd.json diff --git a/spec/helpers/keymaps/dvorak-qwerty-cmd.json b/spec/helpers/keymaps/dvorak-qwerty-cmd.json new file mode 100644 index 0000000..5e807f0 --- /dev/null +++ b/spec/helpers/keymaps/dvorak-qwerty-cmd.json @@ -0,0 +1,710 @@ +{ + "KeyA": { + "unmodified": "a", + "withShift": "A", + "withOption": "å", + "withOptionShift": "Å" + }, + "KeyB": { + "unmodified": "x", + "withShift": "X", + "withOption": "≈", + "withOptionShift": "˛" + }, + "KeyC": { + "unmodified": "j", + "withShift": "J", + "withOption": "∆", + "withOptionShift": "Ô" + }, + "KeyD": { + "unmodified": "e", + "withShift": "E", + "withOption": "", + "withOptionShift": "´" + }, + "KeyE": { + "unmodified": ".", + "withShift": ">", + "withOption": "≥", + "withOptionShift": "˘" + }, + "KeyF": { + "unmodified": "u", + "withShift": "U", + "withOption": "", + "withOptionShift": "¨" + }, + "KeyG": { + "unmodified": "i", + "withShift": "I", + "withOption": "", + "withOptionShift": "ˆ" + }, + "KeyH": { + "unmodified": "d", + "withShift": "D", + "withOption": "∂", + "withOptionShift": "Î" + }, + "KeyI": { + "unmodified": "c", + "withShift": "C", + "withOption": "ç", + "withOptionShift": "Ç" + }, + "KeyJ": { + "unmodified": "h", + "withShift": "H", + "withOption": "˙", + "withOptionShift": "Ó" + }, + "KeyK": { + "unmodified": "t", + "withShift": "T", + "withOption": "†", + "withOptionShift": "ˇ" + }, + "KeyL": { + "unmodified": "n", + "withShift": "N", + "withOption": "", + "withOptionShift": "˜" + }, + "KeyM": { + "unmodified": "m", + "withShift": "M", + "withOption": "µ", + "withOptionShift": "Â" + }, + "KeyN": { + "unmodified": "b", + "withShift": "B", + "withOption": "∫", + "withOptionShift": "ı" + }, + "KeyO": { + "unmodified": "r", + "withShift": "R", + "withOption": "®", + "withOptionShift": "‰" + }, + "KeyP": { + "unmodified": "l", + "withShift": "L", + "withOption": "¬", + "withOptionShift": "Ò" + }, + "KeyQ": { + "unmodified": "'", + "withShift": "\"", + "withOption": "æ", + "withOptionShift": "Æ" + }, + "KeyR": { + "unmodified": "p", + "withShift": "P", + "withOption": "π", + "withOptionShift": "∏" + }, + "KeyS": { + "unmodified": "o", + "withShift": "O", + "withOption": "ø", + "withOptionShift": "Ø" + }, + "KeyT": { + "unmodified": "y", + "withShift": "Y", + "withOption": "¥", + "withOptionShift": "Á" + }, + "KeyU": { + "unmodified": "g", + "withShift": "G", + "withOption": "©", + "withOptionShift": "˝" + }, + "KeyV": { + "unmodified": "k", + "withShift": "K", + "withOption": "˚", + "withOptionShift": "" + }, + "KeyW": { + "unmodified": ",", + "withShift": "<", + "withOption": "≤", + "withOptionShift": "¯" + }, + "KeyX": { + "unmodified": "q", + "withShift": "Q", + "withOption": "œ", + "withOptionShift": "Œ" + }, + "KeyY": { + "unmodified": "f", + "withShift": "F", + "withOption": "ƒ", + "withOptionShift": "Ï" + }, + "KeyZ": { + "unmodified": ";", + "withShift": ":", + "withOption": "…", + "withOptionShift": "Ú" + }, + "Digit1": { + "unmodified": "1", + "withShift": "!", + "withOption": "¡", + "withOptionShift": "⁄" + }, + "Digit2": { + "unmodified": "2", + "withShift": "@", + "withOption": "™", + "withOptionShift": "€" + }, + "Digit3": { + "unmodified": "3", + "withShift": "#", + "withOption": "£", + "withOptionShift": "‹" + }, + "Digit4": { + "unmodified": "4", + "withShift": "$", + "withOption": "¢", + "withOptionShift": "›" + }, + "Digit5": { + "unmodified": "5", + "withShift": "%", + "withOption": "∞", + "withOptionShift": "fi" + }, + "Digit6": { + "unmodified": "6", + "withShift": "^", + "withOption": "§", + "withOptionShift": "fl" + }, + "Digit7": { + "unmodified": "7", + "withShift": "&", + "withOption": "¶", + "withOptionShift": "‡" + }, + "Digit8": { + "unmodified": "8", + "withShift": "*", + "withOption": "•", + "withOptionShift": "°" + }, + "Digit9": { + "unmodified": "9", + "withShift": "(", + "withOption": "ª", + "withOptionShift": "·" + }, + "Digit0": { + "unmodified": "0", + "withShift": ")", + "withOption": "º", + "withOptionShift": "‚" + }, + "Enter": { + "unmodified": "\r", + "withShift": "\r", + "withOption": "\r", + "withOptionShift": "\r" + }, + "Escape": { + "unmodified": "\u001b", + "withShift": "\u001b", + "withOption": "\u001b", + "withOptionShift": "\u001b" + }, + "Backspace": { + "unmodified": "\b", + "withShift": "\b", + "withOption": "\b", + "withOptionShift": "\b" + }, + "Tab": { + "unmodified": "\t", + "withShift": "\t", + "withOption": "\t", + "withOptionShift": "\t" + }, + "Space": { + "unmodified": " ", + "withShift": " ", + "withOption": " ", + "withOptionShift": " " + }, + "Minus": { + "unmodified": "[", + "withShift": "{", + "withOption": "“", + "withOptionShift": "”" + }, + "Equal": { + "unmodified": "]", + "withShift": "}", + "withOption": "‘", + "withOptionShift": "’" + }, + "BracketLeft": { + "unmodified": "/", + "withShift": "?", + "withOption": "÷", + "withOptionShift": "¿" + }, + "BracketRight": { + "unmodified": "=", + "withShift": "+", + "withOption": "≠", + "withOptionShift": "±" + }, + "Backslash": { + "unmodified": "\\", + "withShift": "|", + "withOption": "«", + "withOptionShift": "»" + }, + "Semicolon": { + "unmodified": "s", + "withShift": "S", + "withOption": "ß", + "withOptionShift": "Í" + }, + "Quote": { + "unmodified": "-", + "withShift": "_", + "withOption": "–", + "withOptionShift": "—" + }, + "Backquote": { + "unmodified": "`", + "withShift": "~", + "withOption": "", + "withOptionShift": "`" + }, + "Comma": { + "unmodified": "w", + "withShift": "W", + "withOption": "∑", + "withOptionShift": "„" + }, + "Period": { + "unmodified": "v", + "withShift": "V", + "withOption": "√", + "withOptionShift": "◊" + }, + "Slash": { + "unmodified": "z", + "withShift": "Z", + "withOption": "Ω", + "withOptionShift": "¸" + }, + "CapsLock": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "F1": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "F2": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "F3": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "F4": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "F5": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "F6": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "F7": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "F8": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "F9": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "F10": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "F11": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "F12": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "Insert": { + "unmodified": "\u0005", + "withShift": "\u0005", + "withOption": "\u0005", + "withOptionShift": "\u0005" + }, + "Home": { + "unmodified": "\u0001", + "withShift": "\u0001", + "withOption": "\u0001", + "withOptionShift": "\u0001" + }, + "PageUp": { + "unmodified": "\u000b", + "withShift": "\u000b", + "withOption": "\u000b", + "withOptionShift": "\u000b" + }, + "Delete": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "End": { + "unmodified": "\u0004", + "withShift": "\u0004", + "withOption": "\u0004", + "withOptionShift": "\u0004" + }, + "PageDown": { + "unmodified": "\f", + "withShift": "\f", + "withOption": "\f", + "withOptionShift": "\f" + }, + "ArrowRight": { + "unmodified": "\u001d", + "withShift": "\u001d", + "withOption": "\u001d", + "withOptionShift": "\u001d" + }, + "ArrowLeft": { + "unmodified": "\u001c", + "withShift": "\u001c", + "withOption": "\u001c", + "withOptionShift": "\u001c" + }, + "ArrowDown": { + "unmodified": "\u001f", + "withShift": "\u001f", + "withOption": "\u001f", + "withOptionShift": "\u001f" + }, + "ArrowUp": { + "unmodified": "\u001e", + "withShift": "\u001e", + "withOption": "\u001e", + "withOptionShift": "\u001e" + }, + "NumLock": { + "unmodified": "\u001b", + "withShift": "\u001b", + "withOption": "\u001b", + "withOptionShift": "\u001b" + }, + "NumpadDivide": { + "unmodified": "/", + "withShift": "/", + "withOption": "/", + "withOptionShift": "/" + }, + "NumpadMultiply": { + "unmodified": "*", + "withShift": "*", + "withOption": "*", + "withOptionShift": "*" + }, + "NumpadSubtract": { + "unmodified": "-", + "withShift": "-", + "withOption": "-", + "withOptionShift": "-" + }, + "NumpadAdd": { + "unmodified": "+", + "withShift": "+", + "withOption": "+", + "withOptionShift": "+" + }, + "NumpadEnter": { + "unmodified": "\u0003", + "withShift": "\u0003", + "withOption": "\u0003", + "withOptionShift": "\u0003" + }, + "Numpad1": { + "unmodified": "1", + "withShift": "1", + "withOption": "1", + "withOptionShift": "1" + }, + "Numpad2": { + "unmodified": "2", + "withShift": "2", + "withOption": "2", + "withOptionShift": "2" + }, + "Numpad3": { + "unmodified": "3", + "withShift": "3", + "withOption": "3", + "withOptionShift": "3" + }, + "Numpad4": { + "unmodified": "4", + "withShift": "4", + "withOption": "4", + "withOptionShift": "4" + }, + "Numpad5": { + "unmodified": "5", + "withShift": "5", + "withOption": "5", + "withOptionShift": "5" + }, + "Numpad6": { + "unmodified": "6", + "withShift": "6", + "withOption": "6", + "withOptionShift": "6" + }, + "Numpad7": { + "unmodified": "7", + "withShift": "7", + "withOption": "7", + "withOptionShift": "7" + }, + "Numpad8": { + "unmodified": "8", + "withShift": "8", + "withOption": "8", + "withOptionShift": "8" + }, + "Numpad9": { + "unmodified": "9", + "withShift": "9", + "withOption": "9", + "withOptionShift": "9" + }, + "Numpad0": { + "unmodified": "0", + "withShift": "0", + "withOption": "0", + "withOptionShift": "0" + }, + "NumpadDecimal": { + "unmodified": ".", + "withShift": ".", + "withOption": ".", + "withOptionShift": "." + }, + "IntlBackslash": { + "unmodified": "§", + "withShift": "±", + "withOption": "§", + "withOptionShift": "±" + }, + "ContextMenu": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "NumpadEqual": { + "unmodified": "=", + "withShift": "=", + "withOption": "=", + "withOptionShift": "=" + }, + "F13": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "F14": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "F15": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "F16": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "F17": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "F18": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "F19": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "F20": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "AudioVolumeMute": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "AudioVolumeUp": { + "unmodified": "\u001f", + "withShift": "=", + "withOption": "\u001f", + "withOptionShift": "=" + }, + "AudioVolumeDown": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "NumpadComma": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "IntlRo": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "KanaMode": { + "unmodified": "\u0010", + "withShift": "\u0010", + "withOption": "\u0010", + "withOptionShift": "\u0010" + }, + "IntlYen": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "ControlLeft": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "ShiftLeft": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "AltLeft": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "MetaLeft": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "ControlRight": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "ShiftRight": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "AltRight": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + }, + "MetaRight": { + "unmodified": "", + "withShift": "", + "withOption": "", + "withOptionShift": "" + } +} diff --git a/spec/keymap-manager-spec.coffee b/spec/keymap-manager-spec.coffee index b0c7b44..d96088f 100644 --- a/spec/keymap-manager-spec.coffee +++ b/spec/keymap-manager-spec.coffee @@ -3,6 +3,7 @@ debounce = require 'debounce' fs = require 'fs-plus' path = require 'path' temp = require 'temp' +KeyboardLayout = require('keyboard-layout') KeymapManager = require '../src/keymap-manager' {buildKeydownEvent, buildKeyupEvent} = KeymapManager {appendContent, stub, getFakeClock, mockProcessPlatform} = require './helpers/helpers' @@ -601,8 +602,17 @@ describe "KeymapManager", -> assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'A', ctrlKey: true, shiftKey: true}), 'ctrl-shift-A') assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '{', shiftKey: true}), '{') + describe "when the Dvorak QWERTY-⌘ layout is in use on macOS", -> + it "uses the US layout equivalent when the command key is held down", -> + mockProcessPlatform('darwin') + stub(KeyboardLayout, 'getCurrentKeymap', -> require('./helpers/keymaps/dvorak-qwerty-cmd')) + stub(KeyboardLayout, 'getCurrentKeyboardLayout', -> 'com.apple.keylayout.DVORAK-QWERTYCMD') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'l', code: 'KeyP', altKey: true}), 'alt-l') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'l', code: 'KeyP', ctrlKey: true, altKey: true}), 'ctrl-alt-l') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'l', code: 'KeyP', metaKey: true}), 'cmd-p') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'L', code: 'KeyP', metaKey: true, shiftKey: true}), 'shift-cmd-P') + describe "international layouts", -> - KeyboardLayout = require('keyboard-layout') currentKeymap = null beforeEach -> diff --git a/src/helpers.coffee b/src/helpers.coffee index c7f9dd3..ca431ff 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -33,7 +33,7 @@ exports.normalizeKeystrokes = (keystrokes) -> return false normalizedKeystrokes.join(' ') -exports.keystrokeForKeyboardEvent = (event, dvorakQwertyWorkaroundEnabled) -> +exports.keystrokeForKeyboardEvent = (event) -> {ctrlKey, altKey, shiftKey, metaKey} = event isNonCharacterKey = event.key.length > 1 @@ -64,7 +64,9 @@ exports.keystrokeForKeyboardEvent = (event, dvorakQwertyWorkaroundEnabled) -> altKey = false if event.getModifierState('AltGraph') # Use US equivalent character for non-latin characters in keystrokes with modifiers - if not isLatin(key) and (ctrlKey or altKey or metaKey) + # or when using the dvorak-qwertycmd layout and holding down the command key. + if (not isLatin(key) and (ctrlKey or altKey or metaKey)) or + (metaKey and KeyboardLayout.getCurrentKeyboardLayout() is 'com.apple.keylayout.DVORAK-QWERTYCMD') if characters = usCharactersForKeyCode(event.code) if event.shiftKey key = characters.withShift From 63ae823d7d22d6ee83403ed15a0843a8c0f69f63 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 13 Sep 2016 16:58:18 -0700 Subject: [PATCH 13/24] :arrow_up: keyboard-layout --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4f05fde..b726b78 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "event-kit": "^1.0.0", "fs-plus": "^2.0.4", "grim": "^1.2.1", - "keyboard-layout": "^1.0", + "keyboard-layout": "^1.1.0", "pathwatcher": "^6.2", "property-accessors": "^1", "season": "^5.0.2" From 56b9cc5b818165bf2755d5f7fd002dc8585b1d9d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Sep 2016 07:49:25 -0600 Subject: [PATCH 14/24] :shower: --- src/helpers.coffee | 96 +++++++-------------------------------- src/keymap-manager.coffee | 4 +- 2 files changed, 18 insertions(+), 82 deletions(-) diff --git a/src/helpers.coffee b/src/helpers.coffee index ca431ff..5bc236f 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -2,10 +2,8 @@ KeyboardLayout = require 'keyboard-layout' Modifiers = new Set(['ctrl', 'alt', 'shift', 'cmd']) -AtomModifierRegex = /(ctrl|alt|shift|cmd)$/ +EndsInModifierRegex = /(ctrl|alt|shift|cmd)$/ WhitespaceRegex = /\s+/ -LowerCaseLetterRegex = /^[a-z]$/ -UpperCaseLetterRegex = /^[A-Z]$/ ExactMatch = 'exact' KeydownExactMatch = 'keydownExact' PartialMatch = 'partial' @@ -18,11 +16,17 @@ NonCharacterKeyNamesByDOM3Key = { 'ArrowRight': 'right' } -isASCII = (character) -> character.charCodeAt(0) <= 127 +isASCIICharacter = (character) -> + character? and character.length is 1 and character.charCodeAt(0) <= 127 -isLatin = (character) -> character.charCodeAt(0) <= 0x024F +isLatinCharacter = (character) -> + character? and character.length is 1 and character.charCodeAt(0) <= 0x024F -isUpperCaseLatin = (character) -> isLatin(character) and character.toLowerCase() isnt character +isUpperCaseCharacter = (character) -> + character? and character.length is 1 and character.toLowerCase() isnt character + +isLowerCaseCharacter = (character) -> + character? and character.length is 1 and character.toUpperCase() isnt character exports.normalizeKeystrokes = (keystrokes) -> normalizedKeystrokes = [] @@ -56,7 +60,7 @@ exports.keystrokeForKeyboardEvent = (event) -> else nonAltModifiedKey = characters.unmodified - if not ctrlKey and not metaKey and isASCII(key) and key isnt nonAltModifiedKey + if not ctrlKey and not metaKey and isASCIICharacter(key) and key isnt nonAltModifiedKey altKey = false else key = nonAltModifiedKey @@ -65,7 +69,7 @@ exports.keystrokeForKeyboardEvent = (event) -> # Use US equivalent character for non-latin characters in keystrokes with modifiers # or when using the dvorak-qwertycmd layout and holding down the command key. - if (not isLatin(key) and (ctrlKey or altKey or metaKey)) or + if (not isLatinCharacter(key) and (ctrlKey or altKey or metaKey)) or (metaKey and KeyboardLayout.getCurrentKeyboardLayout() is 'com.apple.keylayout.DVORAK-QWERTYCMD') if characters = usCharactersForKeyCode(event.code) if event.shiftKey @@ -81,7 +85,7 @@ exports.keystrokeForKeyboardEvent = (event) -> keystroke += '-' if keystroke.length > 0 keystroke += 'alt' - if key is 'shift' or (shiftKey and (isNonCharacterKey or isUpperCaseLatin(key))) + if key is 'shift' or (shiftKey and (isNonCharacterKey or (isLatinCharacter(key) and isUpperCaseCharacter(key)))) keystroke += '-' if keystroke keystroke += 'shift' @@ -101,8 +105,7 @@ exports.characterForKeyboardEvent = (event) -> exports.calculateSpecificity = calculateSpecificity -exports.isAtomModifier = (keystroke) -> - Modifiers.has(keystroke) or AtomModifierRegex.test(keystroke) +exports.isBareModifier = (keystroke) -> EndsInModifierRegex.test(keystroke) exports.keydownEvent = (key, options) -> return keyboardEvent(key, 'keydown', options) @@ -197,8 +200,8 @@ normalizeKeystroke = (keystroke) -> if isKeyup primaryKey = primaryKey.toLowerCase() if primaryKey? else - modifiers.add('shift') if UpperCaseLetterRegex.test(primaryKey) - if modifiers.has('shift') and LowerCaseLetterRegex.test(primaryKey) + modifiers.add('shift') if isUpperCaseCharacter(primaryKey) + if modifiers.has('shift') and isLowerCaseCharacter(primaryKey) primaryKey = primaryKey.toUpperCase() keystroke = [] @@ -225,73 +228,6 @@ parseKeystroke = (keystroke) -> keys.push(keystroke.substring(keyStart)) if keyStart < keystroke.length keys -keyForKeyboardEvent = (event) -> - - keyIdentifier = event.keyIdentifier - if process.platform in ['linux', 'win32'] - keyIdentifier = translateKeyIdentifierForWindowsAndLinuxChromiumBug(keyIdentifier) - - return keyIdentifier if KEYBOARD_EVENT_MODIFIERS.has(keyIdentifier) - - charCode = charCodeFromKeyIdentifier(keyIdentifier) - - if dvorakQwertyWorkaroundEnabled and typeof charCode is 'number' - if event.keyCode is 46 # key code for 'delete' - charCode = 127 # ASCII character code for 'delete' - else - charCode = event.keyCode - - if charCode? - if process.platform in ['linux', 'win32'] - charCode = translateCharCodeForWindowsAndLinuxChromiumBug(charCode, event.shiftKey) - - if event.location is KeyboardEvent.DOM_KEY_LOCATION_NUMPAD - # This is a numpad number - charCode = numpadToASCII(charCode) - - charCode = event.which if not isASCII(charCode) and isASCII(event.keyCode) - key = keyFromCharCode(charCode) - else - key = keyIdentifier.toLowerCase() - - # Only upper case alphabetic characters like 'a' - if event.shiftKey - key = key.toUpperCase() if LowerCaseLetterRegex.test(key) - else - key = key.toLowerCase() if UpperCaseLetterRegex.test(key) - - key - -charCodeFromKeyIdentifier = (keyIdentifier) -> - parseInt(keyIdentifier[2..], 16) if keyIdentifier.indexOf('U+') is 0 - -# Chromium includes incorrect keyIdentifier values on keypress events for -# certain symbols keys on Window and Linux. -# -# See https://code.google.com/p/chromium/issues/detail?id=51024 -# See https://bugs.webkit.org/show_bug.cgi?id=19906 -translateKeyIdentifierForWindowsAndLinuxChromiumBug = (keyIdentifier) -> - WindowsAndLinuxKeyIdentifierTranslations[keyIdentifier] ? keyIdentifier - -translateCharCodeForWindowsAndLinuxChromiumBug = (charCode, shift) -> - if translation = WindowsAndLinuxCharCodeTranslations[charCode] - if shift then translation.shifted else translation.unshifted - else - charCode - -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) - -numpadToASCII = (charCode) -> - NumPadToASCII[charCode] ? charCode - usKeymap = null usCharactersForKeyCode = (code) -> usKeymap ?= require('./us-keymap') diff --git a/src/keymap-manager.coffee b/src/keymap-manager.coffee index a5b18db..3b5ce24 100644 --- a/src/keymap-manager.coffee +++ b/src/keymap-manager.coffee @@ -7,7 +7,7 @@ path = require 'path' {Emitter, Disposable, CompositeDisposable} = require 'event-kit' KeyBinding = require './key-binding' CommandEvent = require './command-event' -{normalizeKeystrokes, keystrokeForKeyboardEvent, isAtomModifier, keydownEvent, keyupEvent, characterForKeyboardEvent, keystrokesMatch} = require './helpers' +{normalizeKeystrokes, keystrokeForKeyboardEvent, isBareModifier, keydownEvent, keyupEvent, characterForKeyboardEvent, keystrokesMatch} = require './helpers' Platforms = ['darwin', 'freebsd', 'linux', 'sunos', 'win32'] OtherPlatforms = Platforms.filter (platform) -> platform isnt process.platform @@ -493,7 +493,7 @@ class KeymapManager keystroke = @keystrokeForKeyboardEvent(event) # We dont care about bare modifier keys in the bindings. e.g. `ctrl y` isnt going to work. - if event.type is 'keydown' and @queuedKeystrokes.length > 0 and isAtomModifier(keystroke) + if event.type is 'keydown' and @queuedKeystrokes.length > 0 and isBareModifier(keystroke) event.preventDefault() return From d56c1b3078d64dbf1175ef669e11c799a6a340c8 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Sep 2016 07:54:47 -0600 Subject: [PATCH 15/24] :art: constant names --- src/helpers.coffee | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/helpers.coffee b/src/helpers.coffee index 5bc236f..3532c01 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -1,13 +1,10 @@ {calculateSpecificity} = require 'clear-cut' KeyboardLayout = require 'keyboard-layout' -Modifiers = new Set(['ctrl', 'alt', 'shift', 'cmd']) -EndsInModifierRegex = /(ctrl|alt|shift|cmd)$/ -WhitespaceRegex = /\s+/ -ExactMatch = 'exact' -KeydownExactMatch = 'keydownExact' -PartialMatch = 'partial' -NonCharacterKeyNamesByDOM3Key = { +MODIFIERS = new Set(['ctrl', 'alt', 'shift', 'cmd']) +ENDS_IN_MODIFIER_REGEX = /(ctrl|alt|shift|cmd)$/ +WHITESPACE_REGEX = /\s+/ +NON_CHARACTER_KEY_NAMES_BY_KEYBOARD_EVENT_KEY = { 'Control': 'ctrl', 'Meta': 'cmd', 'ArrowDown': 'down', @@ -15,6 +12,11 @@ NonCharacterKeyNamesByDOM3Key = { 'ArrowLeft': 'left', 'ArrowRight': 'right' } +MATCH_TYPES = { + EXACT: 'exact' + KEYDOWN_EXACT: 'keydownExact' + PARTIAL: 'partial' +} isASCIICharacter = (character) -> character? and character.length is 1 and character.charCodeAt(0) <= 127 @@ -30,7 +32,7 @@ isLowerCaseCharacter = (character) -> exports.normalizeKeystrokes = (keystrokes) -> normalizedKeystrokes = [] - for keystroke in keystrokes.split(WhitespaceRegex) + for keystroke in keystrokes.split(WHITESPACE_REGEX) if normalizedKeystroke = normalizeKeystroke(keystroke) normalizedKeystrokes.push(normalizedKeystroke) else @@ -42,7 +44,7 @@ exports.keystrokeForKeyboardEvent = (event) -> isNonCharacterKey = event.key.length > 1 if isNonCharacterKey - key = NonCharacterKeyNamesByDOM3Key[event.key] ? event.key.toLowerCase() + key = NON_CHARACTER_KEY_NAMES_BY_KEYBOARD_EVENT_KEY[event.key] ? event.key.toLowerCase() else key = event.key @@ -93,7 +95,7 @@ exports.keystrokeForKeyboardEvent = (event) -> keystroke += '-' if keystroke keystroke += 'cmd' - unless Modifiers.has(key) + unless MODIFIERS.has(key) keystroke += '-' if keystroke keystroke += key @@ -105,7 +107,7 @@ exports.characterForKeyboardEvent = (event) -> exports.calculateSpecificity = calculateSpecificity -exports.isBareModifier = (keystroke) -> EndsInModifierRegex.test(keystroke) +exports.isBareModifier = (keystroke) -> ENDS_IN_MODIFIER_REGEX.test(keystroke) exports.keydownEvent = (key, options) -> return keyboardEvent(key, 'keydown', options) @@ -172,11 +174,11 @@ exports.keystrokesMatch = (bindingKeystrokes, userKeystrokes) -> return false if userKeystrokeIndex < userKeystrokes.length - 1 if isPartialMatch and bindingRemainderContainsOnlyKeyups - KeydownExactMatch + MATCH_TYPES.KEYDOWN_EXACT else if isPartialMatch - PartialMatch + MATCH_TYPES.PARTIAL else - ExactMatch + MATCH_TYPES.EXACT normalizeKeystroke = (keystroke) -> if isKeyup = keystroke.startsWith('^') @@ -188,7 +190,7 @@ normalizeKeystroke = (keystroke) -> modifiers = new Set for key, i in keys - if Modifiers.has(key) + if MODIFIERS.has(key) modifiers.add(key) else # only the last key can be a non-modifier From ec9a089a4b05a0f86b90835afc2d37e5c58089d6 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Sep 2016 08:00:12 -0600 Subject: [PATCH 16/24] :art: helpers module organization --- src/helpers.coffee | 116 ++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/src/helpers.coffee b/src/helpers.coffee index 3532c01..0876476 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -30,6 +30,11 @@ isUpperCaseCharacter = (character) -> isLowerCaseCharacter = (character) -> character? and character.length is 1 and character.toUpperCase() isnt character +usKeymap = null +usCharactersForKeyCode = (code) -> + usKeymap ?= require('./us-keymap') + usKeymap[code] + exports.normalizeKeystrokes = (keystrokes) -> normalizedKeystrokes = [] for keystroke in keystrokes.split(WHITESPACE_REGEX) @@ -39,6 +44,56 @@ exports.normalizeKeystrokes = (keystrokes) -> return false normalizedKeystrokes.join(' ') +normalizeKeystroke = (keystroke) -> + if isKeyup = keystroke.startsWith('^') + keystroke = keystroke.slice(1) + keys = parseKeystroke(keystroke) + return false unless keys + + primaryKey = null + modifiers = new Set + + for key, i in keys + if MODIFIERS.has(key) + modifiers.add(key) + else + # only the last key can be a non-modifier + if i is keys.length - 1 + primaryKey = key + else + return false + + if isKeyup + primaryKey = primaryKey.toLowerCase() if primaryKey? + else + modifiers.add('shift') if isUpperCaseCharacter(primaryKey) + if modifiers.has('shift') and isLowerCaseCharacter(primaryKey) + primaryKey = primaryKey.toUpperCase() + + keystroke = [] + if not isKeyup or (isKeyup and not primaryKey?) + keystroke.push('ctrl') if modifiers.has('ctrl') + keystroke.push('alt') if modifiers.has('alt') + keystroke.push('shift') if modifiers.has('shift') + keystroke.push('cmd') if modifiers.has('cmd') + keystroke.push(primaryKey) if primaryKey? + keystroke = keystroke.join('-') + keystroke = "^#{keystroke}" if isKeyup + keystroke + +parseKeystroke = (keystroke) -> + keys = [] + keyStart = 0 + for character, index in keystroke when character is '-' + if index > keyStart + keys.push(keystroke.substring(keyStart, index)) + keyStart = index + 1 + + # The keystroke has a trailing - and is invalid + return false if keyStart is keystroke.length + keys.push(keystroke.substring(keyStart)) if keyStart < keystroke.length + keys + exports.keystrokeForKeyboardEvent = (event) -> {ctrlKey, altKey, shiftKey, metaKey} = event isNonCharacterKey = event.key.length > 1 @@ -110,12 +165,12 @@ exports.calculateSpecificity = calculateSpecificity exports.isBareModifier = (keystroke) -> ENDS_IN_MODIFIER_REGEX.test(keystroke) exports.keydownEvent = (key, options) -> - return keyboardEvent(key, 'keydown', options) + return buildKeyboardEvent(key, 'keydown', options) exports.keyupEvent = (key, options) -> - return keyboardEvent(key, 'keyup', options) + return buildKeyboardEvent(key, 'keyup', options) -keyboardEvent = (key, eventType, {ctrl, shift, alt, cmd, keyCode, target, location}={}) -> +buildKeyboardEvent = (key, eventType, {ctrl, shift, alt, cmd, keyCode, target, location}={}) -> ctrlKey = ctrl ? false altKey = alt ? false shiftKey = shift ? false @@ -179,58 +234,3 @@ exports.keystrokesMatch = (bindingKeystrokes, userKeystrokes) -> MATCH_TYPES.PARTIAL else MATCH_TYPES.EXACT - -normalizeKeystroke = (keystroke) -> - if isKeyup = keystroke.startsWith('^') - keystroke = keystroke.slice(1) - keys = parseKeystroke(keystroke) - return false unless keys - - primaryKey = null - modifiers = new Set - - for key, i in keys - if MODIFIERS.has(key) - modifiers.add(key) - else - # only the last key can be a non-modifier - if i is keys.length - 1 - primaryKey = key - else - return false - - if isKeyup - primaryKey = primaryKey.toLowerCase() if primaryKey? - else - modifiers.add('shift') if isUpperCaseCharacter(primaryKey) - if modifiers.has('shift') and isLowerCaseCharacter(primaryKey) - primaryKey = primaryKey.toUpperCase() - - keystroke = [] - if not isKeyup or (isKeyup and not primaryKey?) - keystroke.push('ctrl') if modifiers.has('ctrl') - keystroke.push('alt') if modifiers.has('alt') - keystroke.push('shift') if modifiers.has('shift') - keystroke.push('cmd') if modifiers.has('cmd') - keystroke.push(primaryKey) if primaryKey? - keystroke = keystroke.join('-') - keystroke = "^#{keystroke}" if isKeyup - keystroke - -parseKeystroke = (keystroke) -> - keys = [] - keyStart = 0 - for character, index in keystroke when character is '-' - if index > keyStart - keys.push(keystroke.substring(keyStart, index)) - keyStart = index + 1 - - # The keystroke has a trailing - and is invalid - return false if keyStart is keystroke.length - keys.push(keystroke.substring(keyStart)) if keyStart < keystroke.length - keys - -usKeymap = null -usCharactersForKeyCode = (code) -> - usKeymap ?= require('./us-keymap') - usKeymap[code] From e9eeeca6b5f5bcd7ae9ce6dbdc169c58df023063 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Sep 2016 09:08:23 -0600 Subject: [PATCH 17/24] Use rimraf in clean script for portability --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b726b78..63c898b 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "./lib/keymap-manager", "scripts": { "prepublish": "npm run clean && npm run compile && npm run lint && npm run atomdoc", - "clean": "rm -rf lib && rm -rf api.json", + "clean": "rimraf lib && rimraf api.json", "compile": "coffee --no-header --output lib --compile src && babel src --out-dir lib", "lint": "coffeelint -r src spec && eslint src spec", "test": "devtool --quit --console node_modules/mocha/bin/_mocha --colors spec/helpers/setup.js spec/*", From 4b139f9de276b40e844771534aa7ef4a9e810b6d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Sep 2016 10:10:46 -0600 Subject: [PATCH 18/24] 6.3.3-beta0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 63c898b..61836f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "atom-keymap", - "version": "6.3.2", + "version": "6.3.3-beta0", "description": "Atom's DOM-aware keymap module", "main": "./lib/keymap-manager", "scripts": { From ef9419a9cb08b9baccccb692085a3b1f0b500527 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Sep 2016 10:58:38 -0600 Subject: [PATCH 19/24] Clear the ctrlKey modifier on Windows when AltGraph is detected Signed-off-by: Max Brunsfeld --- spec/keymap-manager-spec.coffee | 6 +++--- src/helpers.coffee | 9 +++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/spec/keymap-manager-spec.coffee b/spec/keymap-manager-spec.coffee index d96088f..54df182 100644 --- a/spec/keymap-manager-spec.coffee +++ b/spec/keymap-manager-spec.coffee @@ -631,9 +631,9 @@ describe "KeymapManager", -> it "allows arbitrary characters to be typed via an altgraph modifier on Windows and Linux", -> mockProcessPlatform('win32') - assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '@', altKey: true, getModifierState: (key) -> key is 'AltGraph'}), '@') - assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '€', altKey: true, getModifierState: (key) -> key is 'AltGraph'}), '€') - assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'Ë', altKey: true, shiftKey: true, getModifierState: (key) -> key is 'AltGraph'}), 'shift-Ë') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '@', ctrlKey: true, altKey: true, getModifierState: (key) -> key is 'AltGraph'}), '@') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '€', ctrlKey: true, altKey: true, getModifierState: (key) -> key is 'AltGraph'}), '€') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'Ë', ctrlKey: true, altKey: true, shiftKey: true, getModifierState: (key) -> key is 'AltGraph'}), 'shift-Ë') assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'g', altKey: true, getModifierState: (key) -> false}), 'alt-g') assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'e', altKey: true, getModifierState: (key) -> false}), 'alt-e') assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'E', altKey: true, shiftKey: true, getModifierState: (key) -> false}), 'alt-shift-E') diff --git a/src/helpers.coffee b/src/helpers.coffee index 0876476..bfd73a6 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -121,8 +121,13 @@ exports.keystrokeForKeyboardEvent = (event) -> altKey = false else key = nonAltModifiedKey - else - altKey = false if event.getModifierState('AltGraph') + else if process.platform is 'win32' + if event.getModifierState('AltGraph') + altKey = false + ctrlKey = false + else if process.platform is 'linux' + if event.getModifierState('AltGraph') + altKey = false # Use US equivalent character for non-latin characters in keystrokes with modifiers # or when using the dvorak-qwertycmd layout and holding down the command key. From 5be368e96cf2b4457aca11afa9b85095f829b989 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 14 Sep 2016 10:59:21 -0600 Subject: [PATCH 20/24] 6.3.3-beta1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 61836f2..32cfd70 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "atom-keymap", - "version": "6.3.3-beta0", + "version": "6.3.3-beta1", "description": "Atom's DOM-aware keymap module", "main": "./lib/keymap-manager", "scripts": { From 2452838e4f81b084f2350d21af7e9889ce66efe1 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 15 Sep 2016 13:13:05 -0600 Subject: [PATCH 21/24] Allow ctrl-alt- bindings on Windows unless AltGraph variant is ASCII Signed-off-by: Max Brunsfeld --- spec/helpers/keymaps/dvorak-qwerty-cmd.json | 710 ------------------ .../keymaps/mac-dvorak-qwerty-cmd.json | 398 ++++++++++ .../keymaps/{greek.json => mac-greek.json} | 476 ++++++------ spec/helpers/keymaps/mac-swiss-german.json | 398 ++++++++++ .../{turkish.json => mac-turkish.json} | 474 ++++++------ spec/helpers/keymaps/swiss-german.json | 380 ---------- .../helpers/keymaps/windows-swiss-german.json | 314 ++++++++ .../keymaps/windows-us-international.json | 314 ++++++++ spec/keymap-manager-spec.coffee | 26 +- src/helpers.coffee | 43 +- 10 files changed, 1955 insertions(+), 1578 deletions(-) delete mode 100644 spec/helpers/keymaps/dvorak-qwerty-cmd.json create mode 100644 spec/helpers/keymaps/mac-dvorak-qwerty-cmd.json rename spec/helpers/keymaps/{greek.json => mac-greek.json} (50%) create mode 100644 spec/helpers/keymaps/mac-swiss-german.json rename spec/helpers/keymaps/{turkish.json => mac-turkish.json} (50%) delete mode 100644 spec/helpers/keymaps/swiss-german.json create mode 100644 spec/helpers/keymaps/windows-swiss-german.json create mode 100644 spec/helpers/keymaps/windows-us-international.json diff --git a/spec/helpers/keymaps/dvorak-qwerty-cmd.json b/spec/helpers/keymaps/dvorak-qwerty-cmd.json deleted file mode 100644 index 5e807f0..0000000 --- a/spec/helpers/keymaps/dvorak-qwerty-cmd.json +++ /dev/null @@ -1,710 +0,0 @@ -{ - "KeyA": { - "unmodified": "a", - "withShift": "A", - "withOption": "å", - "withOptionShift": "Å" - }, - "KeyB": { - "unmodified": "x", - "withShift": "X", - "withOption": "≈", - "withOptionShift": "˛" - }, - "KeyC": { - "unmodified": "j", - "withShift": "J", - "withOption": "∆", - "withOptionShift": "Ô" - }, - "KeyD": { - "unmodified": "e", - "withShift": "E", - "withOption": "", - "withOptionShift": "´" - }, - "KeyE": { - "unmodified": ".", - "withShift": ">", - "withOption": "≥", - "withOptionShift": "˘" - }, - "KeyF": { - "unmodified": "u", - "withShift": "U", - "withOption": "", - "withOptionShift": "¨" - }, - "KeyG": { - "unmodified": "i", - "withShift": "I", - "withOption": "", - "withOptionShift": "ˆ" - }, - "KeyH": { - "unmodified": "d", - "withShift": "D", - "withOption": "∂", - "withOptionShift": "Î" - }, - "KeyI": { - "unmodified": "c", - "withShift": "C", - "withOption": "ç", - "withOptionShift": "Ç" - }, - "KeyJ": { - "unmodified": "h", - "withShift": "H", - "withOption": "˙", - "withOptionShift": "Ó" - }, - "KeyK": { - "unmodified": "t", - "withShift": "T", - "withOption": "†", - "withOptionShift": "ˇ" - }, - "KeyL": { - "unmodified": "n", - "withShift": "N", - "withOption": "", - "withOptionShift": "˜" - }, - "KeyM": { - "unmodified": "m", - "withShift": "M", - "withOption": "µ", - "withOptionShift": "Â" - }, - "KeyN": { - "unmodified": "b", - "withShift": "B", - "withOption": "∫", - "withOptionShift": "ı" - }, - "KeyO": { - "unmodified": "r", - "withShift": "R", - "withOption": "®", - "withOptionShift": "‰" - }, - "KeyP": { - "unmodified": "l", - "withShift": "L", - "withOption": "¬", - "withOptionShift": "Ò" - }, - "KeyQ": { - "unmodified": "'", - "withShift": "\"", - "withOption": "æ", - "withOptionShift": "Æ" - }, - "KeyR": { - "unmodified": "p", - "withShift": "P", - "withOption": "π", - "withOptionShift": "∏" - }, - "KeyS": { - "unmodified": "o", - "withShift": "O", - "withOption": "ø", - "withOptionShift": "Ø" - }, - "KeyT": { - "unmodified": "y", - "withShift": "Y", - "withOption": "¥", - "withOptionShift": "Á" - }, - "KeyU": { - "unmodified": "g", - "withShift": "G", - "withOption": "©", - "withOptionShift": "˝" - }, - "KeyV": { - "unmodified": "k", - "withShift": "K", - "withOption": "˚", - "withOptionShift": "" - }, - "KeyW": { - "unmodified": ",", - "withShift": "<", - "withOption": "≤", - "withOptionShift": "¯" - }, - "KeyX": { - "unmodified": "q", - "withShift": "Q", - "withOption": "œ", - "withOptionShift": "Œ" - }, - "KeyY": { - "unmodified": "f", - "withShift": "F", - "withOption": "ƒ", - "withOptionShift": "Ï" - }, - "KeyZ": { - "unmodified": ";", - "withShift": ":", - "withOption": "…", - "withOptionShift": "Ú" - }, - "Digit1": { - "unmodified": "1", - "withShift": "!", - "withOption": "¡", - "withOptionShift": "⁄" - }, - "Digit2": { - "unmodified": "2", - "withShift": "@", - "withOption": "™", - "withOptionShift": "€" - }, - "Digit3": { - "unmodified": "3", - "withShift": "#", - "withOption": "£", - "withOptionShift": "‹" - }, - "Digit4": { - "unmodified": "4", - "withShift": "$", - "withOption": "¢", - "withOptionShift": "›" - }, - "Digit5": { - "unmodified": "5", - "withShift": "%", - "withOption": "∞", - "withOptionShift": "fi" - }, - "Digit6": { - "unmodified": "6", - "withShift": "^", - "withOption": "§", - "withOptionShift": "fl" - }, - "Digit7": { - "unmodified": "7", - "withShift": "&", - "withOption": "¶", - "withOptionShift": "‡" - }, - "Digit8": { - "unmodified": "8", - "withShift": "*", - "withOption": "•", - "withOptionShift": "°" - }, - "Digit9": { - "unmodified": "9", - "withShift": "(", - "withOption": "ª", - "withOptionShift": "·" - }, - "Digit0": { - "unmodified": "0", - "withShift": ")", - "withOption": "º", - "withOptionShift": "‚" - }, - "Enter": { - "unmodified": "\r", - "withShift": "\r", - "withOption": "\r", - "withOptionShift": "\r" - }, - "Escape": { - "unmodified": "\u001b", - "withShift": "\u001b", - "withOption": "\u001b", - "withOptionShift": "\u001b" - }, - "Backspace": { - "unmodified": "\b", - "withShift": "\b", - "withOption": "\b", - "withOptionShift": "\b" - }, - "Tab": { - "unmodified": "\t", - "withShift": "\t", - "withOption": "\t", - "withOptionShift": "\t" - }, - "Space": { - "unmodified": " ", - "withShift": " ", - "withOption": " ", - "withOptionShift": " " - }, - "Minus": { - "unmodified": "[", - "withShift": "{", - "withOption": "“", - "withOptionShift": "”" - }, - "Equal": { - "unmodified": "]", - "withShift": "}", - "withOption": "‘", - "withOptionShift": "’" - }, - "BracketLeft": { - "unmodified": "/", - "withShift": "?", - "withOption": "÷", - "withOptionShift": "¿" - }, - "BracketRight": { - "unmodified": "=", - "withShift": "+", - "withOption": "≠", - "withOptionShift": "±" - }, - "Backslash": { - "unmodified": "\\", - "withShift": "|", - "withOption": "«", - "withOptionShift": "»" - }, - "Semicolon": { - "unmodified": "s", - "withShift": "S", - "withOption": "ß", - "withOptionShift": "Í" - }, - "Quote": { - "unmodified": "-", - "withShift": "_", - "withOption": "–", - "withOptionShift": "—" - }, - "Backquote": { - "unmodified": "`", - "withShift": "~", - "withOption": "", - "withOptionShift": "`" - }, - "Comma": { - "unmodified": "w", - "withShift": "W", - "withOption": "∑", - "withOptionShift": "„" - }, - "Period": { - "unmodified": "v", - "withShift": "V", - "withOption": "√", - "withOptionShift": "◊" - }, - "Slash": { - "unmodified": "z", - "withShift": "Z", - "withOption": "Ω", - "withOptionShift": "¸" - }, - "CapsLock": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "F1": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "F2": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "F3": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "F4": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "F5": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "F6": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "F7": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "F8": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "F9": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "F10": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "F11": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "F12": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "Insert": { - "unmodified": "\u0005", - "withShift": "\u0005", - "withOption": "\u0005", - "withOptionShift": "\u0005" - }, - "Home": { - "unmodified": "\u0001", - "withShift": "\u0001", - "withOption": "\u0001", - "withOptionShift": "\u0001" - }, - "PageUp": { - "unmodified": "\u000b", - "withShift": "\u000b", - "withOption": "\u000b", - "withOptionShift": "\u000b" - }, - "Delete": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "End": { - "unmodified": "\u0004", - "withShift": "\u0004", - "withOption": "\u0004", - "withOptionShift": "\u0004" - }, - "PageDown": { - "unmodified": "\f", - "withShift": "\f", - "withOption": "\f", - "withOptionShift": "\f" - }, - "ArrowRight": { - "unmodified": "\u001d", - "withShift": "\u001d", - "withOption": "\u001d", - "withOptionShift": "\u001d" - }, - "ArrowLeft": { - "unmodified": "\u001c", - "withShift": "\u001c", - "withOption": "\u001c", - "withOptionShift": "\u001c" - }, - "ArrowDown": { - "unmodified": "\u001f", - "withShift": "\u001f", - "withOption": "\u001f", - "withOptionShift": "\u001f" - }, - "ArrowUp": { - "unmodified": "\u001e", - "withShift": "\u001e", - "withOption": "\u001e", - "withOptionShift": "\u001e" - }, - "NumLock": { - "unmodified": "\u001b", - "withShift": "\u001b", - "withOption": "\u001b", - "withOptionShift": "\u001b" - }, - "NumpadDivide": { - "unmodified": "/", - "withShift": "/", - "withOption": "/", - "withOptionShift": "/" - }, - "NumpadMultiply": { - "unmodified": "*", - "withShift": "*", - "withOption": "*", - "withOptionShift": "*" - }, - "NumpadSubtract": { - "unmodified": "-", - "withShift": "-", - "withOption": "-", - "withOptionShift": "-" - }, - "NumpadAdd": { - "unmodified": "+", - "withShift": "+", - "withOption": "+", - "withOptionShift": "+" - }, - "NumpadEnter": { - "unmodified": "\u0003", - "withShift": "\u0003", - "withOption": "\u0003", - "withOptionShift": "\u0003" - }, - "Numpad1": { - "unmodified": "1", - "withShift": "1", - "withOption": "1", - "withOptionShift": "1" - }, - "Numpad2": { - "unmodified": "2", - "withShift": "2", - "withOption": "2", - "withOptionShift": "2" - }, - "Numpad3": { - "unmodified": "3", - "withShift": "3", - "withOption": "3", - "withOptionShift": "3" - }, - "Numpad4": { - "unmodified": "4", - "withShift": "4", - "withOption": "4", - "withOptionShift": "4" - }, - "Numpad5": { - "unmodified": "5", - "withShift": "5", - "withOption": "5", - "withOptionShift": "5" - }, - "Numpad6": { - "unmodified": "6", - "withShift": "6", - "withOption": "6", - "withOptionShift": "6" - }, - "Numpad7": { - "unmodified": "7", - "withShift": "7", - "withOption": "7", - "withOptionShift": "7" - }, - "Numpad8": { - "unmodified": "8", - "withShift": "8", - "withOption": "8", - "withOptionShift": "8" - }, - "Numpad9": { - "unmodified": "9", - "withShift": "9", - "withOption": "9", - "withOptionShift": "9" - }, - "Numpad0": { - "unmodified": "0", - "withShift": "0", - "withOption": "0", - "withOptionShift": "0" - }, - "NumpadDecimal": { - "unmodified": ".", - "withShift": ".", - "withOption": ".", - "withOptionShift": "." - }, - "IntlBackslash": { - "unmodified": "§", - "withShift": "±", - "withOption": "§", - "withOptionShift": "±" - }, - "ContextMenu": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "NumpadEqual": { - "unmodified": "=", - "withShift": "=", - "withOption": "=", - "withOptionShift": "=" - }, - "F13": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "F14": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "F15": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "F16": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "F17": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "F18": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "F19": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "F20": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "AudioVolumeMute": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "AudioVolumeUp": { - "unmodified": "\u001f", - "withShift": "=", - "withOption": "\u001f", - "withOptionShift": "=" - }, - "AudioVolumeDown": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "NumpadComma": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "IntlRo": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "KanaMode": { - "unmodified": "\u0010", - "withShift": "\u0010", - "withOption": "\u0010", - "withOptionShift": "\u0010" - }, - "IntlYen": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "ControlLeft": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "ShiftLeft": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "AltLeft": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "MetaLeft": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "ControlRight": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "ShiftRight": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "AltRight": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - }, - "MetaRight": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "" - } -} diff --git a/spec/helpers/keymaps/mac-dvorak-qwerty-cmd.json b/spec/helpers/keymaps/mac-dvorak-qwerty-cmd.json new file mode 100644 index 0000000..c9c6893 --- /dev/null +++ b/spec/helpers/keymaps/mac-dvorak-qwerty-cmd.json @@ -0,0 +1,398 @@ +{ + "KeyA": { + "unmodified": "a", + "withShift": "A", + "withAltGraph": "å", + "withAltGraphShift": "Å" + }, + "KeyB": { + "unmodified": "x", + "withShift": "X", + "withAltGraph": "≈", + "withAltGraphShift": "˛" + }, + "KeyC": { + "unmodified": "j", + "withShift": "J", + "withAltGraph": "∆", + "withAltGraphShift": "Ô" + }, + "KeyD": { + "unmodified": "e", + "withShift": "E", + "withAltGraph": null, + "withAltGraphShift": "´" + }, + "KeyE": { + "unmodified": ".", + "withShift": ">", + "withAltGraph": "≥", + "withAltGraphShift": "˘" + }, + "KeyF": { + "unmodified": "u", + "withShift": "U", + "withAltGraph": null, + "withAltGraphShift": "¨" + }, + "KeyG": { + "unmodified": "i", + "withShift": "I", + "withAltGraph": null, + "withAltGraphShift": "ˆ" + }, + "KeyH": { + "unmodified": "d", + "withShift": "D", + "withAltGraph": "∂", + "withAltGraphShift": "Î" + }, + "KeyI": { + "unmodified": "c", + "withShift": "C", + "withAltGraph": "ç", + "withAltGraphShift": "Ç" + }, + "KeyJ": { + "unmodified": "h", + "withShift": "H", + "withAltGraph": "˙", + "withAltGraphShift": "Ó" + }, + "KeyK": { + "unmodified": "t", + "withShift": "T", + "withAltGraph": "†", + "withAltGraphShift": "ˇ" + }, + "KeyL": { + "unmodified": "n", + "withShift": "N", + "withAltGraph": null, + "withAltGraphShift": "˜" + }, + "KeyM": { + "unmodified": "m", + "withShift": "M", + "withAltGraph": "µ", + "withAltGraphShift": "Â" + }, + "KeyN": { + "unmodified": "b", + "withShift": "B", + "withAltGraph": "∫", + "withAltGraphShift": "ı" + }, + "KeyO": { + "unmodified": "r", + "withShift": "R", + "withAltGraph": "®", + "withAltGraphShift": "‰" + }, + "KeyP": { + "unmodified": "l", + "withShift": "L", + "withAltGraph": "¬", + "withAltGraphShift": "Ò" + }, + "KeyQ": { + "unmodified": "'", + "withShift": "\"", + "withAltGraph": "æ", + "withAltGraphShift": "Æ" + }, + "KeyR": { + "unmodified": "p", + "withShift": "P", + "withAltGraph": "π", + "withAltGraphShift": "∏" + }, + "KeyS": { + "unmodified": "o", + "withShift": "O", + "withAltGraph": "ø", + "withAltGraphShift": "Ø" + }, + "KeyT": { + "unmodified": "y", + "withShift": "Y", + "withAltGraph": "¥", + "withAltGraphShift": "Á" + }, + "KeyU": { + "unmodified": "g", + "withShift": "G", + "withAltGraph": "©", + "withAltGraphShift": "˝" + }, + "KeyV": { + "unmodified": "k", + "withShift": "K", + "withAltGraph": "˚", + "withAltGraphShift": "" + }, + "KeyW": { + "unmodified": ",", + "withShift": "<", + "withAltGraph": "≤", + "withAltGraphShift": "¯" + }, + "KeyX": { + "unmodified": "q", + "withShift": "Q", + "withAltGraph": "œ", + "withAltGraphShift": "Œ" + }, + "KeyY": { + "unmodified": "f", + "withShift": "F", + "withAltGraph": "ƒ", + "withAltGraphShift": "Ï" + }, + "KeyZ": { + "unmodified": ";", + "withShift": ":", + "withAltGraph": "…", + "withAltGraphShift": "Ú" + }, + "Digit1": { + "unmodified": "1", + "withShift": "!", + "withAltGraph": "¡", + "withAltGraphShift": "⁄" + }, + "Digit2": { + "unmodified": "2", + "withShift": "@", + "withAltGraph": "™", + "withAltGraphShift": "€" + }, + "Digit3": { + "unmodified": "3", + "withShift": "#", + "withAltGraph": "£", + "withAltGraphShift": "‹" + }, + "Digit4": { + "unmodified": "4", + "withShift": "$", + "withAltGraph": "¢", + "withAltGraphShift": "›" + }, + "Digit5": { + "unmodified": "5", + "withShift": "%", + "withAltGraph": "∞", + "withAltGraphShift": "fi" + }, + "Digit6": { + "unmodified": "6", + "withShift": "^", + "withAltGraph": "§", + "withAltGraphShift": "fl" + }, + "Digit7": { + "unmodified": "7", + "withShift": "&", + "withAltGraph": "¶", + "withAltGraphShift": "‡" + }, + "Digit8": { + "unmodified": "8", + "withShift": "*", + "withAltGraph": "•", + "withAltGraphShift": "°" + }, + "Digit9": { + "unmodified": "9", + "withShift": "(", + "withAltGraph": "ª", + "withAltGraphShift": "·" + }, + "Digit0": { + "unmodified": "0", + "withShift": ")", + "withAltGraph": "º", + "withAltGraphShift": "‚" + }, + "Space": { + "unmodified": " ", + "withShift": " ", + "withAltGraph": " ", + "withAltGraphShift": " " + }, + "Minus": { + "unmodified": "[", + "withShift": "{", + "withAltGraph": "“", + "withAltGraphShift": "”" + }, + "Equal": { + "unmodified": "]", + "withShift": "}", + "withAltGraph": "‘", + "withAltGraphShift": "’" + }, + "BracketLeft": { + "unmodified": "/", + "withShift": "?", + "withAltGraph": "÷", + "withAltGraphShift": "¿" + }, + "BracketRight": { + "unmodified": "=", + "withShift": "+", + "withAltGraph": "≠", + "withAltGraphShift": "±" + }, + "Backslash": { + "unmodified": "\\", + "withShift": "|", + "withAltGraph": "«", + "withAltGraphShift": "»" + }, + "Semicolon": { + "unmodified": "s", + "withShift": "S", + "withAltGraph": "ß", + "withAltGraphShift": "Í" + }, + "Quote": { + "unmodified": "-", + "withShift": "_", + "withAltGraph": "–", + "withAltGraphShift": "—" + }, + "Backquote": { + "unmodified": "`", + "withShift": "~", + "withAltGraph": null, + "withAltGraphShift": "`" + }, + "Comma": { + "unmodified": "w", + "withShift": "W", + "withAltGraph": "∑", + "withAltGraphShift": "„" + }, + "Period": { + "unmodified": "v", + "withShift": "V", + "withAltGraph": "√", + "withAltGraphShift": "◊" + }, + "Slash": { + "unmodified": "z", + "withShift": "Z", + "withAltGraph": "Ω", + "withAltGraphShift": "¸" + }, + "NumpadDivide": { + "unmodified": "/", + "withShift": "/", + "withAltGraph": "/", + "withAltGraphShift": "/" + }, + "NumpadMultiply": { + "unmodified": "*", + "withShift": "*", + "withAltGraph": "*", + "withAltGraphShift": "*" + }, + "NumpadSubtract": { + "unmodified": "-", + "withShift": "-", + "withAltGraph": "-", + "withAltGraphShift": "-" + }, + "NumpadAdd": { + "unmodified": "+", + "withShift": "+", + "withAltGraph": "+", + "withAltGraphShift": "+" + }, + "Numpad1": { + "unmodified": "1", + "withShift": "1", + "withAltGraph": "1", + "withAltGraphShift": "1" + }, + "Numpad2": { + "unmodified": "2", + "withShift": "2", + "withAltGraph": "2", + "withAltGraphShift": "2" + }, + "Numpad3": { + "unmodified": "3", + "withShift": "3", + "withAltGraph": "3", + "withAltGraphShift": "3" + }, + "Numpad4": { + "unmodified": "4", + "withShift": "4", + "withAltGraph": "4", + "withAltGraphShift": "4" + }, + "Numpad5": { + "unmodified": "5", + "withShift": "5", + "withAltGraph": "5", + "withAltGraphShift": "5" + }, + "Numpad6": { + "unmodified": "6", + "withShift": "6", + "withAltGraph": "6", + "withAltGraphShift": "6" + }, + "Numpad7": { + "unmodified": "7", + "withShift": "7", + "withAltGraph": "7", + "withAltGraphShift": "7" + }, + "Numpad8": { + "unmodified": "8", + "withShift": "8", + "withAltGraph": "8", + "withAltGraphShift": "8" + }, + "Numpad9": { + "unmodified": "9", + "withShift": "9", + "withAltGraph": "9", + "withAltGraphShift": "9" + }, + "Numpad0": { + "unmodified": "0", + "withShift": "0", + "withAltGraph": "0", + "withAltGraphShift": "0" + }, + "NumpadDecimal": { + "unmodified": ".", + "withShift": ".", + "withAltGraph": ".", + "withAltGraphShift": "." + }, + "IntlBackslash": { + "unmodified": "§", + "withShift": "±", + "withAltGraph": "§", + "withAltGraphShift": "±" + }, + "NumpadEqual": { + "unmodified": "=", + "withShift": "=", + "withAltGraph": "=", + "withAltGraphShift": "=" + }, + "AudioVolumeUp": { + "unmodified": null, + "withShift": "=", + "withAltGraph": null, + "withAltGraphShift": "=" + } +} diff --git a/spec/helpers/keymaps/greek.json b/spec/helpers/keymaps/mac-greek.json similarity index 50% rename from spec/helpers/keymaps/greek.json rename to spec/helpers/keymaps/mac-greek.json index 80b9fcd..591fc47 100644 --- a/spec/helpers/keymaps/greek.json +++ b/spec/helpers/keymaps/mac-greek.json @@ -1,380 +1,398 @@ { - "Space": { - "unmodified": " ", - "withShift": " ", - "withOption": " ", - "withOptionShift": " " - }, - "Digit0": { - "unmodified": "0", - "withShift": ")", - "withOption": "°", - "withOptionShift": "ύ" - }, - "Digit1": { - "unmodified": "1", - "withShift": "!", - "withOption": "¹", - "withOptionShift": "έ" - }, - "Digit2": { - "unmodified": "2", - "withShift": "@", - "withOption": "²", - "withOptionShift": "ί" - }, - "Digit3": { - "unmodified": "3", - "withShift": "#", - "withOption": "³", - "withOptionShift": "ή" - }, - "Digit4": { - "unmodified": "4", - "withShift": "$", - "withOption": "£", - "withOptionShift": "ό" - }, - "Digit5": { - "unmodified": "5", - "withShift": "%", - "withOption": "§", - "withOptionShift": "Ώ" - }, - "Digit6": { - "unmodified": "6", - "withShift": "^", - "withOption": "¶", - "withOptionShift": "^" - }, - "Digit7": { - "unmodified": "7", - "withShift": "&", - "withOption": "°", - "withOptionShift": "" - }, - "Digit8": { - "unmodified": "8", - "withShift": "*", - "withOption": "•", - "withOptionShift": "Ρ" - }, - "Digit9": { - "unmodified": "9", - "withShift": "(", - "withOption": "“", - "withOptionShift": "Κ" - }, "KeyA": { "unmodified": "α", "withShift": "Α", - "withOption": "…", - "withOptionShift": "ά" + "withAltGraph": "…", + "withAltGraphShift": "ά" }, "KeyB": { "unmodified": "β", "withShift": "Β", - "withOption": "", - "withOptionShift": "" + "withAltGraph": null, + "withAltGraphShift": null }, "KeyC": { "unmodified": "ψ", "withShift": "Ψ", - "withOption": "ç", - "withOptionShift": "Χ" + "withAltGraph": "ç", + "withAltGraphShift": "Χ" }, "KeyD": { "unmodified": "δ", "withShift": "Δ", - "withOption": "÷", - "withOptionShift": "" + "withAltGraph": "÷", + "withAltGraphShift": null }, "KeyE": { "unmodified": "ε", "withShift": "Ε", - "withOption": "€", - "withOptionShift": "Έ" + "withAltGraph": "€", + "withAltGraphShift": "Έ" }, "KeyF": { "unmodified": "φ", "withShift": "Φ", - "withOption": "≠", - "withOptionShift": "Π" + "withAltGraph": "≠", + "withAltGraphShift": "Π" }, "KeyG": { "unmodified": "γ", "withShift": "Γ", - "withOption": "©", - "withOptionShift": "Ϊ" + "withAltGraph": "©", + "withAltGraphShift": "Ϊ" }, "KeyH": { "unmodified": "η", "withShift": "Η", - "withOption": "½", - "withOptionShift": "≠" + "withAltGraph": "½", + "withAltGraphShift": "≠" }, "KeyI": { "unmodified": "ι", "withShift": "Ι", - "withOption": "†", - "withOptionShift": "Ν" + "withAltGraph": "†", + "withAltGraphShift": "Ν" }, "KeyJ": { "unmodified": "ξ", "withShift": "Ξ", - "withOption": "≤", - "withOptionShift": "§" + "withAltGraph": "≤", + "withAltGraphShift": "§" }, "KeyK": { "unmodified": "κ", "withShift": "Κ", - "withOption": "≥", - "withOptionShift": "°" + "withAltGraph": "≥", + "withAltGraphShift": "°" }, "KeyL": { "unmodified": "λ", "withShift": "Λ", - "withOption": "¬", - "withOptionShift": "·" + "withAltGraph": "¬", + "withAltGraphShift": "·" }, "KeyM": { "unmodified": "μ", "withShift": "Μ", - "withOption": "’", - "withOptionShift": "Ύ" + "withAltGraph": "’", + "withAltGraphShift": "Ύ" }, "KeyN": { "unmodified": "ν", "withShift": "Ν", - "withOption": "‘", - "withOptionShift": "Ό" + "withAltGraph": "‘", + "withAltGraphShift": "Ό" }, "KeyO": { "unmodified": "ο", "withShift": "Ο", - "withOption": "œ", - "withOptionShift": "Τ" + "withAltGraph": "œ", + "withAltGraphShift": "Τ" }, "KeyP": { "unmodified": "π", "withShift": "Π", - "withOption": "≈", - "withOptionShift": "" + "withAltGraph": "≈", + "withAltGraphShift": null }, "KeyQ": { "unmodified": ";", "withShift": ":", - "withOption": "·", - "withOptionShift": "―" + "withAltGraph": "·", + "withAltGraphShift": "―" }, "KeyR": { "unmodified": "ρ", "withShift": "Ρ", - "withOption": "®", - "withOptionShift": "Δ" + "withAltGraph": "®", + "withAltGraphShift": "Δ" }, "KeyS": { "unmodified": "σ", "withShift": "Σ", - "withOption": "ß", - "withOptionShift": "ρ" + "withAltGraph": "ß", + "withAltGraphShift": "ρ" }, "KeyT": { "unmodified": "τ", "withShift": "Τ", - "withOption": "™", - "withOptionShift": "" + "withAltGraph": "™", + "withAltGraphShift": null }, "KeyU": { "unmodified": "θ", "withShift": "Θ", - "withOption": "­", - "withOptionShift": "Ξ" + "withAltGraph": "­", + "withAltGraphShift": "Ξ" }, "KeyV": { "unmodified": "ω", "withShift": "Ω", - "withOption": "±", - "withOptionShift": "Ά" + "withAltGraph": "±", + "withAltGraphShift": "Ά" }, "KeyW": { "unmodified": "ς", - "withShift": "", - "withOption": "―", - "withOptionShift": "Β" + "withShift": null, + "withAltGraph": "―", + "withAltGraphShift": "Β" }, "KeyX": { "unmodified": "χ", "withShift": "Χ", - "withOption": "", - "withOptionShift": "" + "withAltGraph": null, + "withAltGraphShift": null }, "KeyY": { "unmodified": "υ", "withShift": "Υ", - "withOption": "¥", - "withOptionShift": "" + "withAltGraph": "¥", + "withAltGraphShift": null }, "KeyZ": { "unmodified": "ζ", "withShift": "Ζ", - "withOption": "§", - "withOptionShift": "" + "withAltGraph": "§", + "withAltGraphShift": null }, - "Numpad0": { + "Digit1": { + "unmodified": "1", + "withShift": "!", + "withAltGraph": "¹", + "withAltGraphShift": "έ" + }, + "Digit2": { + "unmodified": "2", + "withShift": "@", + "withAltGraph": "²", + "withAltGraphShift": "ί" + }, + "Digit3": { + "unmodified": "3", + "withShift": "#", + "withAltGraph": "³", + "withAltGraphShift": "ή" + }, + "Digit4": { + "unmodified": "4", + "withShift": "$", + "withAltGraph": "£", + "withAltGraphShift": "ό" + }, + "Digit5": { + "unmodified": "5", + "withShift": "%", + "withAltGraph": "§", + "withAltGraphShift": "Ώ" + }, + "Digit6": { + "unmodified": "6", + "withShift": "^", + "withAltGraph": "¶", + "withAltGraphShift": "^" + }, + "Digit7": { + "unmodified": "7", + "withShift": "&", + "withAltGraph": "°", + "withAltGraphShift": null + }, + "Digit8": { + "unmodified": "8", + "withShift": "*", + "withAltGraph": "•", + "withAltGraphShift": "Ρ" + }, + "Digit9": { + "unmodified": "9", + "withShift": "(", + "withAltGraph": "“", + "withAltGraphShift": "Κ" + }, + "Digit0": { "unmodified": "0", - "withShift": "0", - "withOption": "0", - "withOptionShift": "0" + "withShift": ")", + "withAltGraph": "°", + "withAltGraphShift": "ύ" + }, + "Space": { + "unmodified": " ", + "withShift": " ", + "withAltGraph": " ", + "withAltGraphShift": " " + }, + "Minus": { + "unmodified": "-", + "withShift": "_", + "withAltGraph": "±", + "withAltGraphShift": "_" + }, + "Equal": { + "unmodified": "=", + "withShift": "+", + "withAltGraph": "½", + "withAltGraphShift": "+" + }, + "BracketLeft": { + "unmodified": "[", + "withShift": "{", + "withAltGraph": "«", + "withAltGraphShift": "{" + }, + "BracketRight": { + "unmodified": "]", + "withShift": "}", + "withAltGraph": "»", + "withAltGraphShift": "}" + }, + "Backslash": { + "unmodified": "\\", + "withShift": "|", + "withAltGraph": "¦", + "withAltGraphShift": "Ζ" + }, + "Semicolon": { + "unmodified": null, + "withShift": null, + "withAltGraph": null, + "withAltGraphShift": ":" + }, + "Quote": { + "unmodified": "'", + "withShift": "\"", + "withAltGraph": "'", + "withAltGraphShift": "\"" + }, + "Backquote": { + "unmodified": "`", + "withShift": "~", + "withAltGraph": "`", + "withAltGraphShift": "Μ" + }, + "Comma": { + "unmodified": ",", + "withShift": "<", + "withAltGraph": "«", + "withAltGraphShift": null + }, + "Period": { + "unmodified": ".", + "withShift": ">", + "withAltGraph": "»", + "withAltGraphShift": "ώ" + }, + "Slash": { + "unmodified": "/", + "withShift": "?", + "withAltGraph": "/", + "withAltGraphShift": "?" + }, + "NumpadDivide": { + "unmodified": "/", + "withShift": "/", + "withAltGraph": "/", + "withAltGraphShift": "/" + }, + "NumpadMultiply": { + "unmodified": "*", + "withShift": "*", + "withAltGraph": "*", + "withAltGraphShift": "*" + }, + "NumpadSubtract": { + "unmodified": "-", + "withShift": "-", + "withAltGraph": "-", + "withAltGraphShift": "-" + }, + "NumpadAdd": { + "unmodified": "+", + "withShift": "+", + "withAltGraph": "+", + "withAltGraphShift": "+" }, "Numpad1": { "unmodified": "1", "withShift": "1", - "withOption": "1", - "withOptionShift": "1" + "withAltGraph": "1", + "withAltGraphShift": "1" }, "Numpad2": { "unmodified": "2", "withShift": "2", - "withOption": "2", - "withOptionShift": "2" + "withAltGraph": "2", + "withAltGraphShift": "2" }, "Numpad3": { "unmodified": "3", "withShift": "3", - "withOption": "3", - "withOptionShift": "3" + "withAltGraph": "3", + "withAltGraphShift": "3" }, "Numpad4": { "unmodified": "4", "withShift": "4", - "withOption": "4", - "withOptionShift": "4" + "withAltGraph": "4", + "withAltGraphShift": "4" }, "Numpad5": { "unmodified": "5", "withShift": "5", - "withOption": "5", - "withOptionShift": "5" + "withAltGraph": "5", + "withAltGraphShift": "5" }, "Numpad6": { "unmodified": "6", "withShift": "6", - "withOption": "6", - "withOptionShift": "6" + "withAltGraph": "6", + "withAltGraphShift": "6" }, "Numpad7": { "unmodified": "7", "withShift": "7", - "withOption": "7", - "withOptionShift": "7" + "withAltGraph": "7", + "withAltGraphShift": "7" }, "Numpad8": { "unmodified": "8", "withShift": "8", - "withOption": "8", - "withOptionShift": "8" + "withAltGraph": "8", + "withAltGraphShift": "8" }, "Numpad9": { "unmodified": "9", "withShift": "9", - "withOption": "9", - "withOptionShift": "9" + "withAltGraph": "9", + "withAltGraphShift": "9" }, - "NumpadMultiply": { - "unmodified": "*", - "withShift": "*", - "withOption": "*", - "withOptionShift": "*" - }, - "NumpadAdd": { - "unmodified": "+", - "withShift": "+", - "withOption": "+", - "withOptionShift": "+" - }, - "NumpadSubtract": { - "unmodified": "-", - "withShift": "-", - "withOption": "-", - "withOptionShift": "-" + "Numpad0": { + "unmodified": "0", + "withShift": "0", + "withAltGraph": "0", + "withAltGraphShift": "0" }, "NumpadDecimal": { "unmodified": ".", "withShift": ".", - "withOption": ".", - "withOptionShift": "." - }, - "NumpadDivide": { - "unmodified": "/", - "withShift": "/", - "withOption": "/", - "withOptionShift": "/" + "withAltGraph": ".", + "withAltGraphShift": "." }, - "Semicolon": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": ":" + "IntlBackslash": { + "unmodified": "§", + "withShift": "±", + "withAltGraph": null, + "withAltGraphShift": null }, - "Equal": { + "NumpadEqual": { "unmodified": "=", - "withShift": "+", - "withOption": "½", - "withOptionShift": "+" - }, - "NumpadComma": { - "unmodified": ",", - "withShift": "<", - "withOption": "«", - "withOptionShift": "" - }, - "Minus": { - "unmodified": "-", - "withShift": "_", - "withOption": "±", - "withOptionShift": "_" - }, - "Period": { - "unmodified": ".", - "withShift": ">", - "withOption": "»", - "withOptionShift": "ώ" - }, - "Slash": { - "unmodified": "/", - "withShift": "?", - "withOption": "/", - "withOptionShift": "?" - }, - "Backquote": { - "unmodified": "`", - "withShift": "~", - "withOption": "`", - "withOptionShift": "Μ" - }, - "BracketLeft": { - "unmodified": "[", - "withShift": "{", - "withOption": "«", - "withOptionShift": "{" - }, - "IntlYen": { - "unmodified": "\\", - "withShift": "|", - "withOption": "¦", - "withOptionShift": "Ζ" - }, - "BracketRight": { - "unmodified": "]", - "withShift": "}", - "withOption": "»", - "withOptionShift": "}" - }, - "Quote": { - "unmodified": "'", - "withShift": "\"", - "withOption": "'", - "withOptionShift": "\"" + "withShift": "=", + "withAltGraph": "=", + "withAltGraphShift": "=" + }, + "AudioVolumeUp": { + "unmodified": null, + "withShift": "=", + "withAltGraph": null, + "withAltGraphShift": "=" } } diff --git a/spec/helpers/keymaps/mac-swiss-german.json b/spec/helpers/keymaps/mac-swiss-german.json new file mode 100644 index 0000000..f137aa0 --- /dev/null +++ b/spec/helpers/keymaps/mac-swiss-german.json @@ -0,0 +1,398 @@ +{ + "KeyA": { + "unmodified": "a", + "withShift": "A", + "withAltGraph": "å", + "withAltGraphShift": "Å" + }, + "KeyB": { + "unmodified": "b", + "withShift": "B", + "withAltGraph": "∫", + "withAltGraphShift": null + }, + "KeyC": { + "unmodified": "c", + "withShift": "C", + "withAltGraph": "©", + "withAltGraphShift": null + }, + "KeyD": { + "unmodified": "d", + "withShift": "D", + "withAltGraph": "∂", + "withAltGraphShift": "fl" + }, + "KeyE": { + "unmodified": "e", + "withShift": "E", + "withAltGraph": "€", + "withAltGraphShift": "Ë" + }, + "KeyF": { + "unmodified": "f", + "withShift": "F", + "withAltGraph": "ƒ", + "withAltGraphShift": "‡" + }, + "KeyG": { + "unmodified": "g", + "withShift": "G", + "withAltGraph": "@", + "withAltGraphShift": "‚" + }, + "KeyH": { + "unmodified": "h", + "withShift": "H", + "withAltGraph": "ª", + "withAltGraphShift": "·" + }, + "KeyI": { + "unmodified": "i", + "withShift": "I", + "withAltGraph": "¡", + "withAltGraphShift": "ı" + }, + "KeyJ": { + "unmodified": "j", + "withShift": "J", + "withAltGraph": "º", + "withAltGraphShift": "˜" + }, + "KeyK": { + "unmodified": "k", + "withShift": "K", + "withAltGraph": "∆", + "withAltGraphShift": "¯" + }, + "KeyL": { + "unmodified": "l", + "withShift": "L", + "withAltGraph": "¬", + "withAltGraphShift": "ˆ" + }, + "KeyM": { + "unmodified": "m", + "withShift": "M", + "withAltGraph": "µ", + "withAltGraphShift": "˚" + }, + "KeyN": { + "unmodified": "n", + "withShift": "N", + "withAltGraph": null, + "withAltGraphShift": "˙" + }, + "KeyO": { + "unmodified": "o", + "withShift": "O", + "withAltGraph": "ø", + "withAltGraphShift": "Ø" + }, + "KeyP": { + "unmodified": "p", + "withShift": "P", + "withAltGraph": "π", + "withAltGraphShift": "∏" + }, + "KeyQ": { + "unmodified": "q", + "withShift": "Q", + "withAltGraph": "œ", + "withAltGraphShift": "Œ" + }, + "KeyR": { + "unmodified": "r", + "withShift": "R", + "withAltGraph": "®", + "withAltGraphShift": "È" + }, + "KeyS": { + "unmodified": "s", + "withShift": "S", + "withAltGraph": "ß", + "withAltGraphShift": "fi" + }, + "KeyT": { + "unmodified": "t", + "withShift": "T", + "withAltGraph": "†", + "withAltGraphShift": "Î" + }, + "KeyU": { + "unmodified": "u", + "withShift": "U", + "withAltGraph": "°", + "withAltGraphShift": "Ù" + }, + "KeyV": { + "unmodified": "v", + "withShift": "V", + "withAltGraph": "√", + "withAltGraphShift": "◊" + }, + "KeyW": { + "unmodified": "w", + "withShift": "W", + "withAltGraph": "∑", + "withAltGraphShift": "Á" + }, + "KeyX": { + "unmodified": "x", + "withShift": "X", + "withAltGraph": "≈", + "withAltGraphShift": "™" + }, + "KeyY": { + "unmodified": "z", + "withShift": "Z", + "withAltGraph": "Ω", + "withAltGraphShift": "Í" + }, + "KeyZ": { + "unmodified": "y", + "withShift": "Y", + "withAltGraph": "¥", + "withAltGraphShift": "Ÿ" + }, + "Digit1": { + "unmodified": "1", + "withShift": "+", + "withAltGraph": "±", + "withAltGraphShift": "∞" + }, + "Digit2": { + "unmodified": "2", + "withShift": "\"", + "withAltGraph": "“", + "withAltGraphShift": "”" + }, + "Digit3": { + "unmodified": "3", + "withShift": "*", + "withAltGraph": "#", + "withAltGraphShift": "‹" + }, + "Digit4": { + "unmodified": "4", + "withShift": "ç", + "withAltGraph": "Ç", + "withAltGraphShift": "⁄" + }, + "Digit5": { + "unmodified": "5", + "withShift": "%", + "withAltGraph": "[", + "withAltGraphShift": "[" + }, + "Digit6": { + "unmodified": "6", + "withShift": "&", + "withAltGraph": "]", + "withAltGraphShift": "]" + }, + "Digit7": { + "unmodified": "7", + "withShift": "/", + "withAltGraph": "|", + "withAltGraphShift": "\\" + }, + "Digit8": { + "unmodified": "8", + "withShift": "(", + "withAltGraph": "{", + "withAltGraphShift": "Ò" + }, + "Digit9": { + "unmodified": "9", + "withShift": ")", + "withAltGraph": "}", + "withAltGraphShift": "Ô" + }, + "Digit0": { + "unmodified": "0", + "withShift": "=", + "withAltGraph": "≠", + "withAltGraphShift": "Ú" + }, + "Space": { + "unmodified": " ", + "withShift": " ", + "withAltGraph": " ", + "withAltGraphShift": " " + }, + "Minus": { + "unmodified": "'", + "withShift": "?", + "withAltGraph": "¿", + "withAltGraphShift": "" + }, + "Equal": { + "unmodified": null, + "withShift": null, + "withAltGraph": null, + "withAltGraphShift": "^" + }, + "BracketLeft": { + "unmodified": "ü", + "withShift": "è", + "withAltGraph": "§", + "withAltGraphShift": "ÿ" + }, + "BracketRight": { + "unmodified": null, + "withShift": "!", + "withAltGraph": "‘", + "withAltGraphShift": "’" + }, + "Backslash": { + "unmodified": "$", + "withShift": "£", + "withAltGraph": "¶", + "withAltGraphShift": "•" + }, + "Semicolon": { + "unmodified": "ö", + "withShift": "é", + "withAltGraph": "¢", + "withAltGraphShift": "˘" + }, + "Quote": { + "unmodified": "ä", + "withShift": "à", + "withAltGraph": "æ", + "withAltGraphShift": "Æ" + }, + "Backquote": { + "unmodified": "<", + "withShift": ">", + "withAltGraph": "≤", + "withAltGraphShift": "≥" + }, + "Comma": { + "unmodified": ",", + "withShift": ";", + "withAltGraph": "«", + "withAltGraphShift": "»" + }, + "Period": { + "unmodified": ".", + "withShift": ":", + "withAltGraph": "…", + "withAltGraphShift": "÷" + }, + "Slash": { + "unmodified": "-", + "withShift": "_", + "withAltGraph": "–", + "withAltGraphShift": "—" + }, + "NumpadDivide": { + "unmodified": "/", + "withShift": "/", + "withAltGraph": "/", + "withAltGraphShift": "/" + }, + "NumpadMultiply": { + "unmodified": "*", + "withShift": "*", + "withAltGraph": "*", + "withAltGraphShift": "*" + }, + "NumpadSubtract": { + "unmodified": "-", + "withShift": "-", + "withAltGraph": "-", + "withAltGraphShift": "-" + }, + "NumpadAdd": { + "unmodified": "+", + "withShift": "+", + "withAltGraph": "+", + "withAltGraphShift": "+" + }, + "Numpad1": { + "unmodified": "1", + "withShift": "1", + "withAltGraph": "1", + "withAltGraphShift": "1" + }, + "Numpad2": { + "unmodified": "2", + "withShift": "2", + "withAltGraph": "2", + "withAltGraphShift": "2" + }, + "Numpad3": { + "unmodified": "3", + "withShift": "3", + "withAltGraph": "3", + "withAltGraphShift": "3" + }, + "Numpad4": { + "unmodified": "4", + "withShift": "4", + "withAltGraph": "4", + "withAltGraphShift": "4" + }, + "Numpad5": { + "unmodified": "5", + "withShift": "5", + "withAltGraph": "5", + "withAltGraphShift": "5" + }, + "Numpad6": { + "unmodified": "6", + "withShift": "6", + "withAltGraph": "6", + "withAltGraphShift": "6" + }, + "Numpad7": { + "unmodified": "7", + "withShift": "7", + "withAltGraph": "7", + "withAltGraphShift": "7" + }, + "Numpad8": { + "unmodified": "8", + "withShift": "8", + "withAltGraph": "8", + "withAltGraphShift": "8" + }, + "Numpad9": { + "unmodified": "9", + "withShift": "9", + "withAltGraph": "9", + "withAltGraphShift": "9" + }, + "Numpad0": { + "unmodified": "0", + "withShift": "0", + "withAltGraph": "0", + "withAltGraphShift": "0" + }, + "NumpadDecimal": { + "unmodified": ".", + "withShift": ",", + "withAltGraph": ".", + "withAltGraphShift": "." + }, + "IntlBackslash": { + "unmodified": "§", + "withShift": "°", + "withAltGraph": "fi", + "withAltGraphShift": "‰" + }, + "NumpadEqual": { + "unmodified": "=", + "withShift": "=", + "withAltGraph": "=", + "withAltGraphShift": "=" + }, + "AudioVolumeUp": { + "unmodified": null, + "withShift": "=", + "withAltGraph": null, + "withAltGraphShift": "=" + } +} diff --git a/spec/helpers/keymaps/turkish.json b/spec/helpers/keymaps/mac-turkish.json similarity index 50% rename from spec/helpers/keymaps/turkish.json rename to spec/helpers/keymaps/mac-turkish.json index ce5d806..1dff3c2 100644 --- a/spec/helpers/keymaps/turkish.json +++ b/spec/helpers/keymaps/mac-turkish.json @@ -1,380 +1,398 @@ { - "Space": { - "unmodified": " ", - "withShift": " ", - "withOption": " ", - "withOptionShift": " " - }, - "Digit0": { - "unmodified": "0", - "withShift": ":", - "withOption": "º", - "withOptionShift": "÷" - }, - "Digit1": { - "unmodified": "1", - "withShift": "!", - "withOption": "¡", - "withOptionShift": "·" - }, - "Digit2": { - "unmodified": "2", - "withShift": "*", - "withOption": "™", - "withOptionShift": "€" - }, - "Digit3": { - "unmodified": "3", - "withShift": "\"", - "withOption": "“", - "withOptionShift": "”" - }, - "Digit4": { - "unmodified": "4", - "withShift": "'", - "withOption": "‘", - "withOptionShift": "’" - }, - "Digit5": { - "unmodified": "5", - "withShift": "(", - "withOption": "[", - "withOptionShift": "{" - }, - "Digit6": { - "unmodified": "6", - "withShift": "/", - "withOption": "|", - "withOptionShift": "\\" - }, - "Digit7": { - "unmodified": "7", - "withShift": ")", - "withOption": "]", - "withOptionShift": "}" - }, - "Digit8": { - "unmodified": "8", - "withShift": "_", - "withOption": "•", - "withOptionShift": "°" - }, - "Digit9": { - "unmodified": "9", - "withShift": "%", - "withOption": "«", - "withOptionShift": "»" - }, "KeyA": { "unmodified": "u", "withShift": "U", - "withOption": "", - "withOptionShift": "Ë" + "withAltGraph": "", + "withAltGraphShift": "Ë" }, "KeyB": { "unmodified": "ç", "withShift": "Ç", - "withOption": "¯", - "withOptionShift": "˙" + "withAltGraph": "¯", + "withAltGraphShift": "˙" }, "KeyC": { "unmodified": "v", "withShift": "V", - "withOption": "√", - "withOptionShift": "◊" + "withAltGraph": "√", + "withAltGraphShift": "◊" }, "KeyD": { "unmodified": "e", "withShift": "E", - "withOption": "", - "withOptionShift": "‰" + "withAltGraph": null, + "withAltGraphShift": "‰" }, "KeyE": { "unmodified": "ğ", "withShift": "Ğ", - "withOption": "#", - "withOptionShift": "´" + "withAltGraph": "#", + "withAltGraphShift": "´" }, "KeyF": { "unmodified": "a", "withShift": "A", - "withOption": "å", - "withOptionShift": "Å" + "withAltGraph": "å", + "withAltGraphShift": "Å" }, "KeyG": { "unmodified": "ü", "withShift": "Ü", - "withOption": "@", - "withOptionShift": "ª" + "withAltGraph": "@", + "withAltGraphShift": "ª" }, "KeyH": { "unmodified": "t", "withShift": "T", - "withOption": "₺", - "withOptionShift": "Ê" + "withAltGraph": "₺", + "withAltGraphShift": "Ê" }, "KeyI": { "unmodified": "n", "withShift": "N", - "withOption": "", - "withOptionShift": "ˆ" + "withAltGraph": null, + "withAltGraphShift": "ˆ" }, "KeyJ": { "unmodified": "k", "withShift": "K", - "withOption": "", - "withOptionShift": "©" + "withAltGraph": null, + "withAltGraphShift": "©" }, "KeyK": { "unmodified": "m", "withShift": "M", - "withOption": "µ", - "withOptionShift": "˜" + "withAltGraph": "µ", + "withAltGraphShift": "˜" }, "KeyL": { "unmodified": "l", "withShift": "L", - "withOption": "¬", - "withOptionShift": "£" + "withAltGraph": "¬", + "withAltGraphShift": "£" }, "KeyM": { "unmodified": "s", "withShift": "S", - "withOption": "§", - "withOptionShift": "~" + "withAltGraph": "§", + "withAltGraphShift": "~" }, "KeyN": { "unmodified": "z", "withShift": "Z", - "withOption": "Ω", - "withOptionShift": "Û" + "withAltGraph": "Ω", + "withAltGraphShift": "Û" }, "KeyO": { "unmodified": "h", "withShift": "H", - "withOption": "", - "withOptionShift": "Ó" + "withAltGraph": null, + "withAltGraphShift": "Ó" }, "KeyP": { "unmodified": "p", "withShift": "P", - "withOption": "π", - "withOptionShift": "∏" + "withAltGraph": "π", + "withAltGraphShift": "∏" }, "KeyQ": { "unmodified": "f", "withShift": "F", - "withOption": "ƒ", - "withOptionShift": "Ï" + "withAltGraph": "ƒ", + "withAltGraphShift": "Ï" }, "KeyR": { "unmodified": "ı", "withShift": "I", - "withOption": "^", - "withOptionShift": "È" + "withAltGraph": "^", + "withAltGraphShift": "È" }, "KeyS": { "unmodified": "i", "withShift": "İ", - "withOption": "", - "withOptionShift": "∞" + "withAltGraph": null, + "withAltGraphShift": "∞" }, "KeyT": { "unmodified": "o", "withShift": "O", - "withOption": "ø", - "withOptionShift": "Ø" + "withAltGraph": "ø", + "withAltGraphShift": "Ø" }, "KeyU": { "unmodified": "r", "withShift": "R", - "withOption": "®", - "withOptionShift": "Â" + "withAltGraph": "®", + "withAltGraphShift": "Â" }, "KeyV": { "unmodified": "c", "withShift": "C", - "withOption": "ç", - "withOptionShift": "˚" + "withAltGraph": "ç", + "withAltGraphShift": "˚" }, "KeyW": { "unmodified": "g", "withShift": "G", - "withOption": "¶", - "withOptionShift": "`" + "withAltGraph": "¶", + "withAltGraphShift": "`" }, "KeyX": { "unmodified": "ö", "withShift": "Ö", - "withOption": "¨", - "withOptionShift": "Ÿ" + "withAltGraph": "¨", + "withAltGraphShift": "Ÿ" }, "KeyY": { "unmodified": "d", "withShift": "D", - "withOption": "∂", - "withOptionShift": "Î" + "withAltGraph": "∂", + "withAltGraphShift": "Î" }, "KeyZ": { "unmodified": "j", "withShift": "J", - "withOption": "∆", - "withOptionShift": "Ô" + "withAltGraph": "∆", + "withAltGraphShift": "Ô" }, - "Numpad0": { + "Digit1": { + "unmodified": "1", + "withShift": "!", + "withAltGraph": "¡", + "withAltGraphShift": "·" + }, + "Digit2": { + "unmodified": "2", + "withShift": "*", + "withAltGraph": "™", + "withAltGraphShift": "€" + }, + "Digit3": { + "unmodified": "3", + "withShift": "\"", + "withAltGraph": "“", + "withAltGraphShift": "”" + }, + "Digit4": { + "unmodified": "4", + "withShift": "'", + "withAltGraph": "‘", + "withAltGraphShift": "’" + }, + "Digit5": { + "unmodified": "5", + "withShift": "(", + "withAltGraph": "[", + "withAltGraphShift": "{" + }, + "Digit6": { + "unmodified": "6", + "withShift": "/", + "withAltGraph": "|", + "withAltGraphShift": "\\" + }, + "Digit7": { + "unmodified": "7", + "withShift": ")", + "withAltGraph": "]", + "withAltGraphShift": "}" + }, + "Digit8": { + "unmodified": "8", + "withShift": "_", + "withAltGraph": "•", + "withAltGraphShift": "°" + }, + "Digit9": { + "unmodified": "9", + "withShift": "%", + "withAltGraph": "«", + "withAltGraphShift": "»" + }, + "Digit0": { "unmodified": "0", - "withShift": "0", - "withOption": "0", - "withOptionShift": "0" + "withShift": ":", + "withAltGraph": "º", + "withAltGraphShift": "÷" + }, + "Space": { + "unmodified": " ", + "withShift": " ", + "withAltGraph": " ", + "withAltGraphShift": " " + }, + "Minus": { + "unmodified": "x", + "withShift": "X", + "withAltGraph": "≈", + "withAltGraphShift": "Ù" + }, + "Equal": { + "unmodified": "q", + "withShift": "Q", + "withAltGraph": "œ", + "withAltGraphShift": "Œ" + }, + "BracketLeft": { + "unmodified": ";", + "withShift": "$", + "withAltGraph": "…", + "withAltGraphShift": "¢" + }, + "BracketRight": { + "unmodified": ">", + "withShift": "<", + "withAltGraph": "≥", + "withAltGraphShift": "≤" + }, + "Backslash": { + "unmodified": "=", + "withShift": "+", + "withAltGraph": "≠", + "withAltGraphShift": "±" + }, + "Semicolon": { + "unmodified": "y", + "withShift": "Y", + "withAltGraph": "¥", + "withAltGraphShift": "Á" + }, + "Quote": { + "unmodified": "ş", + "withShift": "Ş", + "withAltGraph": "æ", + "withAltGraphShift": "Æ" + }, + "Backquote": { + "unmodified": "w", + "withShift": "W", + "withAltGraph": "∑", + "withAltGraphShift": "„" + }, + "Comma": { + "unmodified": "b", + "withShift": "B", + "withAltGraph": "∫", + "withAltGraphShift": "ß" + }, + "Period": { + "unmodified": ".", + "withShift": "?", + "withAltGraph": "&", + "withAltGraphShift": "¿" + }, + "Slash": { + "unmodified": ",", + "withShift": "-", + "withAltGraph": "–", + "withAltGraphShift": "—" + }, + "NumpadDivide": { + "unmodified": "/", + "withShift": "/", + "withAltGraph": "/", + "withAltGraphShift": "/" + }, + "NumpadMultiply": { + "unmodified": "*", + "withShift": "*", + "withAltGraph": "*", + "withAltGraphShift": "*" + }, + "NumpadSubtract": { + "unmodified": "-", + "withShift": "-", + "withAltGraph": "-", + "withAltGraphShift": "-" + }, + "NumpadAdd": { + "unmodified": "+", + "withShift": "+", + "withAltGraph": "+", + "withAltGraphShift": "+" }, "Numpad1": { "unmodified": "1", "withShift": "1", - "withOption": "1", - "withOptionShift": "1" + "withAltGraph": "1", + "withAltGraphShift": "1" }, "Numpad2": { "unmodified": "2", "withShift": "2", - "withOption": "2", - "withOptionShift": "2" + "withAltGraph": "2", + "withAltGraphShift": "2" }, "Numpad3": { "unmodified": "3", "withShift": "3", - "withOption": "3", - "withOptionShift": "3" + "withAltGraph": "3", + "withAltGraphShift": "3" }, "Numpad4": { "unmodified": "4", "withShift": "4", - "withOption": "4", - "withOptionShift": "4" + "withAltGraph": "4", + "withAltGraphShift": "4" }, "Numpad5": { "unmodified": "5", "withShift": "5", - "withOption": "5", - "withOptionShift": "5" + "withAltGraph": "5", + "withAltGraphShift": "5" }, "Numpad6": { "unmodified": "6", "withShift": "6", - "withOption": "6", - "withOptionShift": "6" + "withAltGraph": "6", + "withAltGraphShift": "6" }, "Numpad7": { "unmodified": "7", "withShift": "7", - "withOption": "7", - "withOptionShift": "7" + "withAltGraph": "7", + "withAltGraphShift": "7" }, "Numpad8": { "unmodified": "8", "withShift": "8", - "withOption": "8", - "withOptionShift": "8" + "withAltGraph": "8", + "withAltGraphShift": "8" }, "Numpad9": { "unmodified": "9", "withShift": "9", - "withOption": "9", - "withOptionShift": "9" - }, - "NumpadMultiply": { - "unmodified": "*", - "withShift": "*", - "withOption": "*", - "withOptionShift": "*" + "withAltGraph": "9", + "withAltGraphShift": "9" }, - "NumpadAdd": { - "unmodified": "+", - "withShift": "+", - "withOption": "+", - "withOptionShift": "+" - }, - "NumpadSubtract": { - "unmodified": "-", - "withShift": "-", - "withOption": "-", - "withOptionShift": "-" + "Numpad0": { + "unmodified": "0", + "withShift": "0", + "withAltGraph": "0", + "withAltGraphShift": "0" }, "NumpadDecimal": { "unmodified": ",", "withShift": ",", - "withOption": ",", - "withOptionShift": "," - }, - "NumpadDivide": { - "unmodified": "/", - "withShift": "/", - "withOption": "/", - "withOptionShift": "/" - }, - "Semicolon": { - "unmodified": "y", - "withShift": "Y", - "withOption": "¥", - "withOptionShift": "Á" - }, - "Equal": { - "unmodified": "q", - "withShift": "Q", - "withOption": "œ", - "withOptionShift": "Œ" - }, - "NumpadComma": { - "unmodified": "b", - "withShift": "B", - "withOption": "∫", - "withOptionShift": "ß" - }, - "Minus": { - "unmodified": "x", - "withShift": "X", - "withOption": "≈", - "withOptionShift": "Ù" + "withAltGraph": ",", + "withAltGraphShift": "," }, - "Period": { - "unmodified": ".", - "withShift": "?", - "withOption": "&", - "withOptionShift": "¿" + "IntlBackslash": { + "unmodified": "§", + "withShift": "±", + "withAltGraph": null, + "withAltGraphShift": null }, - "Slash": { - "unmodified": ",", - "withShift": "-", - "withOption": "–", - "withOptionShift": "—" - }, - "Backquote": { - "unmodified": "w", - "withShift": "W", - "withOption": "∑", - "withOptionShift": "„" - }, - "BracketLeft": { - "unmodified": ";", - "withShift": "$", - "withOption": "…", - "withOptionShift": "¢" - }, - "IntlYen": { + "NumpadEqual": { "unmodified": "=", - "withShift": "+", - "withOption": "≠", - "withOptionShift": "±" - }, - "BracketRight": { - "unmodified": ">", - "withShift": "<", - "withOption": "≥", - "withOptionShift": "≤" - }, - "Quote": { - "unmodified": "ş", - "withShift": "Ş", - "withOption": "æ", - "withOptionShift": "Æ" + "withShift": "=", + "withAltGraph": "=", + "withAltGraphShift": "=" + }, + "AudioVolumeUp": { + "unmodified": null, + "withShift": "=", + "withAltGraph": null, + "withAltGraphShift": "=" } } diff --git a/spec/helpers/keymaps/swiss-german.json b/spec/helpers/keymaps/swiss-german.json deleted file mode 100644 index e1a0b31..0000000 --- a/spec/helpers/keymaps/swiss-german.json +++ /dev/null @@ -1,380 +0,0 @@ -{ - "Space": { - "unmodified": " ", - "withShift": " ", - "withOption": " ", - "withOptionShift": " " - }, - "Digit0": { - "unmodified": "0", - "withShift": "=", - "withOption": "≠", - "withOptionShift": "Ú" - }, - "Digit1": { - "unmodified": "1", - "withShift": "+", - "withOption": "±", - "withOptionShift": "∞" - }, - "Digit2": { - "unmodified": "2", - "withShift": "\"", - "withOption": "“", - "withOptionShift": "”" - }, - "Digit3": { - "unmodified": "3", - "withShift": "*", - "withOption": "#", - "withOptionShift": "‹" - }, - "Digit4": { - "unmodified": "4", - "withShift": "ç", - "withOption": "Ç", - "withOptionShift": "⁄" - }, - "Digit5": { - "unmodified": "5", - "withShift": "%", - "withOption": "[", - "withOptionShift": "[" - }, - "Digit6": { - "unmodified": "6", - "withShift": "&", - "withOption": "]", - "withOptionShift": "]" - }, - "Digit7": { - "unmodified": "7", - "withShift": "/", - "withOption": "|", - "withOptionShift": "\\" - }, - "Digit8": { - "unmodified": "8", - "withShift": "(", - "withOption": "{", - "withOptionShift": "Ò" - }, - "Digit9": { - "unmodified": "9", - "withShift": ")", - "withOption": "}", - "withOptionShift": "Ô" - }, - "KeyA": { - "unmodified": "a", - "withShift": "A", - "withOption": "å", - "withOptionShift": "Å" - }, - "KeyB": { - "unmodified": "b", - "withShift": "B", - "withOption": "∫", - "withOptionShift": "" - }, - "KeyC": { - "unmodified": "c", - "withShift": "C", - "withOption": "©", - "withOptionShift": "" - }, - "KeyD": { - "unmodified": "d", - "withShift": "D", - "withOption": "∂", - "withOptionShift": "fl" - }, - "KeyE": { - "unmodified": "e", - "withShift": "E", - "withOption": "€", - "withOptionShift": "Ë" - }, - "KeyF": { - "unmodified": "f", - "withShift": "F", - "withOption": "ƒ", - "withOptionShift": "‡" - }, - "KeyG": { - "unmodified": "g", - "withShift": "G", - "withOption": "@", - "withOptionShift": "‚" - }, - "KeyH": { - "unmodified": "h", - "withShift": "H", - "withOption": "ª", - "withOptionShift": "·" - }, - "KeyI": { - "unmodified": "i", - "withShift": "I", - "withOption": "¡", - "withOptionShift": "ı" - }, - "KeyJ": { - "unmodified": "j", - "withShift": "J", - "withOption": "º", - "withOptionShift": "˜" - }, - "KeyK": { - "unmodified": "k", - "withShift": "K", - "withOption": "∆", - "withOptionShift": "¯" - }, - "KeyL": { - "unmodified": "l", - "withShift": "L", - "withOption": "¬", - "withOptionShift": "ˆ" - }, - "KeyM": { - "unmodified": "m", - "withShift": "M", - "withOption": "µ", - "withOptionShift": "˚" - }, - "KeyN": { - "unmodified": "n", - "withShift": "N", - "withOption": "", - "withOptionShift": "˙" - }, - "KeyO": { - "unmodified": "o", - "withShift": "O", - "withOption": "ø", - "withOptionShift": "Ø" - }, - "KeyP": { - "unmodified": "p", - "withShift": "P", - "withOption": "π", - "withOptionShift": "∏" - }, - "KeyQ": { - "unmodified": "q", - "withShift": "Q", - "withOption": "œ", - "withOptionShift": "Œ" - }, - "KeyR": { - "unmodified": "r", - "withShift": "R", - "withOption": "®", - "withOptionShift": "È" - }, - "KeyS": { - "unmodified": "s", - "withShift": "S", - "withOption": "ß", - "withOptionShift": "fi" - }, - "KeyT": { - "unmodified": "t", - "withShift": "T", - "withOption": "†", - "withOptionShift": "Î" - }, - "KeyU": { - "unmodified": "u", - "withShift": "U", - "withOption": "°", - "withOptionShift": "Ù" - }, - "KeyV": { - "unmodified": "v", - "withShift": "V", - "withOption": "√", - "withOptionShift": "◊" - }, - "KeyW": { - "unmodified": "w", - "withShift": "W", - "withOption": "∑", - "withOptionShift": "Á" - }, - "KeyX": { - "unmodified": "x", - "withShift": "X", - "withOption": "≈", - "withOptionShift": "™" - }, - "KeyY": { - "unmodified": "z", - "withShift": "Z", - "withOption": "Ω", - "withOptionShift": "Í" - }, - "KeyZ": { - "unmodified": "y", - "withShift": "Y", - "withOption": "¥", - "withOptionShift": "Ÿ" - }, - "Numpad0": { - "unmodified": "0", - "withShift": "0", - "withOption": "0", - "withOptionShift": "0" - }, - "Numpad1": { - "unmodified": "1", - "withShift": "1", - "withOption": "1", - "withOptionShift": "1" - }, - "Numpad2": { - "unmodified": "2", - "withShift": "2", - "withOption": "2", - "withOptionShift": "2" - }, - "Numpad3": { - "unmodified": "3", - "withShift": "3", - "withOption": "3", - "withOptionShift": "3" - }, - "Numpad4": { - "unmodified": "4", - "withShift": "4", - "withOption": "4", - "withOptionShift": "4" - }, - "Numpad5": { - "unmodified": "5", - "withShift": "5", - "withOption": "5", - "withOptionShift": "5" - }, - "Numpad6": { - "unmodified": "6", - "withShift": "6", - "withOption": "6", - "withOptionShift": "6" - }, - "Numpad7": { - "unmodified": "7", - "withShift": "7", - "withOption": "7", - "withOptionShift": "7" - }, - "Numpad8": { - "unmodified": "8", - "withShift": "8", - "withOption": "8", - "withOptionShift": "8" - }, - "Numpad9": { - "unmodified": "9", - "withShift": "9", - "withOption": "9", - "withOptionShift": "9" - }, - "NumpadMultiply": { - "unmodified": "*", - "withShift": "*", - "withOption": "*", - "withOptionShift": "*" - }, - "NumpadAdd": { - "unmodified": "+", - "withShift": "+", - "withOption": "+", - "withOptionShift": "+" - }, - "NumpadSubtract": { - "unmodified": "-", - "withShift": "-", - "withOption": "-", - "withOptionShift": "-" - }, - "NumpadDecimal": { - "unmodified": ".", - "withShift": ",", - "withOption": ".", - "withOptionShift": "." - }, - "NumpadDivide": { - "unmodified": "/", - "withShift": "/", - "withOption": "/", - "withOptionShift": "/" - }, - "Semicolon": { - "unmodified": "ö", - "withShift": "é", - "withOption": "¢", - "withOptionShift": "˘" - }, - "Equal": { - "unmodified": "", - "withShift": "", - "withOption": "", - "withOptionShift": "^" - }, - "NumpadComma": { - "unmodified": ",", - "withShift": ";", - "withOption": "«", - "withOptionShift": "»" - }, - "Minus": { - "unmodified": "'", - "withShift": "?", - "withOption": "¿", - "withOptionShift": "" - }, - "Period": { - "unmodified": ".", - "withShift": ":", - "withOption": "…", - "withOptionShift": "÷" - }, - "Slash": { - "unmodified": "-", - "withShift": "_", - "withOption": "–", - "withOptionShift": "—" - }, - "Backquote": { - "unmodified": "<", - "withShift": ">", - "withOption": "≤", - "withOptionShift": "≥" - }, - "BracketLeft": { - "unmodified": "ü", - "withShift": "è", - "withOption": "§", - "withOptionShift": "ÿ" - }, - "IntlYen": { - "unmodified": "$", - "withShift": "£", - "withOption": "¶", - "withOptionShift": "•" - }, - "BracketRight": { - "unmodified": "", - "withShift": "!", - "withOption": "‘", - "withOptionShift": "’" - }, - "Quote": { - "unmodified": "ä", - "withShift": "à", - "withOption": "æ", - "withOptionShift": "Æ" - } -} diff --git a/spec/helpers/keymaps/windows-swiss-german.json b/spec/helpers/keymaps/windows-swiss-german.json new file mode 100644 index 0000000..32194af --- /dev/null +++ b/spec/helpers/keymaps/windows-swiss-german.json @@ -0,0 +1,314 @@ +{ + "KeyA": { + "unmodified": "a", + "withShift": "A", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyB": { + "unmodified": "b", + "withShift": "B", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyC": { + "unmodified": "c", + "withShift": "C", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyD": { + "unmodified": "d", + "withShift": "D", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyE": { + "unmodified": "e", + "withShift": "E", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyF": { + "unmodified": "f", + "withShift": "F", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyG": { + "unmodified": "g", + "withShift": "G", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyH": { + "unmodified": "h", + "withShift": "H", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyI": { + "unmodified": "i", + "withShift": "I", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyJ": { + "unmodified": "j", + "withShift": "J", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyK": { + "unmodified": "k", + "withShift": "K", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyL": { + "unmodified": "l", + "withShift": "L", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyM": { + "unmodified": "m", + "withShift": "M", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyN": { + "unmodified": "n", + "withShift": "N", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyO": { + "unmodified": "o", + "withShift": "O", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyP": { + "unmodified": "p", + "withShift": "P", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyQ": { + "unmodified": "q", + "withShift": "Q", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyR": { + "unmodified": "r", + "withShift": "R", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyS": { + "unmodified": "s", + "withShift": "S", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyT": { + "unmodified": "t", + "withShift": "T", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyU": { + "unmodified": "u", + "withShift": "U", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyV": { + "unmodified": "v", + "withShift": "V", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyW": { + "unmodified": "w", + "withShift": "W", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyX": { + "unmodified": "x", + "withShift": "X", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyY": { + "unmodified": "z", + "withShift": "Z", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyZ": { + "unmodified": "y", + "withShift": "Y", + "withAltGraph": null, + "withAltGraphShift": null + }, + "Digit1": { + "unmodified": "1", + "withShift": "+", + "withAltGraph": "¦", + "withAltGraphShift": null + }, + "Digit2": { + "unmodified": "2", + "withShift": "\"", + "withAltGraph": "@", + "withAltGraphShift": null + }, + "Digit3": { + "unmodified": "3", + "withShift": "*", + "withAltGraph": "#", + "withAltGraphShift": null + }, + "Digit4": { + "unmodified": "4", + "withShift": "ç", + "withAltGraph": "°", + "withAltGraphShift": null + }, + "Digit5": { + "unmodified": "5", + "withShift": "%", + "withAltGraph": "§", + "withAltGraphShift": null + }, + "Digit6": { + "unmodified": "6", + "withShift": "&", + "withAltGraph": "¬", + "withAltGraphShift": null + }, + "Digit7": { + "unmodified": "7", + "withShift": "/", + "withAltGraph": "|", + "withAltGraphShift": null + }, + "Digit8": { + "unmodified": "8", + "withShift": "(", + "withAltGraph": "¢", + "withAltGraphShift": null + }, + "Digit9": { + "unmodified": "9", + "withShift": ")", + "withAltGraph": null, + "withAltGraphShift": null + }, + "Digit0": { + "unmodified": "0", + "withShift": "=", + "withAltGraph": null, + "withAltGraphShift": null + }, + "Space": { + "unmodified": " ", + "withShift": " ", + "withAltGraph": null, + "withAltGraphShift": null + }, + "Minus": { + "unmodified": "'", + "withShift": "?", + "withAltGraph": null, + "withAltGraphShift": null + }, + "Equal": { + "unmodified": "´^", + "withShift": null, + "withAltGraph": "`~", + "withAltGraphShift": null + }, + "BracketLeft": { + "unmodified": "ü", + "withShift": "è", + "withAltGraph": "[", + "withAltGraphShift": null + }, + "BracketRight": { + "unmodified": null, + "withShift": "¨!", + "withAltGraph": "]", + "withAltGraphShift": null + }, + "Backslash": { + "unmodified": "$", + "withShift": "£", + "withAltGraph": "}", + "withAltGraphShift": null + }, + "Semicolon": { + "unmodified": "ö", + "withShift": "é", + "withAltGraph": null, + "withAltGraphShift": null + }, + "Quote": { + "unmodified": "ä", + "withShift": "à", + "withAltGraph": "{", + "withAltGraphShift": null + }, + "Backquote": { + "unmodified": "§", + "withShift": "°", + "withAltGraph": null, + "withAltGraphShift": null + }, + "Comma": { + "unmodified": ",", + "withShift": ";", + "withAltGraph": null, + "withAltGraphShift": null + }, + "Period": { + "unmodified": ".", + "withShift": ":", + "withAltGraph": null, + "withAltGraphShift": null + }, + "Slash": { + "unmodified": "-", + "withShift": "_", + "withAltGraph": null, + "withAltGraphShift": null + }, + "NumpadMultiply": { + "unmodified": "*", + "withShift": "*", + "withAltGraph": null, + "withAltGraphShift": null + }, + "NumpadSubtract": { + "unmodified": "-", + "withShift": "-", + "withAltGraph": null, + "withAltGraphShift": null + }, + "NumpadAdd": { + "unmodified": "+", + "withShift": "+", + "withAltGraph": null, + "withAltGraphShift": null + }, + "IntlBackslash": { + "unmodified": "<", + "withShift": ">", + "withAltGraph": "\\", + "withAltGraphShift": null + } +} diff --git a/spec/helpers/keymaps/windows-us-international.json b/spec/helpers/keymaps/windows-us-international.json new file mode 100644 index 0000000..4d426c4 --- /dev/null +++ b/spec/helpers/keymaps/windows-us-international.json @@ -0,0 +1,314 @@ +{ + "KeyA": { + "unmodified": "a", + "withShift": "A", + "withAltGraph": "á", + "withAltGraphShift": "Á" + }, + "KeyB": { + "unmodified": "b", + "withShift": "B", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyC": { + "unmodified": "c", + "withShift": "C", + "withAltGraph": "©", + "withAltGraphShift": "¢" + }, + "KeyD": { + "unmodified": "d", + "withShift": "D", + "withAltGraph": "ð", + "withAltGraphShift": "Ð" + }, + "KeyE": { + "unmodified": "e", + "withShift": "E", + "withAltGraph": "é", + "withAltGraphShift": "É" + }, + "KeyF": { + "unmodified": "f", + "withShift": "F", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyG": { + "unmodified": "g", + "withShift": "G", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyH": { + "unmodified": "h", + "withShift": "H", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyI": { + "unmodified": "i", + "withShift": "I", + "withAltGraph": "í", + "withAltGraphShift": "Í" + }, + "KeyJ": { + "unmodified": "j", + "withShift": "J", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyK": { + "unmodified": "k", + "withShift": "K", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyL": { + "unmodified": "l", + "withShift": "L", + "withAltGraph": "ø", + "withAltGraphShift": "Ø" + }, + "KeyM": { + "unmodified": "m", + "withShift": "M", + "withAltGraph": "µ", + "withAltGraphShift": null + }, + "KeyN": { + "unmodified": "n", + "withShift": "N", + "withAltGraph": "ñ", + "withAltGraphShift": "Ñ" + }, + "KeyO": { + "unmodified": "o", + "withShift": "O", + "withAltGraph": "ó", + "withAltGraphShift": "Ó" + }, + "KeyP": { + "unmodified": "p", + "withShift": "P", + "withAltGraph": "ö", + "withAltGraphShift": "Ö" + }, + "KeyQ": { + "unmodified": "q", + "withShift": "Q", + "withAltGraph": "ä", + "withAltGraphShift": "Ä" + }, + "KeyR": { + "unmodified": "r", + "withShift": "R", + "withAltGraph": "®", + "withAltGraphShift": null + }, + "KeyS": { + "unmodified": "s", + "withShift": "S", + "withAltGraph": "ß", + "withAltGraphShift": "§" + }, + "KeyT": { + "unmodified": "t", + "withShift": "T", + "withAltGraph": "þ", + "withAltGraphShift": "Þ" + }, + "KeyU": { + "unmodified": "u", + "withShift": "U", + "withAltGraph": "ú", + "withAltGraphShift": "Ú" + }, + "KeyV": { + "unmodified": "v", + "withShift": "V", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyW": { + "unmodified": "w", + "withShift": "W", + "withAltGraph": "å", + "withAltGraphShift": "Å" + }, + "KeyX": { + "unmodified": "x", + "withShift": "X", + "withAltGraph": null, + "withAltGraphShift": null + }, + "KeyY": { + "unmodified": "y", + "withShift": "Y", + "withAltGraph": "ü", + "withAltGraphShift": "Ü" + }, + "KeyZ": { + "unmodified": "z", + "withShift": "Z", + "withAltGraph": "æ", + "withAltGraphShift": "Æ" + }, + "Digit1": { + "unmodified": "1", + "withShift": "!", + "withAltGraph": "¡", + "withAltGraphShift": "¹" + }, + "Digit2": { + "unmodified": "2", + "withShift": "@", + "withAltGraph": "²", + "withAltGraphShift": null + }, + "Digit3": { + "unmodified": "3", + "withShift": "#", + "withAltGraph": "³", + "withAltGraphShift": null + }, + "Digit4": { + "unmodified": "4", + "withShift": "$", + "withAltGraph": "¤", + "withAltGraphShift": "£" + }, + "Digit5": { + "unmodified": "5", + "withShift": "%", + "withAltGraph": null, + "withAltGraphShift": null + }, + "Digit6": { + "unmodified": "6", + "withShift": null, + "withAltGraph": "^¼", + "withAltGraphShift": null + }, + "Digit7": { + "unmodified": "7", + "withShift": "&", + "withAltGraph": "½", + "withAltGraphShift": null + }, + "Digit8": { + "unmodified": "8", + "withShift": "*", + "withAltGraph": "¾", + "withAltGraphShift": null + }, + "Digit9": { + "unmodified": "9", + "withShift": "(", + "withAltGraph": "‘", + "withAltGraphShift": null + }, + "Digit0": { + "unmodified": "0", + "withShift": ")", + "withAltGraph": null, + "withAltGraphShift": null + }, + "Space": { + "unmodified": " ", + "withShift": " ", + "withAltGraph": null, + "withAltGraphShift": null + }, + "Minus": { + "unmodified": "-", + "withShift": "_", + "withAltGraph": "¥", + "withAltGraphShift": null + }, + "Equal": { + "unmodified": "=", + "withShift": "+", + "withAltGraph": "×", + "withAltGraphShift": "÷" + }, + "BracketLeft": { + "unmodified": "[", + "withShift": "{", + "withAltGraph": "«", + "withAltGraphShift": null + }, + "BracketRight": { + "unmodified": "]", + "withShift": "}", + "withAltGraph": "»", + "withAltGraphShift": null + }, + "Backslash": { + "unmodified": "\\", + "withShift": "|", + "withAltGraph": "¬", + "withAltGraphShift": "¦" + }, + "Semicolon": { + "unmodified": ";", + "withShift": ":", + "withAltGraph": "¶", + "withAltGraphShift": "°" + }, + "Quote": { + "unmodified": null, + "withShift": "'\"", + "withAltGraph": "´", + "withAltGraphShift": "¨" + }, + "Backquote": { + "unmodified": null, + "withShift": "`~", + "withAltGraph": null, + "withAltGraphShift": null + }, + "Comma": { + "unmodified": ",", + "withShift": "<", + "withAltGraph": "ç", + "withAltGraphShift": "Ç" + }, + "Period": { + "unmodified": ".", + "withShift": ">", + "withAltGraph": null, + "withAltGraphShift": null + }, + "Slash": { + "unmodified": "/", + "withShift": "?", + "withAltGraph": "¿", + "withAltGraphShift": null + }, + "NumpadMultiply": { + "unmodified": "*", + "withShift": "*", + "withAltGraph": null, + "withAltGraphShift": null + }, + "NumpadSubtract": { + "unmodified": "-", + "withShift": "-", + "withAltGraph": null, + "withAltGraphShift": null + }, + "NumpadAdd": { + "unmodified": "+", + "withShift": "+", + "withAltGraph": null, + "withAltGraphShift": null + }, + "IntlBackslash": { + "unmodified": "\\", + "withShift": "|", + "withAltGraph": null, + "withAltGraphShift": null + } +} diff --git a/spec/keymap-manager-spec.coffee b/spec/keymap-manager-spec.coffee index 54df182..9c871c9 100644 --- a/spec/keymap-manager-spec.coffee +++ b/spec/keymap-manager-spec.coffee @@ -605,7 +605,7 @@ describe "KeymapManager", -> describe "when the Dvorak QWERTY-⌘ layout is in use on macOS", -> it "uses the US layout equivalent when the command key is held down", -> mockProcessPlatform('darwin') - stub(KeyboardLayout, 'getCurrentKeymap', -> require('./helpers/keymaps/dvorak-qwerty-cmd')) + stub(KeyboardLayout, 'getCurrentKeymap', -> require('./helpers/keymaps/mac-dvorak-qwerty-cmd')) stub(KeyboardLayout, 'getCurrentKeyboardLayout', -> 'com.apple.keylayout.DVORAK-QWERTYCMD') assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'l', code: 'KeyP', altKey: true}), 'alt-l') assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'l', code: 'KeyP', ctrlKey: true, altKey: true}), 'ctrl-alt-l') @@ -619,25 +619,27 @@ describe "KeymapManager", -> currentKeymap = null stub(KeyboardLayout, 'getCurrentKeymap', -> currentKeymap) - it "allows normal ASCII characters (<= 127) to be typed via an option modifier on macOS", -> + it "allows ASCII characters (<= 127) to be typed via an option modifier on macOS", -> mockProcessPlatform('darwin') - currentKeymap = require('./helpers/keymaps/swiss-german') + currentKeymap = require('./helpers/keymaps/mac-swiss-german') assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '@', code: 'KeyG', altKey: true}), '@') # Does not use alt variant characters outside of basic ASCII range assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '‚', code: 'KeyG', altKey: true, shiftKey: true}), 'alt-shift-G') # Does not use alt variant character if ctrl modifier is used assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '@', code: 'KeyG', ctrlKey: true, altKey: true}), 'ctrl-alt-g') - it "allows arbitrary characters to be typed via an altgraph modifier on Windows and Linux", -> + it "allows ASCII characters to be typed via an altgraph modifier on Windows", -> mockProcessPlatform('win32') - assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '@', ctrlKey: true, altKey: true, getModifierState: (key) -> key is 'AltGraph'}), '@') - assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '€', ctrlKey: true, altKey: true, getModifierState: (key) -> key is 'AltGraph'}), '€') - assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'Ë', ctrlKey: true, altKey: true, shiftKey: true, getModifierState: (key) -> key is 'AltGraph'}), 'shift-Ë') - assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'g', altKey: true, getModifierState: (key) -> false}), 'alt-g') - assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'e', altKey: true, getModifierState: (key) -> false}), 'alt-e') - assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'E', altKey: true, shiftKey: true, getModifierState: (key) -> false}), 'alt-shift-E') + currentKeymap = require('./helpers/keymaps/windows-swiss-german') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '@', code: 'Digit2', ctrlKey: true, altKey: true}), '@') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '°', code: 'Digit4', ctrlKey: true, altKey: true}), 'ctrl-alt-4') + + currentKeymap = require('./helpers/keymaps/windows-us-international') + assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '¢', code: 'KeyC', ctrlKey: true, altKey: true, shiftKey: true}), 'ctrl-alt-shift-C') + + it "allows arbitrary characters to be typed via an altgraph modifier on Linux", -> mockProcessPlatform('linux') assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '@', altKey: true, getModifierState: (key) -> key is 'AltGraph'}), '@') assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '€', altKey: true, getModifierState: (key) -> key is 'AltGraph'}), '€') @@ -648,7 +650,7 @@ describe "KeymapManager", -> it "converts non-latin keycaps to their U.S. counterpart for purposes of binding", -> mockProcessPlatform('darwin') - currentKeymap = require('./helpers/keymaps/greek') + currentKeymap = require('./helpers/keymaps/mac-greek') assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'δ', code: 'KeyD'}), 'δ') assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'Δ', code: 'KeyD', shiftKey: true}), 'Δ') assert.equal(keymapManager.keystrokeForKeyboardEvent({key: '÷', altKey: true, code: 'KeyD'}), 'alt-d') @@ -656,7 +658,7 @@ describe "KeymapManager", -> assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'Δ', code: 'KeyD', metaKey: true, shiftKey: true}), 'shift-cmd-D') # Don't use U.S. counterpart for latin characters - currentKeymap = require('./helpers/keymaps/turkish') + currentKeymap = require('./helpers/keymaps/mac-turkish') assert.equal(keymapManager.keystrokeForKeyboardEvent({key: 'ö', code: 'KeyX', metaKey: true}), 'cmd-ö') currentKeymap = null diff --git a/src/helpers.coffee b/src/helpers.coffee index bfd73a6..b3338ac 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -103,28 +103,26 @@ exports.keystrokeForKeyboardEvent = (event) -> else key = event.key + # When the option key is down on macOS, we need to determine whether the + # the user intends to type an ASCII character that is only reachable by use + # of the option key (such as option-g to type @ on a Swiss-German layout) + # or used as a modifier to match against an alt-* binding. + # + # We check for event.code because test helpers produce events without it. if altKey - if process.platform is 'darwin' - # When the option key is down on macOS, we need to determine whether the - # the user intends to type an ASCII character that is only reachable by use - # of the option key (such as option-g to type @ on a Swiss-German layout) - # or used as a modifier to match against an alt-* binding. - # - # We check for event.code because test helpers produce events without it. - if event.code and (characters = KeyboardLayout.getCurrentKeymap()[event.code]) - if shiftKey - nonAltModifiedKey = characters.withShift - else - nonAltModifiedKey = characters.unmodified - - if not ctrlKey and not metaKey and isASCIICharacter(key) and key isnt nonAltModifiedKey - altKey = false - else - key = nonAltModifiedKey - else if process.platform is 'win32' - if event.getModifierState('AltGraph') + if process.platform is 'darwin' and event.code + nonAltModifiedKey = nonAltModifiedKeyForKeyboardEvent(event) + if ctrlKey or metaKey or not isASCIICharacter(key) or key is nonAltModifiedKey + key = nonAltModifiedKey + else altKey = false + else if process.platform is 'win32' and ctrlKey and event.code + nonAltModifiedKey = nonAltModifiedKeyForKeyboardEvent(event) + if metaKey or not isASCIICharacter(key) or key is nonAltModifiedKey + key = nonAltModifiedKey + else ctrlKey = false + altKey = false else if process.platform is 'linux' if event.getModifierState('AltGraph') altKey = false @@ -162,6 +160,13 @@ exports.keystrokeForKeyboardEvent = (event) -> keystroke = normalizeKeystroke("^#{keystroke}") if event.type is 'keyup' keystroke +nonAltModifiedKeyForKeyboardEvent = (event) -> + if event.code and (characters = KeyboardLayout.getCurrentKeymap()[event.code]) + if event.shiftKey + characters.withShift + else + characters.unmodified + exports.characterForKeyboardEvent = (event) -> event.key unless event.ctrlKey or event.metaKey From fcd0eb34fac7bf61995e8a30b61418064e531699 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 15 Sep 2016 13:13:27 -0600 Subject: [PATCH 22/24] Ditch coffee-cache because it makes it hard to debug syntax errors Signed-off-by: Max Brunsfeld --- package.json | 1 - spec/helpers/setup.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 32cfd70..fa56784 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ "babel-preset-stage-0": "6.5.0", "babel-register": "6.5.2", "chai": "3.5.0", - "coffee-cache": "0.2.0", "coffee-script": "1.7.0", "coffeelint": "1.14.2", "debounce": "1.0.0", diff --git a/spec/helpers/setup.js b/spec/helpers/setup.js index ac4b496..f66d58b 100644 --- a/spec/helpers/setup.js +++ b/spec/helpers/setup.js @@ -1,5 +1,5 @@ require('babel-register') -require('coffee-cache') +require('coffee-script/register') global.assert = require('chai').assert From c9b14fdd2c9ff4981d1c7406a1414dced5afd426 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 15 Sep 2016 13:28:18 -0600 Subject: [PATCH 23/24] :arrow_up: keyboard-layout --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fa56784..450a182 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "event-kit": "^1.0.0", "fs-plus": "^2.0.4", "grim": "^1.2.1", - "keyboard-layout": "^1.1.0", + "keyboard-layout": "^1.2.0", "pathwatcher": "^6.2", "property-accessors": "^1", "season": "^5.0.2" From 83a451b4ea71b441d42d24611910292f61d1ea36 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 15 Sep 2016 13:45:38 -0600 Subject: [PATCH 24/24] Mock out process.platform as darwin by default This avoids calling the non-existent getModifierState method on our fake keyboard events when running on Travis. --- spec/keymap-manager-spec.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/keymap-manager-spec.coffee b/spec/keymap-manager-spec.coffee index 9c871c9..b368816 100644 --- a/spec/keymap-manager-spec.coffee +++ b/spec/keymap-manager-spec.coffee @@ -12,6 +12,7 @@ describe "KeymapManager", -> keymapManager = null beforeEach -> + mockProcessPlatform('darwin') keymapManager = new KeymapManager afterEach ->