define([ "settings!keys", "command", "editor", "util/dom2" ], function(Settings, command, editor) { var keycodes = { 9: "TAB", 13: "RETURN", 32: "SPACE", 33: "PAGEUP", 34: "PAGEDOWN", 35: "END", 36: "HOME", 37: "LEFT", 39: "RIGHT", 38: "UP", 40: "DOWN", 187: "=", 189: "-" }; //back-compat: we now use Ace-style bindings (Ctrl-X) instead of Vim-style (^-x) var upgradeKeys = function(config) { var converted = {}; for (var key in config) { var value = config[key]; //detect old syntax if (key.indexOf("^-") > -1 || key.indexOf("M-") > -1) { key = key .replace(/\^-/g, "Ctrl-") .replace(/M-/g, "Alt-") .replace(/-([A-Z]+)$/, "-Shift-$1") .replace(/-([a-z]+)$/, function(match) { return match.toUpperCase() }); } converted[key] = value; } return converted; }; //need to remove existing Ace conflicts var bindAce = function() { var handler = editor.getKeyboardHandler(); var bindings = upgradeKeys(Settings.get("keys")); for (var k in bindings) { var action = bindings[k]; if (!action.ace) continue; handler.bindKey(k, action.ace); } }; command.on("init:startup", bindAce); command.on("init:restart", bindAce); //we have to listen on keydown, because keypress will get caught by the window manager window.on("keydown", function(e) { var char = String.fromCharCode(e.keyCode); if (e.keyCode in keycodes) { char = keycodes[e.keyCode]; } var prefixes = []; if (e.ctrlKey) prefixes.push("Ctrl"); if (e.altKey) prefixes.push("Alt"); if (e.shiftKey) prefixes.push("Shift"); var combo = prefixes.length ? prefixes.join("-") + "-" + char : char; var keyConfig = upgradeKeys(Settings.get("keys")); if (combo in keyConfig) { e.preventDefault(); var action = keyConfig[combo]; if (typeof action == "string") { action = { command: action }; } if (action.ace) { //we're going to bind these directly on startup //so we shouldn't act on them return;// editor.execCommand(action.ace); } command.fire(action.command, action.argument); } }); });