diff --git a/demo/demo_startup.js b/demo/demo_startup.js index 2e0ec600..6a3018cc 100644 --- a/demo/demo_startup.js +++ b/demo/demo_startup.js @@ -57,6 +57,7 @@ exports.launch = function(env) { var vim = require("ace/keyboard/vim").Vim; var emacs = require("ace/keyboard/emacs").Emacs; + var HashHandler = require("ace/keyboard/hash_handler").HashHandler; var docs = {}; @@ -84,9 +85,15 @@ exports.launch = function(env) { var container = document.getElementById("editor"); env.editor = new Editor(new Renderer(container, theme)); - - // This is how you change the keyboardHandler. - env.editor.setKeyboardHandler(vim); + // This is how you can set a custom keyboardHandler. + // + // Define some basic keymapping using a hash: + // env.editor.setKeyboardHandler(new HashHandler({ + // "gotoright": "Tab" + // })); + // + // Use a more complex keymapping: + // env.editor.setKeyboardHandler(vim); function onDocChange() { var doc = getDoc(); diff --git a/lib/ace/editor.js b/lib/ace/editor.js index fed601df..bb977088 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -491,7 +491,7 @@ var Editor =function(renderer, doc) { } this.onTextInput = function(text) { - this.keyBinding.onTextInput(text); + this.keyBinding.onTextInput.call(this.keyBinding, text); }; this.onCommandKey = function(e, hashId, keyCode) { diff --git a/lib/ace/keyboard/hash_handler.js b/lib/ace/keyboard/hash_handler.js new file mode 100644 index 00000000..f968b39b --- /dev/null +++ b/lib/ace/keyboard/hash_handler.js @@ -0,0 +1,116 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Skywriter. + * + * The Initial Developer of the Original Code is + * Mozilla. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Fabian Jakobs + * Julian Viereck (julian.viereck@gmail.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { + +var keyUtil = require("pilot/keys"); + +function HashHandler(config) { + this.setConfig(config); +} + +(function() { + 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 (keyUtil.KEY_MODS[parts[i]]) + hashId = hashId | keyUtil.KEY_MODS[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, + ret = {}; + for (i in obj) { + key = obj[i]; + if (keySplit && typeof key == "string") { + key = key.split(keySplit); + for (j = 0, l = key.length; j < l; ++j) + parseKeys.call(this, key[j], i, ret); + } + else { + parseKeys.call(this, key, i, ret); + } + } + return ret; + } + + this.setConfig = function(config) { + this.$config = config; + if (typeof this.$config.reverse == "undefined") + this.$config.reverse = objectReverse.call(this, this.$config, "|"); + }; + + /** + * This function is called by keyBinding. + */ + this.handleKeyboard = function(data, hashId, textOrKey, keyCode) { + // Figure out if a commandKey was pressed or just some text was insert. + if (hashId != 0 || keyCode != 0) { + return { + command: (this.$config.reverse[hashId] || {})[textOrKey] + } + } else { + return { + command: "inserttext", + args: { + text: textOrKey + } + } + } + } +}).call(HashHandler.prototype) + +exports.HashHandler = HashHandler; +}); diff --git a/lib/ace/keyboard/keybinding.js b/lib/ace/keyboard/keybinding.js index 5cac794c..8d309126 100644 --- a/lib/ace/keyboard/keybinding.js +++ b/lib/ace/keyboard/keybinding.js @@ -42,6 +42,7 @@ var useragent = require("pilot/useragent"); var keyUtil = require("pilot/keys"); var event = require("pilot/event"); var settings = require("pilot/settings").settings; +var HashHandler = require("ace/keyboard/hash_handler").HashHandler; var default_mac = require("ace/conf/keybindings/default_mac").bindings; var default_win = require("ace/conf/keybindings/default_win").bindings; var canon = require("pilot/canon"); @@ -51,59 +52,12 @@ var KeyBinding = function(editor, config) { this.$editor = editor; this.$data = { }; this.$keyboardHandler = null; - this.setConfig(config); + this.$defaulKeyboardHandler = new HashHandler(config || (useragent.isMac + ? default_mac + : default_win)); }; (function() { - 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 (keyUtil.KEY_MODS[parts[i]]) - hashId = hashId | keyUtil.KEY_MODS[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, - ret = {}; - for (i in obj) { - key = obj[i]; - if (keySplit && typeof key == "string") { - key = key.split(keySplit); - for (j = 0, l = key.length; j < l; ++j) - parseKeys.call(this, key[j], i, ret); - } - else { - parseKeys.call(this, key, i, ret); - } - } - return ret; - } - - this.setConfig = function(config) { - this.config = config || (useragent.isMac - ? default_mac - : default_win); - if (typeof this.config.reverse == "undefined") - this.config.reverse = objectReverse.call(this, this.config, "|"); - }; - this.setKeyboardHandler = function(keyboardHandler) { if (this.$keyboardHandler != keyboardHandler) { this.$data = { }; @@ -115,24 +69,19 @@ var KeyBinding = function(editor, config) { return this.$keyboardHandler; }; - this.onCommandKey = function(e, hashId, keyCode) { - key = (keyUtil[keyCode] || - String.fromCharCode(keyCode)).toLowerCase(); - + this.$callKeyboardHandler = function (e, hashId, keyOrText, keyCode) { var toExecute; if (this.$keyboardHandler) { toExecute = - this.$keyboardHandler.handleKeyboard(this.$data, hashId, key, e); + this.$keyboardHandler.handleKeyboard(this.$data, hashId, keyOrText, keyCode, e); } // If there is nothing to execute yet, then use the default keymapping. - if (!toExecute) { - toExecute = { - command: (this.config.reverse[hashId] || {})[key] - }; + if (!toExecute || !toExecute.command) { + toExecute = this.$defaulKeyboardHandler. + handleKeyboard(this.$data, hashId, keyOrText, keyCode, e); } - // If there is something to execute, then go for it. if (toExecute) { var success = canon.exec(toExecute.command, {editor: this.$editor}, toExecute.args); @@ -142,17 +91,15 @@ var KeyBinding = function(editor, config) { } }; + this.onCommandKey = function(e, hashId, keyCode) { + key = (keyUtil[keyCode] || + String.fromCharCode(keyCode)).toLowerCase(); + + this.$callKeyboardHandler(e, hashId, key, keyCode); + }; + this.onTextInput = function(text) { - if (this.$keyboardHandler) { - var toExecute = - this.$keyboardHandler.handleKeyboard(this.$data, 0, text, {}); - var success = canon.exec(toExecute.command, - {editor: this.$editor}, toExecute.args); - if (success) { - return; - } - } - this.$editor.insert(text); + this.$callKeyboardHandler({}, 0, text, 0); } }).call(KeyBinding.prototype);