diff options
author | Kris Maglione <maglione.k@gmail.com> | 2009-05-22 22:12:11 -0400 |
---|---|---|
committer | Kris Maglione <maglione.k@gmail.com> | 2009-05-22 22:12:11 -0400 |
commit | 36f6ff463f9c6e125c964a68e160b433d5357135 (patch) | |
tree | 706a17955e935dfd8c401158c0020eab54fb6253 | |
parent | fa16e09a9a0e37fea08238ffd61dca4db1b93eb5 (diff) | |
download | pentadactyl-36f6ff463f9c6e125c964a68e160b433d5357135.tar.gz |
Store canonical names for all bound keys.
-rw-r--r-- | common/content/completion.js | 4 | ||||
-rw-r--r-- | common/content/events.js | 262 | ||||
-rw-r--r-- | common/content/liberator.js | 2 | ||||
-rw-r--r-- | common/content/mappings.js | 2 |
4 files changed, 135 insertions, 135 deletions
diff --git a/common/content/completion.js b/common/content/completion.js index 0eabbc15..071cfab2 100644 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -815,7 +815,7 @@ function Completion() //{{{ let key = item[0]; if (!isNaN(key)) key = parseInt(key); - else if (/^[A-Z_]+$/.test(key)) + else if (/^[A-Z_][A-Z0-9_]*$/.test(key)) key = ""; item.key = key; }); @@ -1120,7 +1120,7 @@ function Completion() //{{{ { if (!isNaN(a.item.key) && !isNaN(b.item.key)) return a.item.key - b.item.key; - return isNaN(b.item.key) - isNaN(a.item.key) || compare(a, b); + return isNaN(b.item.key) - isNaN(a.item.key) || compare(a.item.key, b.item.key); } if (!context.anchored) // We've already listed anchored matches, so don't list them again here. context.filters.push(function (item) util.compareIgnoreCase(item.text.substr(0, this.filter.length), this.filter)); diff --git a/common/content/events.js b/common/content/events.js index 56131a42..85af0be7 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -432,67 +432,34 @@ function Events() //{{{ // matters, so use that string as the first item, that you // want to refer to within liberator's source code for // comparisons like if (key == "<Esc>") { ... } - var keyTable = [ - [ KeyEvent.DOM_VK_ESCAPE, ["Esc", "Escape"] ], - [ KeyEvent.DOM_VK_LEFT_SHIFT, ["<"] ], - [ KeyEvent.DOM_VK_RIGHT_SHIFT, [">"] ], - [ KeyEvent.DOM_VK_RETURN, ["Return", "CR", "Enter"] ], - [ KeyEvent.DOM_VK_TAB, ["Tab"] ], - [ KeyEvent.DOM_VK_DELETE, ["Del"] ], - [ KeyEvent.DOM_VK_BACK_SPACE, ["BS"] ], - [ KeyEvent.DOM_VK_HOME, ["Home"] ], - [ KeyEvent.DOM_VK_INSERT, ["Insert", "Ins"] ], - [ KeyEvent.DOM_VK_END, ["End"] ], - [ KeyEvent.DOM_VK_LEFT, ["Left"] ], - [ KeyEvent.DOM_VK_RIGHT, ["Right"] ], - [ KeyEvent.DOM_VK_UP, ["Up"] ], - [ KeyEvent.DOM_VK_DOWN, ["Down"] ], - [ KeyEvent.DOM_VK_PAGE_UP, ["PageUp"] ], - [ KeyEvent.DOM_VK_PAGE_DOWN, ["PageDown"] ], - [ KeyEvent.DOM_VK_F1, ["F1"] ], - [ KeyEvent.DOM_VK_F2, ["F2"] ], - [ KeyEvent.DOM_VK_F3, ["F3"] ], - [ KeyEvent.DOM_VK_F4, ["F4"] ], - [ KeyEvent.DOM_VK_F5, ["F5"] ], - [ KeyEvent.DOM_VK_F6, ["F6"] ], - [ KeyEvent.DOM_VK_F7, ["F7"] ], - [ KeyEvent.DOM_VK_F8, ["F8"] ], - [ KeyEvent.DOM_VK_F9, ["F9"] ], - [ KeyEvent.DOM_VK_F10, ["F10"] ], - [ KeyEvent.DOM_VK_F11, ["F11"] ], - [ KeyEvent.DOM_VK_F12, ["F12"] ], - [ KeyEvent.DOM_VK_F13, ["F13"] ], - [ KeyEvent.DOM_VK_F14, ["F14"] ], - [ KeyEvent.DOM_VK_F15, ["F15"] ], - [ KeyEvent.DOM_VK_F16, ["F16"] ], - [ KeyEvent.DOM_VK_F17, ["F17"] ], - [ KeyEvent.DOM_VK_F18, ["F18"] ], - [ KeyEvent.DOM_VK_F19, ["F19"] ], - [ KeyEvent.DOM_VK_F20, ["F20"] ], - [ KeyEvent.DOM_VK_F21, ["F21"] ], - [ KeyEvent.DOM_VK_F22, ["F22"] ], - [ KeyEvent.DOM_VK_F23, ["F23"] ], - [ KeyEvent.DOM_VK_F24, ["F24"] ] - ]; - - function getKeyCode(str) - { - str = str.toLowerCase(); + var keyTable = { + add: ["Plus", "Add"], + back_space: ["BS"], + delete: ["Del"], + escape: ["Esc", "Escape"], + insert: ["Insert", "Ins"], + left_shift: ["<"], + return: ["Return", "CR", "Enter"], + right_shift: [">"], + space: ["Space", " "], + subtract: ["Minus", "Subtract"], + }; - for (let [,key] in Iterator(keyTable)) - { - for (let [,name] in Iterator(key[1])) - { - // we don't store lowercase keys in the keyTable, because we - // also need to get good looking strings for the reverse action - if (name.toLowerCase() == str) - return key[0]; - } + const code_key = {}; + const key_code = {}; + + for (let [k, v] in Iterator(KeyEvent)) + if (/^DOM_VK_/.test(k)) { + k = k.substr(7).toLowerCase(); + let names = [k.replace(/(^|_)(.)/g, function (m, n1, n2) n2.toUpperCase()) + .replace(/^NUMPAD/, "k")]; + if (k in keyTable) + names = keyTable[k]; + code_key[v] = names[0] + for (let [,name] in Iterator(names)) + key_code[name.toLowerCase()] = v } - return 0; - } - function isFormElemFocused() { let elem = liberator.focus; @@ -663,51 +630,53 @@ function Events() //{{{ ////////////////////// MAPPINGS //////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////{{{ - mappings.add(modes.all, - ["<Esc>", "<C-[>"], "Focus content", - function () { events.onEscape(); }); - - // add the ":" mapping in all but insert mode mappings - mappings.add([modes.NORMAL, modes.PLAYER, modes.VISUAL, modes.HINTS, modes.MESSAGE, modes.COMPOSE, modes.CARET, modes.TEXTAREA], - [":"], "Enter command line mode", - function () { commandline.open(":", "", modes.EX); }); - - // focus events - mappings.add([modes.NORMAL, modes.PLAYER, modes.VISUAL, modes.CARET], - ["<Tab>"], "Advance keyboard focus", - function () { document.commandDispatcher.advanceFocus(); }); - - mappings.add([modes.NORMAL, modes.PLAYER, modes.VISUAL, modes.CARET, modes.INSERT, modes.TEXTAREA], - ["<S-Tab>"], "Rewind keyboard focus", - function () { document.commandDispatcher.rewindFocus(); }); - - mappings.add(modes.all, - ["<C-z>"], "Temporarily ignore all " + config.name + " key bindings", - function () { modes.passAllKeys = true; }); - - mappings.add(modes.all, - ["<C-v>"], "Pass through next key", - function () { modes.passNextKey = true; }); - - mappings.add(modes.all, - ["<Nop>"], "Do nothing", - function () { return; }); - - // macros - mappings.add([modes.NORMAL, modes.PLAYER, modes.MESSAGE], - ["q"], "Record a key sequence into a macro", - function (arg) { events.startRecording(arg); }, - { flags: Mappings.flags.ARGUMENT }); - - mappings.add([modes.NORMAL, modes.PLAYER, modes.MESSAGE], - ["@"], "Play a macro", - function (count, arg) - { - if (count < 1) count = 1; - while (count-- && events.playMacro(arg)) - ; - }, - { flags: Mappings.flags.ARGUMENT | Mappings.flags.COUNT }); + liberator.registerObserver("load_mappings", function() { + mappings.add(modes.all, + ["<Esc>", "<C-[>"], "Focus content", + function () { events.onEscape(); }); + + // add the ":" mapping in all but insert mode mappings + mappings.add([modes.NORMAL, modes.PLAYER, modes.VISUAL, modes.HINTS, modes.MESSAGE, modes.COMPOSE, modes.CARET, modes.TEXTAREA], + [":"], "Enter command line mode", + function () { commandline.open(":", "", modes.EX); }); + + // focus events + mappings.add([modes.NORMAL, modes.PLAYER, modes.VISUAL, modes.CARET], + ["<Tab>"], "Advance keyboard focus", + function () { document.commandDispatcher.advanceFocus(); }); + + mappings.add([modes.NORMAL, modes.PLAYER, modes.VISUAL, modes.CARET, modes.INSERT, modes.TEXTAREA], + ["<S-Tab>"], "Rewind keyboard focus", + function () { document.commandDispatcher.rewindFocus(); }); + + mappings.add(modes.all, + ["<C-z>"], "Temporarily ignore all " + config.name + " key bindings", + function () { modes.passAllKeys = true; }); + + mappings.add(modes.all, + ["<C-v>"], "Pass through next key", + function () { modes.passNextKey = true; }); + + mappings.add(modes.all, + ["<Nop>"], "Do nothing", + function () { return; }); + + // macros + mappings.add([modes.NORMAL, modes.PLAYER, modes.MESSAGE], + ["q"], "Record a key sequence into a macro", + function (arg) { events.startRecording(arg); }, + { flags: Mappings.flags.ARGUMENT }); + + mappings.add([modes.NORMAL, modes.PLAYER, modes.MESSAGE], + ["@"], "Play a macro", + function (count, arg) + { + if (count < 1) count = 1; + while (count-- && events.playMacro(arg)) + ; + }, + { flags: Mappings.flags.ARGUMENT | Mappings.flags.COUNT }); + }); /////////////////////////////////////////////////////////////////////////////}}} ////////////////////// COMMANDS //////////////////////////////////////////////// @@ -899,6 +868,41 @@ function Events() //{{{ } }, + canonKeys: function(keys) + { + var res = [] + for (var i = 0; i < keys.length; i++) + { + let key = [keys[i]]; + let keyCode = 0; + + if (keys[i] == "<") + { + let [match, modifier, keyname] = keys.substr(i).toLowerCase().match(/<((?:[csma]-)*)(.+?)>/) || []; + if (keyname) + { + modifier = modifier.toUpperCase(); + key = [k + "-" for ([i, k] in Iterator("CASM")) if (modifier.indexOf(k + "-") >= 0)] + keyCode = key_code[keyname]; + + let c = String.fromCharCode(keyCode); + if (key.length == 0 && c == code_key[keyCode]) + key = [c.toLowerCase()]; + else + key = ["<"].concat(key, code_key[keyCode] || keyname, ">"); + i += match.length - 1; + } + } + else // a simple key + { + if (keys[i] != keys[i].toLowerCase()) + key = ["<S-", keys[i].toUpperCase(), ">"]; + } + res.push(key); + } + return util.Array.flatten(res).join(""); + }, + /** * Pushes keys onto the event queue from liberator. It is similar to * Vim's feedkeys() method, but cannot cope with 2 partially-fed @@ -942,6 +946,7 @@ function Events() //{{{ let [match, modifier, keyname] = keys.substr(i).match(/<((?:[CSMA]-)*)(.+?)>/i) || []; if (keyname) { + keyname = keyname.toLowerCase(); if (modifier) // check for modifiers { ctrl = /C-/i.test(modifier); @@ -957,22 +962,24 @@ function Events() //{{{ keyname = keyname.toUpperCase(); charCode = keyname.charCodeAt(0); } - else if (keyname.toLowerCase() == "space") - charCode = 32; - else if (keyname.toLowerCase() == "nop") + else if (keyname == "nop") string = "<Nop>"; - else if (keyCode = getKeyCode(keyname)) + else if (keyname == "space") + ; + else if (keyCode = key_code[keyname]) charCode = 0; else // an invalid key like <A-xxx> was found, stop propagation here (like Vim) break; + if (keyCode == 32) + charCode = 32; + i += match.length - 1; } } else // a simple key { - // FIXME: does not work for non A-Z keys like Ö,Ä,... - shift = (keys[i] >= "A" && keys[i] <= "Z"); + shift = keys[i] != keys[i].toLowerCase(); } let elem = liberator.focus; @@ -1026,7 +1033,7 @@ function Events() //{{{ * @param {Event} event * @returns {string} */ - toString: function (event) + toString: function (event, all) { if (!event) return "[object Mappings]"; @@ -1041,6 +1048,8 @@ function Events() //{{{ modifier += "C-"; if (event.altKey) modifier += "A-"; + if (event.shiftKey) + modifier += "S-"; if (event.metaKey) modifier += "M-"; @@ -1048,17 +1057,8 @@ function Events() //{{{ { if (event.charCode == 0) { - if (event.shiftKey) - modifier += "S-"; - - for (let i = 0; i < keyTable.length; i++) - { - if (keyTable[i][0] == event.keyCode) - { - key = keyTable[i][1][0]; - break; - } - } + if (event.keyCode in code_key) + key = code_key[event.keyCode]; } // [Ctrl-Bug] special handling of mysterious <C-[>, <C-\\>, <C-]>, <C-^>, <C-_> bugs (OS/X) // (i.e., cntrl codes 27--31) @@ -1089,19 +1089,20 @@ function Events() //{{{ else // [Ctrl-Bug 2,3,4,5/5] the <C-\\>, <C-]>, <C-^>, <C-_> bugs key = String.fromCharCode(event.charCode + 64); } - // special handling of the Space key - else if (event.charCode == 32) - { - if (event.shiftKey) - modifier += "S-"; - key = "Space"; - } // a normal key like a, b, c, 0, etc. else if (event.charCode > 0) { - key = String.fromCharCode(event.charCode); + key = String.fromCharCode(event.charCode).toLowerCase(); + if (key in key_code) + key = code_key[key_code[key]]; + } + if (key == null) + return; + let k = key.toLowerCase(); + if (!(k in key_code) || String.fromCharCode(key_code[k]).toLowerCase() == k) + { if (modifier.length == 0) - return key; + return k; } } else if (event.type == "click" || event.type == "dblclick") @@ -1129,7 +1130,6 @@ function Events() //{{{ if (key == null) return null; - // a key like F1 is always enclosed in < and > return "<" + modifier + key + ">"; }, diff --git a/common/content/liberator.js b/common/content/liberator.js index 880ea30d..a5c62840 100644 --- a/common/content/liberator.js +++ b/common/content/liberator.js @@ -1268,9 +1268,9 @@ const liberator = (function () //{{{ // commands must always be the first module to be initialized loadModule("commands", Commands); loadModule("options", Options); + loadModule("events", Events); loadModule("mappings", Mappings); loadModule("buffer", Buffer); - loadModule("events", Events); loadModule("commandline", CommandLine); loadModule("statusline", StatusLine); loadModule("editor", Editor); diff --git a/common/content/mappings.js b/common/content/mappings.js index ada1aa94..233cbd12 100644 --- a/common/content/mappings.js +++ b/common/content/mappings.js @@ -58,7 +58,7 @@ function Map(modes, keys, description, action, extraInfo) //{{{ /** @property {number[]} All of the modes for which this mapping applies. */ this.modes = modes; /** @property {string[]} All of this mapping's names (key sequences). */ - this.names = keys.map(function (cmd) cmd.replace(/[casm]-/g, String.toUpperCase)); // only store keysyms with uppercase modifier strings + this.names = keys.map(events.canonKeys); /** @property {function (number)} The function called to execute this mapping. */ this.action = action; |