diff --git a/src/ace/KeyBinding.js b/src/ace/KeyBinding.js index 16411920..d5b4842d 100644 --- a/src/ace/KeyBinding.js +++ b/src/ace/KeyBinding.js @@ -5,26 +5,15 @@ require.def("ace/KeyBinding", var KeyBinding = function(element, editor, config) { this.editor = editor; this.setConfig(config); - var keys = this.keys; var _self = this; ace.addKeyListener(element, function(e) { - var key = []; - if (e.ctrlKey) { - key.push("Ctrl"); - } - if (e.metaKey) { - key.push("Meta"); - } - if (e.altKey) { - key.push("Alt"); - } - if (e.shiftKey) { - key.push("Shift"); - } - key.push(keys[e.keyCode] || String.fromCharCode(e.keyCode)); + var hashId = 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0) + | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0); + var key = _self.keyNames[e.keyCode]; - var command = _self[_self.config.reverse[key.join("-")]]; + var command = _self[(_self.config.reverse[hashId] || {})[(key + || String.fromCharCode(e.keyCode)).toLowerCase()]]; if (command) { _self.selection = editor.getSelection(); command.call(_self); @@ -34,24 +23,62 @@ var KeyBinding = function(element, editor, config) { }; (function() { - this.keys = { - 8 : "Backspace", - 9 : "Tab", - 16 : "Shift", - 17 : "Ctrl", - 18 : "Alt", - 33 : "PageUp", - 34 : "PageDown", - 35 : "End", - 36 : "Home", - 37 : "Left", - 38 : "Up", - 39 : "Right", - 40 : "Down", - 45 : "Insert", - 46 : "Delete", - 91 : "Meta" + this.keyMods = {"ctrl": 1, "alt": 2, "option" : 2, "shift": 4, "meta": 8, "command": 8}; + + this.keyNames = { + "8" : "Backspace", + "9" : "Tab", + "13" : "Enter", + "27" : "Esc", + "32" : "Space", + "33" : "PageUp", + "34" : "PageDown", + "35" : "End", + "36" : "Home", + "37" : "Left", + "38" : "Up", + "39" : "Right", + "40" : "Down", + "45" : "Insert", + "46" : "Del", + "107": "+", + "112": "F1", + "113": "F2", + "114": "F3", + "115": "F4", + "116": "F5", + "117": "F6", + "118": "F7", + "119": "F8", + "120": "F9", + "121": "F10", + "122": "F11", + "123": "F12" }; + + function splitSafe(s, separator, limit, bLowerCase) { + return (bLowerCase && s.toLowerCase() || s) + .replace(/(?:^\s+|\n|\s+$)/g, "") + .split(new RegExp("[\\s ]*" + separator + "[\\s ]*", "g"), limit || 999); + } + + function parseKeys(keys, val, ret) { + var key, + hashId = 0, + parts = splitSafe(keys, "\\-", null, true), + i = 0, + l = parts.length; + + for (; i < l; ++i) { + if (this.keyMods[parts[i]]) + hashId = hashId | this.keyMods[parts[i]]; + else + key = parts[i] || "-"; //when empty, the splitSafe removed a '-' + } + + (ret[hashId] || (ret[hashId] = {}))[key] = val; + return ret; + } function objectReverse(obj, keySplit) { var i, j, l, key, @@ -61,10 +88,10 @@ var KeyBinding = function(element, editor, config) { if (keySplit && typeof key == "string") { key = key.split(keySplit); for (j = 0, l = key.length; j < l; ++j) - ret[key[j].replace(/Command/i, "Meta").replace(/Option/i, "Alt")] = i; + parseKeys.call(this, key[j], i, ret); } else { - ret[key.replace(/Command/i, "Meta").replace(/Option/i, "Alt")] = i; + parseKeys.call(this, key, i, ret); } } return ret; @@ -75,7 +102,7 @@ var KeyBinding = function(element, editor, config) { ? default_mac : default_win); if (typeof this.config.reverse == "undefined") - this.config.reverse = objectReverse(this.config, "|"); + this.config.reverse = objectReverse.call(this, this.config, "|"); }; this["selectall"] = function() {