diff --git a/common/content/buffer.js b/common/content/buffer.js index d76c6045..e1a4a97f 100644 --- a/common/content/buffer.js +++ b/common/content/buffer.js @@ -309,7 +309,11 @@ var Buffer = Module("buffer", { // happens when the users switches tabs onLocationChange: function onLocationChange(webProgress, request, uri) { onLocationChange.superapply(this, arguments); + + delete mappings.hives; + statusline.updateUrl(); + if (webProgress.DOMWindow && uri) { statusline.updateProgress(webProgress.DOMWindow); diff --git a/common/content/commands.js b/common/content/commands.js index e0d2e9c9..99daaf8b 100644 --- a/common/content/commands.js +++ b/common/content/commands.js @@ -760,6 +760,7 @@ var Commands = Module("commands", { return [count, "", ""]; return [count, io.readHeredoc(arg), ""]; } + let [count, arg, quote] = Commands.parseArg(str, null, _keepQuotes); if (quote == "\\" && !complete) return [, , , "Trailing \\"]; diff --git a/common/content/events.js b/common/content/events.js index d19137f6..2ec56994 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -1115,8 +1115,6 @@ var Events = Module("events", { this.main = main; this.events = []; this.hive = hive; - if (!hive.get) - util.dumpStack(main + " " + hive + " !hive.get") }, get toStringParams() [this.main.name, this.hive.name], @@ -1135,7 +1133,6 @@ var Events = Module("events", { process: function process(event) { function kill(event) { - util.dumpStack("kill " + events.toString(event)); event.stopPropagation(); event.preventDefault(); } diff --git a/common/content/mappings.js b/common/content/mappings.js index f7699b7e..e8f7bdd1 100644 --- a/common/content/mappings.js +++ b/common/content/mappings.js @@ -122,13 +122,17 @@ var Map = Class("Map", { }); var MapHive = Class("MapHive", { - init: function init(name) { + init: function init(name, description, filter) { this.name = name; this.stacks = {}; + this.description = description; + this.filter = filter || function (uri) true; }, get toStringParams() [this.name], + get builtin() mappings.builtinHives.indexOf(this) >= 0, + /** * Iterates over all mappings present in all of the given *modes*. * @@ -263,15 +267,18 @@ var MapHive = Class("MapHive", { */ var Mappings = Module("mappings", { init: function () { - this.userHive = MapHive("user"); - this.builtinHive = MapHive("builtin"); - this.hives = array([this.userHive, this.builtinHive]); + this.userHive = MapHive("user", "User-defined mappings"); + this.builtinHive = MapHive("builtin", "Builtin mappings"); + + this.builtinHives = array([this.userHive, this.builtinHive]); + this.allHives = [this.userHive, this.builtinHive]; }, - _addMap: function (map) { - let hive = map.user ? this.userHive : this.builtinHive; + hives: Class.memoize(function () array(this.allHives.filter(function (h) h.filter(buffer.uri)))), + _addMap: function (map, hive) { map.definedAt = commands.getCaller(Components.stack.caller.caller); + map.hive = hive; map.modes.forEach(function (mode) { hive.add(mode, map); }); @@ -311,7 +318,7 @@ var Mappings = Module("mappings", { * @optional */ add: function (modes, keys, description, action, extra) { - this._addMap(Map(modes, keys, description, action, extra)); + this._addMap(Map(modes, keys, description, action, extra), this.builtinHive); }, /** @@ -335,9 +342,26 @@ var Mappings = Module("mappings", { for (let [, mode] in Iterator(map.modes)) this.userHive.remove(mode, name); - this._addMap(map); + this._addMap(map, extra.hive || this.userHive); }, + addHive: function addHive(name, filter, description) { + this.removeHive(name); + let hive = MapHive(name, description, filter); + this.allHives.unshift(hive); + return hive; + }, + + removeHive: function removeHive(name, filter) { + let hive = this.getHive(name); + dactyl.assert(!hive || !hive.builtin, "Not replacing builtin hive"); + if (hive) + this.allHives.splice(this.allHives.indexOf(hive), 1); + return hive; + }, + + getHive: function getHive(name) array.nth(this.allHives, function (h) h.name == name, 0) || null, + /** * Returns the map from *mode* named *cmd*. * @@ -416,6 +440,9 @@ var Mappings = Module("mappings", { if (noremap) args["-builtin"] = true; + if (isString(args["-group"])) + args["-group"] = mappings.getHive(args["-group"]); + if (!rhs) // list the mapping mappings.list(mapmodes, mappings.expandLeader(lhs)); else { @@ -424,6 +451,7 @@ var Mappings = Module("mappings", { Command.bindMacro(args, "-keys", function (params) params), { count: args["-count"], + hive: args["-group"], noremap: args["-builtin"], persist: !args["-nopersist"], get rhs() String(this.action), @@ -465,6 +493,17 @@ var Mappings = Module("mappings", { names: ["-ex", "-e"], description: "Execute this mapping as an Ex command rather than keys" }, + { + names: ["-group", "-g"], + description: "Mapping group to which to add this mapping", + type: CommandOption.STRING, + get default() io.sourcing && io.sourcing.mapHive || mappings.userHive, + completer: function (context) { + context.keys = { text: "name", description: function (h) h.description || h.filter }; + context.completions = mappings.allHives.filter(function (h) h.name != "builtin"); + }, + validator: Option.validateCompleter + }, { names: ["-javascript", "-js", "-j"], description: "Execute this mapping as JavaScript rather than keys" @@ -564,6 +603,58 @@ var Mappings = Module("mappings", { }); } + commands.add(["mapg[roup]"], + "Create or select a mapping group", + function (args) { + dactyl.assert(args.length <= 2, "Trailing characters"); + + if (args.length == 0) { + throw FailedAssertion("Not implemented"); + return; + } + + let name = Option.dequote(args[0]); + let hive = mappings.getHive(name); + + if (args.length == 2) { + dactyl.assert(!hive || args.bang, "Group exists"); + + let filter = function siteFilter(uri) + siteFilter.filters.every(function (f) f(uri) == f.result); + + update(filter, { + toString: function () this.filters.join(","), + filters: Option.splitList(args[1], true).map(function (pattern) { + let [, res, filter] = /^(!?)(.*)/.exec(pattern); + + return update(Styles.matchFilter(filter), { + result: !res, + toString: function () pattern + }); + }) + }); + + hive = mappings.addHive(name, filter, args["-description"]); + } + + dactyl.assert(hive, "No mapping group: " + name); + dactyl.assert(hive.name != "builtin", "Can't map to builtin hive"); + if (io.sourcing) + io.sourcing.mapHive = hive; + }, + { + argCount: "*", + bang: true, + keepQuotes: true, + options: [ + { + names: ["-description", "-d"], + description: "A description of this mapping group", + type: CommandOption.STRING + } + ] + }); + let modeFlag = { names: ["-mode", "-m"], type: CommandOption.STRING, @@ -683,7 +774,7 @@ var Mappings = Module("mappings", { "string", "\\", { setter: function (value) { if (this.hasChanged) - for (let hive in mappings.hives.iterValues()) + for (let hive in values(mappings.allHives)) for (let stack in values(hive.stacks)) delete stack.states; return value; diff --git a/common/content/options.js b/common/content/options.js index 98332060..4211af66 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -389,7 +389,7 @@ var Option = Class("Option", { }, parseRegexp: function (value, result, flags) { - if (isArray(flags)) // Called by map + if (isArray(flags)) // Called by Array.map result = flags = undefined; let [, bang, val] = /^(!?)(.*)/.exec(value); diff --git a/common/modules/prefs.jsm b/common/modules/prefs.jsm index 36c12669..9e8128ed 100644 --- a/common/modules/prefs.jsm +++ b/common/modules/prefs.jsm @@ -38,15 +38,15 @@ var Prefs = Module("prefs", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]) cleanup: function cleanup() { if (this.defaults != this) this.defaults.cleanup(); - - this.branch.removeObserver("", this); this._observers = {}; if (this.observe) { + this.branch.removeObserver("", this); this.observe.unregister(); delete this.observe; } }, + observe: null, observers: { "nsPref:changed": function (subject, data) { let observers = this._observers[data]; diff --git a/common/modules/styles.jsm b/common/modules/styles.jsm index 53d66ad4..515e83ec 100644 --- a/common/modules/styles.jsm +++ b/common/modules/styles.jsm @@ -311,6 +311,10 @@ var Styles = Module("Styles", { matchFilter: function (filter) { if (filter === "*") var test = function test(uri) true; + else if (filter[0] == "^") { + let re = RegExp(filter[0]); + test = function test(uri) re.test(uri.spec); + } else if (/[*]$/.test(filter)) { let re = RegExp("^" + util.regexp.escape(filter.substr(0, filter.length - 1))); test = function test(uri) re.test(uri.spec);