From 0cc69f8932c4d911a343bb5fdb4e7a85f67ba6d0 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sat, 5 Feb 2011 08:13:56 -0500 Subject: [PATCH] Also group :autocmds. --HG-- branch : groups --- common/content/autocommands.js | 149 +++++++++++++++++++-------------- common/content/contexts.js | 35 ++++---- common/modules/template.jsm | 4 +- 3 files changed, 110 insertions(+), 78 deletions(-) diff --git a/common/content/autocommands.js b/common/content/autocommands.js index ed962466..347a77a2 100644 --- a/common/content/autocommands.js +++ b/common/content/autocommands.js @@ -8,16 +8,25 @@ /** @scope modules */ -var AutoCommand = Struct("event", "patterns", "command"); +var AutoCommand = Struct("event", "filter", "command"); +update(AutoCommand.prototype, { + eventName: Class.memoize(function () this.event.toLowerCase()), -/** - * @instance autocommands - */ -var AutoCommands = Module("autocommands", { - init: function () { + match: function (event, pattern) { + return (!event || this.eventName == event.toLowerCase()) && (!pattern || String(this.filter) === pattern); + } +}); + +var AutoCmdHive = Class("AutoCmdHive", { + init: function init(group) { + this.group = group; this._store = []; }, + get toStringParams() [this.group.name], + + get builtin() this.group.builtin, + __iterator__: function () array.iterValues(this._store), /** @@ -26,24 +35,26 @@ var AutoCommands = Module("autocommands", { * * @param {Array} events The array of event names for which this * autocommand should be executed. - * @param {string} regexp The URL pattern to match against the buffer URL. + * @param {string} pattern The URL pattern to match against the buffer URL. * @param {string} cmd The Ex command to run. */ - add: function (events, regexp, cmd) { - events.forEach(function (event) { - this._store.push(AutoCommand(event, Option.parse.regexplist(regexp.source || regexp), cmd)); - }, this); + add: function (events, pattern, cmd) { + if (!callable(pattern)) + pattern = Group.compileFilter(pattern); + + for (let event in values(events)) + this._store.push(AutoCommand(event, pattern, cmd)); }, /** * Returns all autocommands with a matching *event* and *regexp*. * * @param {string} event The event name filter. - * @param {string} regexp The URL pattern filter. + * @param {string} pattern The URL pattern filter. * @returns {AutoCommand[]} */ - get: function (event, regexp) { - return this._store.filter(function (autoCmd) AutoCommands.matchAutoCmd(autoCmd, event, regexp)); + get: function (event, pattern) { + return this._store.filter(function (autoCmd) autoCmd.match(event, regexp)); }, /** @@ -53,8 +64,25 @@ var AutoCommands = Module("autocommands", { * @param {string} regexp The URL pattern filter. */ remove: function (event, regexp) { - this._store = this._store.filter(function (autoCmd) !AutoCommands.matchAutoCmd(autoCmd, event, regexp)); + this._store = this._store.filter(function (autoCmd) !autoCmd.match(event, regexp)); }, +}); + +/** + * @instance autocommands + */ +var AutoCommands = Module("autocommands", { + init: function () { + this.user = contexts.subGroup.autocmd.user; + }, + + hives: Group.SubGroup("autocmd", AutoCmdHive), + + get activeHives() contexts.activeGroups("autocmd").map(function (h) h.autocmd), + + add: deprecated("autocommand.user.add", { get: function add() autocommands.user.closure.add }), + get: deprecated("autocommand.user.get", { get: function get() autocommands.user.closure.get }), + remove: deprecated("autocommand.user.remove", { get: function remove() autocommands.user.closure.remove }), /** * Lists all autocommands with a matching *event* and *regexp*. @@ -63,32 +91,39 @@ var AutoCommands = Module("autocommands", { * @param {string} regexp The URL pattern filter. */ list: function (event, regexp) { - let cmds = {}; - // XXX - this._store.forEach(function (autoCmd) { - if (AutoCommands.matchAutoCmd(autoCmd, event, regexp)) { - cmds[autoCmd.event] = cmds[autoCmd.event] || []; - cmds[autoCmd.event].push(autoCmd); - } - }); + function cmds(hive) { + let cmds = {}; + hive._store.forEach(function (autoCmd) { + if (autoCmd.match(event, regexp)) { + cmds[autoCmd.event] = cmds[autoCmd.event] || []; + cmds[autoCmd.event].push(autoCmd); + } + }); + return cmds; + } commandline.commandOutput( - + { - template.map(cmds, function ([event, items]) + template.map(this.activeHives, function (hive) - - - + - template.map(items, function (item) - - - - )) + + + + + + template.map(cmds(hive), function ([event, items]) + + + template.map(items, function (item, i) + + + + + ) + + ) + + ) }
----- Auto Commands ---------- Auto Commands -----
{event}
 {item.patterns}{item.command}
{hive.group.name}
{i == 0 ? event : ""}{item.filter}{item.command}
); }, @@ -104,29 +139,26 @@ var AutoCommands = Module("autocommands", { if (options.get("eventignore").has(event)) return; - let autoCmds = this._store.filter(function (autoCmd) autoCmd.event == event); dactyl.echomsg('Executing ' + event + ' Auto commands for "*"', 8); let lastPattern = null; - let url = args.url || ""; + let uri = args.url ? util.newURI(args.url) : buffer.uri; - for (let [, autoCmd] in Iterator(autoCmds)) { - if (autoCmd.patterns.some(function (re) re.test(url) ^ !re.result)) { - if (!lastPattern || String(lastPattern) != String(autoCmd.patterns)) - dactyl.echomsg("Executing " + event + " Auto commands for " + autoCmd.patterns, 8); + event = event.toLowerCase(); + for (let hive in this.hives.iterValues()) + for (let autoCmd in values(hive._store)) + if (autoCmd.eventName === event && autoCmd.filter(uri)) { + if (!lastPattern || lastPattern !== String(autoCmd.filter)) + dactyl.echomsg("Executing " + event + " Auto commands for " + autoCmd.filter, 8); - lastPattern = autoCmd.patterns; - dactyl.echomsg("autocommand " + autoCmd.command, 9); + lastPattern = String(autoCmd.filter); + dactyl.echomsg("autocommand " + autoCmd.command, 9); - dactyl.trapErrors(autoCmd.command, autoCmd, args); - } - } + dactyl.trapErrors(autoCmd.command, autoCmd, args); + } } }, { - matchAutoCmd: function (autoCmd, event, regexp) { - return (!event || autoCmd.event == event) && (!regexp || String(autoCmd.patterns) == regexp); - } }, { commands: function () { commands.add(["au[tocmd]"], @@ -135,29 +167,21 @@ var AutoCommands = Module("autocommands", { let [event, regexp, cmd] = args; let events = []; - try { - if (args.length > 1) - Option.parse.regexplist(regexp); - } - catch (e) { - dactyl.assert(false, "E475: Invalid argument: " + regexp); - } - if (event) { // NOTE: event can only be a comma separated list for |:au {event} {pat} {cmd}| - let validEvents = Object.keys(config.autocommands); + let validEvents = Object.keys(config.autocommands).map(String.toLowerCase); validEvents.push("*"); events = Option.parse.stringlist(event); - dactyl.assert(events.every(function (event) validEvents.indexOf(event) >= 0), - "E216: No such group or event: " + event); + dactyl.assert(events.every(function (event) validEvents.indexOf(event.toLowerCase()) >= 0), + "E216: No such group or event: " + event); } if (args.length > 2) { // add new command, possibly removing all others with the same event/pattern if (args.bang) - autocommands.remove(event, regexp); + args["-group"].remove(event, regexp); cmd = contexts.bindMacro(args, "-ex", function (params) params); - autocommands.add(events, regexp, cmd); + args["-group"].add(events, regexp, cmd); } else { if (event == "*") @@ -166,7 +190,7 @@ var AutoCommands = Module("autocommands", { if (args.bang) { // TODO: "*" only appears to work in Vim when there is a {group} specified if (args[0] != "*" || args.length > 1) - autocommands.remove(event, regexp); // remove all + args["-group"].remove(event, regexp); // remove all } else autocommands.list(event, regexp); // list all @@ -183,6 +207,7 @@ var AutoCommands = Module("autocommands", { keepQuotes: true, literal: 2, options: [ + contexts.GroupFlag("autocmd"), { names: ["-javascript", "-js"], description: "Interpret the action as JavaScript code rather than an Ex command" @@ -245,7 +270,7 @@ var AutoCommands = Module("autocommands", { }; }, javascript: function () { - JavaScript.setCompleter(autocommands.get, [function () Iterator(config.autocommands)]); + JavaScript.setCompleter(autocommands.user.get, [function () Iterator(config.autocommands)]); }, options: function () { options.add(["eventignore", "ei"], diff --git a/common/content/contexts.js b/common/content/contexts.js index 793b960b..b743cab9 100644 --- a/common/content/contexts.js +++ b/common/content/contexts.js @@ -27,6 +27,26 @@ var Group = Class("Group", { subGroups: {} }, { + compileFilter: function (patterns) { + + function siteFilter(uri) siteFilter.filters.every(function (f) f(uri) == f.result); + + patterns = Option.splitList(patterns, true); + + return update(siteFilter, { + toString: function () this.filters.join(","), + + filters: patterns.map(function (pattern) { + let [, res, filter] = /^(!?)(.*)/.exec(pattern); + + return update(Styles.matchFilter(Option.dequote(filter)), { + result: !res, + toString: function () pattern + }); + }) + }); + }, + groupsProto: {}, subGroupMap: {}, @@ -256,20 +276,7 @@ var Contexts = Module("contexts", { if (args.length == 2) { dactyl.assert(!group || 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(Option.dequote(filter)), { - result: !res, - toString: function () pattern - }); - }) - }); + let filter = Group.compileFilter(args[1]); group = contexts.addGroup(name, args["-description"], filter, !args["-nopersist"]); } diff --git a/common/modules/template.jsm b/common/modules/template.jsm index cd85bb54..d3e7dcd0 100644 --- a/common/modules/template.jsm +++ b/common/modules/template.jsm @@ -86,10 +86,10 @@ var Template = Module("Template", { let ret = <>; let n = 0; for each (let i in Iterator(iter)) { - let val = func(i); + let val = func(i, n); if (val == undefined) continue; - if (sep && n++) + if (n++ && sep) ret += sep; if (interruptable && n % interruptable == 0) util.threadYield(true, true);