make hash_handler more useful

This commit is contained in:
nightwing 2012-03-13 22:06:48 +04:00
commit 6381f3e048
2 changed files with 106 additions and 168 deletions

View file

@ -1,131 +1,21 @@
define(function(require, exports, module) {
"use strict";
var keyUtil = require("../lib/keys");
var oop = require("../lib/oop");
var HashHandler = require("../keyboard/hash_handler").HashHandler;
var CommandManager = function(platform, commands) {
if (typeof platform !== "string")
throw new TypeError("'platform' argument must be either 'mac' or 'win'");
this.platform = platform;
this.commands = {};
this.commmandKeyBinding = {};
if (commands)
commands.forEach(this.addCommand, this);
this.addCommands(commands);
};
oop.inherits(CommandManager, HashHandler);
(function() {
this.addCommand = function(command) {
if (this.commands[command.name])
this.removeCommand(command);
this.commands[command.name] = command;
if (command.bindKey) {
this._buildKeyHash(command);
}
};
this.removeCommand = function(command) {
var name = (typeof command === 'string' ? command : command.name);
command = this.commands[name];
delete this.commands[name];
// exaustive search is brute force but since removeCommand is
// not a performance critical operation this should be OK
var ckb = this.commmandKeyBinding;
for (var hashId in ckb) {
for (var key in ckb[hashId]) {
if (ckb[hashId][key] == command)
delete ckb[hashId][key];
}
}
};
this.addCommands = function(commands) {
Object.keys(commands).forEach(function(name) {
var command = commands[name];
if (typeof command === "string")
return this.bindKey(command, name);
if (typeof command === "function")
command = { exec: command };
if (!command.name)
command.name = name;
this.addCommand(command);
}, this);
};
this.removeCommands = function(commands) {
Object.keys(commands).forEach(function(name) {
this.removeCommand(commands[name]);
}, this);
};
this.bindKey = function(key, command) {
if(!key)
return;
var ckb = this.commmandKeyBinding;
key.split("|").forEach(function(keyPart) {
var binding = parseKeys(keyPart, command);
var hashId = binding.hashId;
(ckb[hashId] || (ckb[hashId] = {}))[binding.key] = command;
});
};
this.bindKeys = function(keyList) {
Object.keys(keyList).forEach(function(key) {
this.bindKey(key, keyList[key]);
}, this);
};
this._buildKeyHash = function(command) {
var binding = command.bindKey;
if (!binding)
return;
var key = typeof binding == "string" ? binding: binding[this.platform];
this.bindKey(key, command);
}
function parseKeys(keys, val, ret) {
var key;
var hashId = 0;
var parts = splitSafe(keys);
for (var i=0, l = parts.length; 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 '-'
}
return {
key: key,
hashId: hashId
}
}
function splitSafe(s, separator) {
return (s.toLowerCase()
.trim()
.split(new RegExp("[\\s ]*\\-[\\s ]*", "g"), 999));
}
this.findKeyCommand = function findKeyCommand(hashId, textOrKey) {
// Convert keyCode to the string representation.
if (typeof textOrKey == "number") {
textOrKey = keyUtil.keyCodeToString(textOrKey);
}
var ckbr = this.commmandKeyBinding;
return ckbr[hashId] && ckbr[hashId][textOrKey.toLowerCase()];
}
this.exec = function(command, editor, args) {
if (typeof command === 'string')

View file

@ -41,76 +41,124 @@ define(function(require, exports, module) {
var keyUtil = require("../lib/keys");
function HashHandler(config) {
this.setConfig(config);
}
function HashHandler(config, platform) {
this.platform = platform;
this.commands = {};
this.commmandKeyBinding = {};
this.addCommands(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);
this.addCommand = function(command) {
if (this.commands[command.name])
this.removeCommand(command);
this.commands[command.name] = command;
if (command.bindKey) {
this._buildKeyHash(command);
}
};
this.removeCommand = function(command) {
var name = (typeof command === 'string' ? command : command.name);
command = this.commands[name];
delete this.commands[name];
// exhaustive search is brute force but since removeCommand is
// not a performance critical operation this should be OK
var ckb = this.commmandKeyBinding;
for (var hashId in ckb) {
for (var key in ckb[hashId]) {
if (ckb[hashId][key] == command)
delete ckb[hashId][key];
}
}
};
this.addCommands = function(commands) {
commands && Object.keys(commands).forEach(function(name) {
var command = commands[name];
if (typeof command === "string")
return this.bindKey(command, name);
if (typeof command === "function")
command = { exec: command };
if (!command.name)
command.name = name;
this.addCommand(command);
}, this);
};
this.removeCommands = function(commands) {
Object.keys(commands).forEach(function(name) {
this.removeCommand(commands[name]);
}, this);
};
this.bindKey = function(key, command) {
if(!key)
return;
var ckb = this.commmandKeyBinding;
key.split("|").forEach(function(keyPart) {
var binding = parseKeys(keyPart, command);
var hashId = binding.hashId;
(ckb[hashId] || (ckb[hashId] = {}))[binding.key] = command;
});
};
this.bindKeys = function(keyList) {
Object.keys(keyList).forEach(function(key) {
this.bindKey(key, keyList[key]);
}, this);
};
this._buildKeyHash = function(command) {
var binding = command.bindKey;
if (!binding)
return;
var key = typeof binding == "string" ? binding: binding[this.platform];
this.bindKey(key, command);
}
function parseKeys(keys, val, ret) {
var key,
hashId = 0,
parts = splitSafe(keys, "\\-", null, true),
i = 0,
l = parts.length;
var key;
var hashId = 0;
var parts = splitSafe(keys.toLowerCase());
for (; i < l; ++i) {
for (var i = 0, l = parts.length; 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 {
key: key,
hashId: hashId
}
return ret;
}
this.setConfig = function(config) {
this.$config = config;
if (typeof this.$config.reverse == "undefined")
this.$config.reverse = objectReverse.call(this, this.$config, "|");
function splitSafe(s, separator) {
return (s.trim()
.split(new RegExp("[\\s ]*\\-[\\s ]*", "g"), 999));
}
this.findKeyCommand = function findKeyCommand(hashId, keyString) {
var ckbr = this.commmandKeyBinding;
return ckbr[hashId] && ckbr[hashId][keyString.toLowerCase()];
}
this.handleKeyboard = function(data, hashId, keyString, keyCode) {
return this.findKeyCommand(hashId, keyString)
};
/**
* 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;