X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=common%2Fcontent%2Fmappings.js;h=155849e46fa73a6fb848beef87b9be44f2172129;hb=70740024f9c028c1fd63e1a1850ab062ff956054;hp=668d8ce106a02fffd666ae93fb797ee425a6621b;hpb=eeed0be1a8abf7e3c97f43b63c1d595e940fef21;p=dactyl.git diff --git a/common/content/mappings.js b/common/content/mappings.js index 668d8ce..155849e 100644 --- a/common/content/mappings.js +++ b/common/content/mappings.js @@ -12,8 +12,8 @@ * A class representing key mappings. Instances are created by the * {@link Mappings} class. * - * @param {number[]} modes The modes in which this mapping is active. - * @param {string[]} keys The key sequences which are bound to + * @param {[Modes.Mode]} modes The modes in which this mapping is active. + * @param {[string]} keys The key sequences which are bound to * *action*. * @param {string} description A short one line description of the key mapping. * @param {function} action The action invoked by each key sequence. @@ -30,26 +30,21 @@ */ var Map = Class("Map", { init: function (modes, keys, description, action, extraInfo) { - modes = Array.concat(modes); - if (!modes.every(util.identity)) - throw TypeError("Invalid modes: " + modes); - this.id = ++Map.id; this.modes = modes; this._keys = keys; this.action = action; this.description = description; - if (Object.freeze) - Object.freeze(this.modes); + Object.freeze(this.modes); if (extraInfo) - update(this, extraInfo); + this.update(extraInfo); }, name: Class.memoize(function () this.names[0]), - /** @property {string[]} All of this mapping's names (key sequences). */ + /** @property {[string]} All of this mapping's names (key sequences). */ names: Class.memoize(function () this._keys.map(function (k) events.canonicalKeys(k))), get toStringParams() [this.modes.map(function (m) m.name), this.names.map(String.quote)], @@ -58,7 +53,7 @@ var Map = Class("Map", { /** @property {number} A unique ID for this mapping. */ id: null, - /** @property {number[]} All of the modes for which this mapping applies. */ + /** @property {[Modes.Mode]} All of the modes for which this mapping applies. */ modes: null, /** @property {function (number)} The function called to execute this mapping. */ action: null, @@ -96,7 +91,7 @@ var Map = Class("Map", { */ hasName: function (name) this.keys.indexOf(name) >= 0, - get keys() this.names.map(mappings.expandLeader), + get keys() array.flatten(this.names.map(mappings.closure.expand)), /** * Execute the action for this mapping. @@ -119,7 +114,7 @@ var Map = Class("Map", { mappings.repeat = repeat; if (this.executing) - util.dumpStack("Attempt to execute mapping recursively: " + args.command); + util.dumpStack(_("map.recursive", args.command)); dactyl.assert(!this.executing, _("map.recursive", args.command)); try { @@ -159,10 +154,10 @@ var MapHive = Class("MapHive", Contexts.Hive, { }, /** - * Adds a new default key mapping. + * Adds a new key mapping. * - * @param {number[]} modes The modes that this mapping applies to. - * @param {string[]} keys The key sequences which are bound to *action*. + * @param {[Modes.Mode]} modes The modes that this mapping applies to. + * @param {[string]} keys The key sequences which are bound to *action*. * @param {string} description A description of the key mapping. * @param {function} action The action invoked by each key sequence. * @param {Object} extra An optional extra configuration hash. @@ -171,6 +166,10 @@ var MapHive = Class("MapHive", Contexts.Hive, { add: function (modes, keys, description, action, extra) { extra = extra || {}; + modes = Array.concat(modes); + if (!modes.every(util.identity)) + throw TypeError(/*L*/"Invalid modes: " + modes); + let map = Map(modes, keys, description, action, extra); map.definedAt = contexts.getCaller(Components.stack.caller); map.hive = this; @@ -307,13 +306,32 @@ var Mappings = Module("mappings", { get userHives() this.allHives.filter(function (h) h !== this.builtin, this), - expandLeader: function (keyString) keyString.replace(//i, options["mapleader"]), + expandLeader: function expandLeader(keyString) keyString.replace(//i, function () options["mapleader"]), + + prefixes: Class.memoize(function () { + let list = Array.map("CASM", function (s) s + "-"); + + return iter(util.range(0, 1 << list.length)).map(function (mask) + list.filter(function (p, i) mask & (1 << i)).join("")).toArray().concat("*-"); + }), + + expand: function expand(keys) { + keys = keys.replace(//i, options["mapleader"]); + if (!/<\*-/.test(keys)) + return keys; + + return util.debrace(events.iterKeys(keys).map(function (key) { + if (/^<\*-/.test(key)) + return ["<", this.prefixes, key.slice(3)]; + return key; + }, this).flatten().array).map(function (k) events.canonicalKeys(k)); + }, iterate: function (mode) { let seen = {}; for (let hive in this.hives.iterValues()) for (let map in array(hive.getStack(mode)).iterValues()) - if (!set.add(seen, map.name)) + if (!Set.add(seen, map.name)) yield map; }, @@ -330,8 +348,8 @@ var Mappings = Module("mappings", { /** * Adds a new default key mapping. * - * @param {number[]} modes The modes that this mapping applies to. - * @param {string[]} keys The key sequences which are bound to *action*. + * @param {[Modes.Mode]} modes The modes that this mapping applies to. + * @param {[string]} keys The key sequences which are bound to *action*. * @param {string} description A description of the key mapping. * @param {function} action The action invoked by each key sequence. * @param {Object} extra An optional extra configuration hash. @@ -352,8 +370,8 @@ var Mappings = Module("mappings", { /** * Adds a new user-defined key mapping. * - * @param {number[]} modes The modes that this mapping applies to. - * @param {string[]} keys The key sequences which are bound to *action*. + * @param {[Modes.Mode]} modes The modes that this mapping applies to. + * @param {[string]} keys The key sequences which are bound to *action*. * @param {string} description A description of the key mapping. * @param {function} action The action invoked by each key sequence. * @param {Object} extra An optional extra configuration hash (see @@ -369,7 +387,7 @@ var Mappings = Module("mappings", { /** * Returns the map from *mode* named *cmd*. * - * @param {number} mode The mode to search. + * @param {Modes.Mode} mode The mode to search. * @param {string} cmd The map name to match. * @returns {Map} */ @@ -379,9 +397,9 @@ var Mappings = Module("mappings", { * Returns an array of maps with names starting with but not equal to * *prefix*. * - * @param {number} mode The mode to search. + * @param {Modes.Mode} mode The mode to search. * @param {string} prefix The map prefix string to match. - * @returns {Map[]} + * @returns {[Map]} */ getCandidates: function (mode, prefix) this.hives.map(function (h) h.getCandidates(mode, prefix)) @@ -389,15 +407,15 @@ var Mappings = Module("mappings", { /** * Lists all user-defined mappings matching *filter* for the specified - * *modes*. + * *modes* in the specified *hives*. * - * @param {number[]} modes An array of modes to search. - * @param {string} filter The filter string to match. + * @param {[Modes.Mode]} modes An array of modes to search. + * @param {string} filter The filter string to match. @optional + * @param {[MapHive]} hives The map hives to list. @optional */ list: function (modes, filter, hives) { - let modeSign = ""; - modes.filter(function (m) m.char).forEach(function (m) { modeSign += m.char; }); - modes.filter(function (m) !m.char).forEach(function (m) { modeSign += " " + m.name; }); + let modeSign = modes.map(function (m) m.char || "").join("") + + modes.map(function (m) !m.char ? " " + m.name : "").join(""); modeSign = modeSign.replace(/^ /, ""); hives = (hives || mappings.userHives).map(function (h) [h, maps(h)]) @@ -413,9 +431,9 @@ var Mappings = Module("mappings", { let list = - - + + + { @@ -459,6 +477,11 @@ var Mappings = Module("mappings", { return; } + if (args[1] && !/^$/i.test(args[1]) + && !args["-count"] && !args["-ex"] && !args["-javascript"] + && mapmodes.every(function (m) m.count)) + args[1] = "" + args[1]; + let [lhs, rhs] = args; if (noremap) args["-builtin"] = true; @@ -474,7 +497,7 @@ var Mappings = Module("mappings", { contexts.bindMacro(args, "-keys", function (params) params), { arg: args["-arg"], - count: args["-count"], + count: args["-count"] || !(args["-ex"] || args["-javascript"]), noremap: args["-builtin"], persist: !args["-nopersist"], get rhs() String(this.action), @@ -484,92 +507,93 @@ var Mappings = Module("mappings", { } const opts = { - completer: function (context, args) { - let mapmodes = array.uniq(args["-modes"].map(findMode)); - if (args.length == 1) - return completion.userMapping(context, mapmodes, args["-group"]); - if (args.length == 2) { - if (args["-javascript"]) - return completion.javascript(context); - if (args["-ex"]) - return completion.ex(context); - } + identifier: "map", + completer: function (context, args) { + let mapmodes = array.uniq(args["-modes"].map(findMode)); + if (args.length == 1) + return completion.userMapping(context, mapmodes, args["-group"]); + if (args.length == 2) { + if (args["-javascript"]) + return completion.javascript(context); + if (args["-ex"]) + return completion.ex(context); + } + }, + hereDoc: true, + literal: 1, + options: [ + { + names: ["-arg", "-a"], + description: "Accept an argument after the requisite key press", }, - hereDoc: true, - literal: 1, - options: [ - { - names: ["-arg", "-a"], - description: "Accept an argument after the requisite key press", - }, - { - names: ["-builtin", "-b"], - description: "Execute this mapping as if there were no user-defined mappings" - }, - { - names: ["-count", "-c"], - description: "Accept a count before the requisite key press" - }, - { - names: ["-description", "-desc", "-d"], - description: "A description of this mapping", - default: "User-defined mapping", - type: CommandOption.STRING - }, - { - names: ["-ex", "-e"], - description: "Execute this mapping as an Ex command rather than keys" - }, - contexts.GroupFlag("mappings"), - { - names: ["-javascript", "-js", "-j"], - description: "Execute this mapping as JavaScript rather than keys" - }, - update({}, modeFlag, { - names: ["-modes", "-mode", "-m"], - type: CommandOption.LIST, - description: "Create this mapping in the given modes", - default: mapmodes || ["n", "v"] - }), - { - names: ["-nopersist", "-n"], - description: "Do not save this mapping to an auto-generated RC file" - }, - { - names: ["-silent", "-s", "", ""], - description: "Do not echo any generated keys to the command line" - } - ], - serialize: function () { - return this.name != "map" ? [] : - array(mappings.userHives) - .filter(function (h) h.persist) - .map(function (hive) [ - { - command: "map", - options: array([ - hive.name !== "user" && ["-group", hive.name], - ["-modes", uniqueModes(map.modes)], - ["-description", map.description], - map.silent && ["-silent"]]) - - .filter(util.identity) - .toObject(), - arguments: [map.names[0]], - literalArg: map.rhs, - ignoreDefaults: true - } - for (map in userMappings(hive)) - if (map.persist) - ]) - .flatten().array; + { + names: ["-builtin", "-b"], + description: "Execute this mapping as if there were no user-defined mappings" + }, + { + names: ["-count", "-c"], + description: "Accept a count before the requisite key press" + }, + { + names: ["-description", "-desc", "-d"], + description: "A description of this mapping", + default: /*L*/"User-defined mapping", + type: CommandOption.STRING + }, + { + names: ["-ex", "-e"], + description: "Execute this mapping as an Ex command rather than keys" + }, + contexts.GroupFlag("mappings"), + { + names: ["-javascript", "-js", "-j"], + description: "Execute this mapping as JavaScript rather than keys" + }, + update({}, modeFlag, { + names: ["-modes", "-mode", "-m"], + type: CommandOption.LIST, + description: "Create this mapping in the given modes", + default: mapmodes || ["n", "v"] + }), + { + names: ["-nopersist", "-n"], + description: "Do not save this mapping to an auto-generated RC file" + }, + { + names: ["-silent", "-s", "", ""], + description: "Do not echo any generated keys to the command line" } + ], + serialize: function () { + return this.name != "map" ? [] : + array(mappings.userHives) + .filter(function (h) h.persist) + .map(function (hive) [ + { + command: "map", + options: array([ + hive.name !== "user" && ["-group", hive.name], + ["-modes", uniqueModes(map.modes)], + ["-description", map.description], + map.silent && ["-silent"]]) + + .filter(util.identity) + .toObject(), + arguments: [map.names[0]], + literalArg: map.rhs, + ignoreDefaults: true + } + for (map in userMappings(hive)) + if (map.persist) + ]) + .flatten().array; + } }; function userMappings(hive) { let seen = {}; for (let stack in values(hive.stacks)) for (let map in array.iterValues(stack)) - if (!set.add(seen, map.id)) + if (!Set.add(seen, map.id)) yield map; } @@ -606,6 +630,7 @@ var Mappings = Module("mappings", { dactyl.echoerr(_("map.noSuch", args[0])); }, { + identifier: "unmap", argCount: "?", bang: true, completer: opts.completer, @@ -627,7 +652,7 @@ var Mappings = Module("mappings", { validator: function (value) Array.concat(value).every(findMode), completer: function () [[array.compact([mode.name.toLowerCase().replace(/_/g, "-"), mode.char]), mode.description] for (mode in values(modes.all)) - if (!mode.hidden)], + if (!mode.hidden)] }; function findMode(name) { @@ -641,7 +666,9 @@ var Mappings = Module("mappings", { function uniqueModes(modes) { let chars = [k for ([k, v] in Iterator(modules.modes.modeChars)) if (v.every(function (mode) modes.indexOf(mode) >= 0))]; - return array.uniq(modes.filter(function (m) chars.indexOf(m.char) < 0).concat(chars)); + return array.uniq(modes.filter(function (m) chars.indexOf(m.char) < 0) + .map(function (m) m.name.toLowerCase()) + .concat(chars)); } commands.add(["feedkeys", "fk"], @@ -664,14 +691,14 @@ var Mappings = Module("mappings", { if (mode.char && !commands.get(mode.char + "map", true)) addMapCommands(mode.char, [m.mask for (m in modes.mainModes) if (m.char == mode.char)], - [mode.name.toLowerCase()]); + mode.displayName); let args = { getMode: function (args) findMode(args["-mode"]), iterate: function (args, mainOnly) { let modes = [this.getMode(args)]; if (!mainOnly) - modes = modes.concat(modes[0].bases); + modes = modes[0].allBases; let seen = {}; // Bloody hell. --Kris @@ -679,7 +706,7 @@ var Mappings = Module("mappings", { for (let hive in mappings.hives.iterValues()) for (let map in array.iterValues(hive.getStack(mode))) for (let name in values(map.names)) - if (!set.add(seen, name)) { + if (!Set.add(seen, name)) { yield { name: name, columns: [ @@ -725,8 +752,8 @@ var Mappings = Module("mappings", { tags = services["dactyl:"].HELP_TAGS) ({ helpTag: prefix + map.name, __proto__: map } for (map in self.iterate(args, true)) - if (map.hive === mappings.builtin || set.has(tags, prefix + map.name))), - description: "List all " + mode.name + " mode mappings along with their short descriptions", + if (map.hive === mappings.builtin || Set.has(tags, prefix + map.name))), + description: "List all " + mode.displayName + " mode mappings along with their short descriptions", index: mode.char + "-map", getMode: function (args) mode, options: []
- ModeCommandAction{_("title.Mode")}{_("title.Command")}{_("title.Action")}