diff options
author | Kris Maglione <maglione.k@gmail.com> | 2011-02-10 21:36:03 -0500 |
---|---|---|
committer | Kris Maglione <maglione.k@gmail.com> | 2011-02-10 21:36:03 -0500 |
commit | 30e29714247c58dc011bbf69a31cef9450fb8f9d (patch) | |
tree | 5f0f8f4b47e783d4a06cdb8ad736b9d405a32b27 | |
parent | 56a28ec0faa3fc5dc218fece57fed1c6d6463d5e (diff) | |
download | pentadactyl-30e29714247c58dc011bbf69a31cef9450fb8f9d.tar.gz |
Experimentally move contexts.js to contexts.jsm.
--HG--
branch : groups
rename : common/content/contexts.js => common/modules/contexts.jsm
-rw-r--r-- | common/content/autocommands.js | 12 | ||||
-rw-r--r-- | common/content/events.js | 16 | ||||
-rw-r--r-- | common/content/mappings.js | 39 | ||||
-rw-r--r-- | common/modules/base.jsm | 3 | ||||
-rw-r--r-- | common/modules/commands.jsm | 252 | ||||
-rw-r--r-- | common/modules/contexts.jsm (renamed from common/content/contexts.js) | 380 | ||||
-rw-r--r-- | common/modules/io.jsm | 6 | ||||
-rw-r--r-- | common/modules/overlay.jsm | 4 | ||||
-rw-r--r-- | common/modules/styles.jsm | 10 | ||||
-rw-r--r-- | common/modules/util.jsm | 5 |
10 files changed, 401 insertions, 326 deletions
diff --git a/common/content/autocommands.js b/common/content/autocommands.js index e24d2e6e..c5357fe1 100644 --- a/common/content/autocommands.js +++ b/common/content/autocommands.js @@ -17,7 +17,7 @@ update(AutoCommand.prototype, { } }); -var AutoCmdHive = Class("AutoCmdHive", Group.Hive, { +var AutoCmdHive = Class("AutoCmdHive", Contexts.Hive, { init: function init(group) { init.supercall(this, group); this._store = []; @@ -69,12 +69,14 @@ var AutoCmdHive = Class("AutoCmdHive", Group.Hive, { */ var AutoCommands = Module("autocommands", { init: function () { - this.user = contexts.hives.autocmd.user; + update(this, { + hives: contexts.Hives("autocmd", AutoCmdHive), + user: contexts.hives.autocmd.user + }); }, - hives: Group.Hives("autocmd", AutoCmdHive), - - get activeHives() contexts.activeGroups("autocmd").map(function (h) h.autocmd).filter(function (h) h._store.length), + get activeHives() contexts.initializedGroups("autocmd") + .filter(function (h) h._store.length), add: deprecated("autocommand.user.add", { get: function add() autocommands.user.closure.add }), get: deprecated("autocommand.user.get", { get: function get() autocommands.user.closure.get }), diff --git a/common/content/events.js b/common/content/events.js index de6a65aa..dbbb0f34 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -255,7 +255,7 @@ var KeyArgProcessor = Class("KeyArgProcessor", KeyProcessor, { } }); -var EventHive = Class("EventHive", Group.Hive, { +var EventHive = Class("EventHive", Contexts.Hive, { init: function init(group) { init.supercall(this, group); this.sessionListeners = []; @@ -321,6 +321,14 @@ var Events = Module("events", { init: function () { const self = this; + update(this, { + hives: contexts.Hives("events", EventHive), + user: contexts.hives.events.user, + builtin: contexts.hives.events.builtin + }); + + EventHive.prototype.wrapListener = this.closure.wrapListener; + XML.ignoreWhitespace = true; util.overlayWindow(window, { append: <e4x xmlns={XUL}> @@ -342,10 +350,6 @@ var Events = Module("events", { this._macroKeys = []; this._lastMacro = ""; - EventHive.prototype.wrapListener = this.closure.wrapListener; - this.user = contexts.hives.events.user; - this.builtin = contexts.hives.events.builtin; - this._macros = storage.newMap("macros", { privateData: true, store: true }); for (let [k, m] in this._macros) if (isString(m)) @@ -411,8 +415,6 @@ var Events = Module("events", { }); }, - hives: Group.Hives("events", EventHive), - /** * Adds an event listener for this session and removes it on * dactyl shutdown. diff --git a/common/content/mappings.js b/common/content/mappings.js index 86ff72ca..5ab10f3c 100644 --- a/common/content/mappings.js +++ b/common/content/mappings.js @@ -138,7 +138,7 @@ var Map = Class("Map", { id: 0 }); -var MapHive = Class("MapHive", Group.Hive, { +var MapHive = Class("MapHive", Contexts.Hive, { init: function init(group) { init.supercall(this, group); this.stacks = {}; @@ -297,14 +297,10 @@ var MapHive = Class("MapHive", Group.Hive, { */ var Mappings = Module("mappings", { init: function () { - this.user = contexts.hives.mappings.user; - this.builtin = contexts.hives.mappings.builtin; }, repeat: Modes.boundProperty(), - hives: Group.Hives("mappings", MapHive), - get allHives() contexts.allGroups.mappings, get userHives() this.allHives.filter(function (h) h !== this.builtin, this), @@ -436,7 +432,14 @@ var Mappings = Module("mappings", { } }, { }, { - commands: function () { + contexts: function initContexts(dactyl, modules, window) { + update(Mappings.prototype, { + hives: contexts.Hives("mappings", MapHive), + user: contexts.hives.mappings.user, + builtin: contexts.hives.mappings.builtin + }); + }, + commands: function initCommands(dactyl, modules, window) { function addMapCommands(ch, mapmodes, modeDescription) { function map(args, noremap) { let mapmodes = array.uniq(args["-modes"].map(findMode)); @@ -454,7 +457,7 @@ var Mappings = Module("mappings", { if (!rhs) // list the mapping mappings.list(mapmodes, mappings.expandLeader(lhs), hives); else { - util.assert(args["-group"] !== mappings.builtin, + util.assert(args["-group"].modifiable, "Cannot change mappings in the builtin group"); args["-group"].add(mapmodes, [lhs], @@ -575,7 +578,7 @@ var Mappings = Module("mappings", { commands.add([ch + "mapc[lear]"], "Remove all mappings" + modeDescription, function (args) { - util.assert(args["-group"] !== mappings.builtin, + util.assert(args["-group"].modifiable, "Cannot change mappings in the builtin group"); let mapmodes = array.uniq(args["-modes"].map(findMode)); @@ -599,7 +602,7 @@ var Mappings = Module("mappings", { commands.add([ch + "unm[ap]"], "Remove a mapping" + modeDescription, function (args) { - util.assert(args["-group"] !== mappings.builtin, + util.assert(args["-group"].modifiable, "Cannot change mappings in the builtin group"); let mapmodes = array.uniq(args["-modes"].map(findMode)); @@ -668,6 +671,12 @@ var Mappings = Module("mappings", { addMapCommands("", [modes.NORMAL, modes.VISUAL], ""); + for (let mode in modes.mainModes) + 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()]); + let args = { getMode: function (args) findMode(args["-mode"]), iterate: function (args) { @@ -729,14 +738,8 @@ var Mappings = Module("mappings", { options: [] }); }); - - for (let mode in modes.mainModes) - 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()]); }, - completion: function () { + completion: function initCompletion(dactyl, modules, window) { completion.userMapping = function userMapping(context, modes, hive) { // FIXME: have we decided on a 'standard' way to handle this clash? --djk hive = hive || mappings.user; @@ -745,14 +748,14 @@ var Mappings = Module("mappings", { context.completions = hive.iterate(modes); }; }, - javascript: function () { + javascript: function initJavascript(dactyl, modules, window) { JavaScript.setCompleter([mappings.get, mappings.builtin.get], [ null, function (context, obj, args) [[m.names, m.description] for (m in this.iterate(args[0]))] ]); }, - options: function () { + options: function initOptions(dactyl, modules, window) { options.add(["mapleader", "ml"], "Define the replacement keys for the <Leader> pseudo-key", "string", "\\", { diff --git a/common/modules/base.jsm b/common/modules/base.jsm index ea894b8c..56d86a3b 100644 --- a/common/modules/base.jsm +++ b/common/modules/base.jsm @@ -981,7 +981,8 @@ let StructBase = Class("StructBase", Array, { } }, { fromArray: function (ary) { - ary.__proto__ = this.prototype; + if (!(ary instanceof this)) + ary.__proto__ = this.prototype; return ary; }, diff --git a/common/modules/commands.jsm b/common/modules/commands.jsm index a7bfde9c..4f63fb64 100644 --- a/common/modules/commands.jsm +++ b/common/modules/commands.jsm @@ -11,12 +11,10 @@ try { Components.utils.import("resource://dactyl/bootstrap.jsm"); defineModule("commands", { exports: ["ArgType", "Command", "Commands", "CommandOption", "Ex", "commands"], + require: ["contexts"], use: ["config", "options", "template", "util"] }, this); - -/** @scope modules */ - /** * A structure representing the options available for a command. * @@ -273,20 +271,20 @@ var Command = Class("Command", { * @see Commands@parseArguments */ options: [], + optionMap: Class.memoize(function () array(this.options) .map(function (opt) opt.names.map(function (name) [name, opt])) .flatten().toObject()), + newArgs: function (base) { let res = []; update(res, base); res.__proto__ = this.argsPrototype; return res; }, - argsPrototype: Class.memoize(function () update([], - array(this.options).filter(function (opt) opt.default !== undefined) - .map(function (opt) [opt.names[0], Class.Property(Object.getOwnPropertyDescriptor(opt, "default"))]) - .toObject(), - { + + argsPrototype: Class.memoize(function () { + let res = update([], { __iterator__: function () array.iterItems(this), command: this, @@ -298,6 +296,7 @@ var Command = Class("Command", { get literalArg() this.command.literal != null && this[this.command.literal] || "", // TODO: string: Class.memoize(function () { ... }), + verify: function verify() { if (this.command.argCount) { util.assert((this.length > 0 || !/^[1+]$/.test(this.command.argCount)) && @@ -309,7 +308,18 @@ var Command = Class("Command", { "E488: Trailing characters"); } } - })), + }); + + this.options.forEach(function (opt) { + if (opt.default !== undefined) + Object.defineProperty(res, opt.names[0], + Object.getOwnPropertyDescriptor(opt, "default") || + { configurable: true, enumerable: true, get: function () opt.default }); + }); + + return res; + }), + /** * @property {boolean|function(args)} When true, invocations of this * command may contain private data which should be purged from @@ -416,6 +426,113 @@ var Ex = Module("Ex", { __noSuchMethod__: function (meth, args) this._run(meth).apply(this, args) }); +var CommandHive = Class("CommandHive", Contexts.Hive, { + init: function init(group) { + init.supercall(this, group); + this._map = {}; + this._list = []; + }, + + /** @property {Iterator(Command)} @private */ + __iterator__: function () array.iterValues(this._list.sort(function (a, b) a.name > b.name)), + + /** @property {string} The last executed Ex command line. */ + repeat: null, + + /** + * Adds a new command. + * + * @param {string[]} names The names by which this command can be + * invoked. The first name specified is the command's canonical + * name. + * @param {string} description A description of the command. + * @param {function} action The action invoked by this command. + * @param {Object} extra An optional extra configuration hash. + * @optional + */ + add: function (names, description, action, extra, replace) { + const { commands, contexts } = this.modules; + + extra = extra || {}; + if (!extra.definedAt) + extra.definedAt = contexts.getCaller(Components.stack.caller); + + extra.hive = this; + extra.parsedSpecs = Command.parseSpecs(names); + + let names = array.flatten(extra.parsedSpecs); + let name = names[0]; + + util.assert(!names.some(function (name) name in commands.builtin._map), + "E182: Can't replace non-user command: " + name); + + util.assert(replace || names.every(function (name) !(name in this._map), this), + "Not replacing command " + name); + + for (let name in values(names)) { + ex.__defineGetter__(name, function () this._run(name)); + if (name in this._map) + this.remove(name); + } + + let self = this; + let closure = function () self._map[name]; + + memoize(this._map, name, function () commands.Command(names, description, action, extra)); + memoize(this._list, this._list.length, closure); + for (let alias in values(names.slice(1))) + memoize(this._map, alias, closure); + + return name; + }, + + _add: function (names, description, action, extra, replace) { + const { contexts } = this.modules; + + extra = extra || {}; + extra.definedAt = contexts.getCaller(Components.stack.caller.caller); + return this.add.apply(this, arguments); + }, + + /** + * Clear all commands. + * @returns {Command} + */ + clear: function clear() { + util.assert(this.group.modifiable, "Cannot delete non-user commands"); + this._map = {}; + this._list = []; + }, + + /** + * Returns the command with matching *name*. + * + * @param {string} name The name of the command to return. This can be + * any of the command's names. + * @param {boolean} full If true, only return a command if one of + * its names matches *name* exactly. + * @returns {Command} + */ + get: function get(name, full) this._map[name] + || !full && array.nth(this._list, function (cmd) cmd.hasName(name), 0) + || null, + + /** + * Remove the user-defined command with matching *name*. + * + * @param {string} name The name of the command to remove. This can be + * any of the command's names. + */ + remove: function remove(name) { + util.assert(this.group.modifiable, "Cannot delete non-user commands"); + + let cmd = this.get(name); + this._list = this._list.filter(function (c) c !== cmd); + for (let name in values(cmd.names)) + delete this._map[name]; + } +}); + /** * @instance commands */ @@ -425,121 +542,17 @@ var Commands = Module("commands", { Local: function Local(dactyl, modules, window) let ({ Group, contexts } = modules) ({ init: function () { this.Command = Class("Command", Command, { modules: modules }); - this.user = contexts.hives.commands.user; - this.builtin = contexts.hives.commands.builtin; + update(this, { + hives: contexts.Hives("commands", Class("CommandHive", CommandHive, { modules: modules })), + user: contexts.hives.commands.user, + builtin: contexts.hives.commands.builtin + }); }, get context() contexts.context, get readHeredoc() modules.io.readHeredoc, - hives: Group.Hives("commands", Class("CommandHive", Group.Hive, { - init: function init(group) { - init.supercall(this, group); - this._map = {}; - this._list = []; - }, - - /** @property {Iterator(Command)} @private */ - __iterator__: function () array.iterValues(this._list.sort(function (a, b) a.name > b.name)), - - /** @property {string} The last executed Ex command line. */ - repeat: null, - - /** - * Adds a new command. - * - * @param {string[]} names The names by which this command can be - * invoked. The first name specified is the command's canonical - * name. - * @param {string} description A description of the command. - * @param {function} action The action invoked by this command. - * @param {Object} extra An optional extra configuration hash. - * @optional - */ - add: function (names, description, action, extra, replace) { - const { commands } = modules; - - extra = extra || {}; - if (!extra.definedAt) - extra.definedAt = contexts.getCaller(Components.stack.caller); - - extra.hive = this; - extra.parsedSpecs = Command.parseSpecs(names); - - let names = array.flatten(extra.parsedSpecs); - let name = names[0]; - - util.assert(!names.some(function (name) name in commands.builtin._map), - "E182: Can't replace non-user command: " + name); - - util.assert(replace || names.every(function (name) !(name in this._map), this), - "Not replacing command " + name); - - for (let name in values(names)) { - ex.__defineGetter__(name, function () this._run(name)); - if (name in this._map) - this.remove(name); - } - - let self = this; - let closure = function () self._map[name]; - - memoize(this._map, name, function () commands.Command(names, description, action, extra)); - memoize(this._list, this._list.length, closure); - for (let alias in values(names.slice(1))) - memoize(this._map, alias, closure); - - return name; - }, - - _add: function (names, description, action, extra, replace) { - extra = extra || {}; - extra.definedAt = contexts.getCaller(Components.stack.caller.caller); - return this.add.apply(this, arguments); - }, - - /** - * Clear all commands. - * @returns {Command} - */ - clear: function clear() { - util.assert(this.group !== contexts.default, - "Cannot delete non-user commands"); - this._map = {}; - this._list = []; - }, - - /** - * Returns the command with matching *name*. - * - * @param {string} name The name of the command to return. This can be - * any of the command's names. - * @param {boolean} full If true, only return a command if one of - * its names matches *name* exactly. - * @returns {Command} - */ - get: function get(name, full) this._map[name] - || !full && array.nth(this._list, function (cmd) cmd.hasName(name), 0) - || null, - - /** - * Remove the user-defined command with matching *name*. - * - * @param {string} name The name of the command to remove. This can be - * any of the command's names. - */ - remove: function remove(name) { - util.assert(this.group !== contexts.default, - "Cannot delete non-user commands"); - - let cmd = this.get(name); - this._list = this._list.filter(function (c) c !== cmd); - for (let name in values(cmd.names)) - delete this._map[name]; - } - })), - get allHives() contexts.allGroups.commands, get userHives() this.allHives.filter(function (h) h !== this.builtin, this), @@ -689,7 +702,8 @@ var Commands = Module("commands", { let defaults = {}; if (args.ignoreDefaults) - defaults = array(this.options).map(function (opt) [opt.names[0], opt.default]).toObject(); + defaults = array(this.options).map(function (opt) [opt.names[0], opt.default]) + .toObject(); for (let [opt, val] in Iterator(args.options || {})) { if (val != null && defaults[opt] === val) diff --git a/common/content/contexts.js b/common/modules/contexts.jsm index caa5b8c5..98c130fa 100644 --- a/common/content/contexts.js +++ b/common/modules/contexts.jsm @@ -4,34 +4,45 @@ // given in the LICENSE.txt file included with this file. "use strict"; +try { + +Components.utils.import("resource://dactyl/bootstrap.jsm"); +defineModule("contexts", { + exports: ["Contexts", "Group", "contexts"], + use: ["commands", "options", "services", "storage", "styles", "util"] +}, this); + var Group = Class("Group", { init: function init(name, description, filter, persist) { const self = this; + this.name = name; this.description = description; - this.filter = filter || Group.defaultFilter; + this.filter = filter || this.constructor.defaultFilter; this.persist = persist || false; this.hives = []; }, + modifiable: true, + cleanup: function cleanup() { for (let hive in values(this.hives)) - dactyl.trapErrors("cleanup", hive); + util.trapErrors("cleanup", hive); this.hives = []; - for (let hive in keys(Group.hiveMap)) + for (let hive in keys(this.hiveMap)) delete this[hive]; }, destroy: function destroy() { for (let hive in values(this.hives)) - dactyl.trapErrors("destroy", hive); + util.trapErrors("destroy", hive); }, argsExtra: function argsExtra() ({}), get toStringParams() [this.name], - get builtin() contexts.builtinGroups.indexOf(this) >= 0, + get builtin() this.modules.contexts.builtinGroups.indexOf(this) >= 0, }, { compileFilter: function (patterns) { @@ -44,7 +55,10 @@ var Group = Class("Group", { return update(siteFilter, { toString: function () this.filters.join(","), - toXML: function () template.map(this.filters, function (f) <span highlight={f(buffer.uri) ? "Filter" : ""}>{f}</span>, <>,</>), + toXML: function (modules) let (uri = modules && modules.buffer.uri) + template.map(this.filters, + function (f) <span highlight={uri && f(uri) ? "Filter" : ""}>{f}</span>, + <>,</>), filters: patterns.map(function (pattern) { let [, res, filter] = /^(!?)(.*)/.exec(pattern); @@ -57,93 +71,170 @@ var Group = Class("Group", { }); }, - groupsProto: {}, + defaultFilter: Class.memoize(function () this.compileFilter(["*"])) +}); - defaultFilter: Class.memoize(function () this.compileFilter(["*"])), +var Contexts = Module("contexts", { + Local: function Local(dactyl, modules, window) ({ + init: function () { + const contexts = this; + this.modules = modules; + + this.groupList = []; + this.groupMap = {}; + this.groupsProto = {}; + this.hives = {}; + this.hiveProto = {}; + + this.user = this.addGroup("user", "User-defined items", null, true); + this.builtin = this.addGroup("builtin", "Builtin items"); + this.builtinGroups = [this.builtin, this.user]; + this.builtin.modifiable = false; + + this.GroupFlag = Class("GroupFlag", CommandOption, { + init: function (name) { + this.name = name; + + this.type = ArgType("group", function (group) { + return isString(group) ? contexts.getGroup(group, name) + : group[name]; + }); + }, - hiveMap: {}, + get toStringParams() [this.name], - Hive: Class("Hive", { - init: function init(group) { - this.group = group; + names: ["-group", "-g"], + + description: "Group to which to add", + + get default() (contexts.context && contexts.context.group || contexts.user)[this.name], + + completer: function (context) modules.completion.group(context) + }); }, - cleanup: function cleanup() {}, - destroy: function destroy() {}, + cleanup: function () { + for (let hive in values(this.groupList)) + util.trapErrors("cleanup", hive); + }, - get argsExtra() this.group.argsExtra, - get builtin() this.group.builtin, + destroy: function () { + for (let hive in values(this.groupList)) + util.trapErrors("destroy", hive); - get name() this.group.name, - set name(val) this.group.name = val, + for (let plugin in values(plugins.contexts)) + if (plugin.onUnload) + util.trapErrors("onUnload", plugin); + }, - get description() this.group.description, - set description(val) this.group.description = val, + Group: Class("Group", Group, { modules: modules, get hiveMap() modules.contexts.hives }), - get filter() this.group.filter, - set filter(val) this.group.filter = val, + Hives: Class("Hives", Class.Property, { + init: function init(name, constructor) { + const { contexts } = modules; + const self = this; - get persist() this.group.persist, - set persist(val) this.group.persist = val, + if (this.Hive) + return { + enumerable: true, - get toStringParams() [this.name] + get: function () array(contexts.groups[self.name]) + }; + + + this.Hive = constructor; + this.name = name; + memoize(contexts.Group.prototype, name, function () { + let group = constructor(this); + this.hives.push(group); + delete contexts.groups; + return group; + }); + + memoize(contexts.hives, name, + function () Object.create(Object.create(contexts.hiveProto, + { _hive: { value: name } }))); + + memoize(contexts.groupsProto, name, + function () [group[name] for (group in values(this.groups)) if (set.has(group, name))]); + }, + + get toStringParams() [this.name, this.Hive] + }) }), - Hives: Class("Hives", Class.Property, { - init: function init(name, constructor) { - const self = this; - if (this.Group) - return { - enumerable: true, + Context: function Context(file, group, args) { + const { contexts, io, newContext, plugins, userContext } = this.modules; - get: function () array(contexts.groups[self.name]) - }; + function Const(val) Class.Property({ enumerable: true, value: val }); + let isPlugin = array.nth(io.getRuntimeDirectories("plugins"), + function (dir) dir.contains(file, true), + 0); + let isRuntime = array.nth(io.getRuntimeDirectories(""), + function (dir) dir.contains(file, true), + 0); - this.Group = constructor; - this.name = name; - memoize(Group.prototype, name, function () { - let group = constructor(this); - this.hives.push(group); - delete contexts.groups; - return group; - }); + let self = set.has(plugins, file.path) && plugins[file.path]; + if (self) { + if (set.has(self, "onUnload")) + self.onUnload(); + } + else { + let name = isPlugin ? file.getRelativeDescriptor(isPlugin).replace(File.PATH_SEP, "-") + : file.leafName; + + self = update(newContext.apply(null, args || [userContext]), { + NAME: Const(name.replace(/\..*/, "").replace(/-([a-z])/g, function (m, n1) n1.toUpperCase())), + + PATH: Const(file.path), - memoize(Group.hiveMap, name, - function () Object.create(Object.create(contexts.hiveProto, - { _hive: { value: name } }))); + CONTEXT: Const(self), - memoize(Group.groupsProto, name, - function () [group[name] for (group in values(this.groups)) if (set.has(group, name))]); + unload: Const(function unload() { + if (plugins[this.NAME] === this || plugins[this.PATH] === this) + if (this.onUnload) + this.onUnload(); + + if (plugins[this.NAME] === this) + delete plugins[this.NAME]; + + if (plugins[this.PATH] === this) + delete plugins[this.PATH]; + + if (!this.GROUP.builtin) + contexts.removeGroup(this.GROUP); + }) + }); + Class.replaceProperty(plugins, file.path, self); + + // This belongs elsewhere + if (isPlugin && args) + Object.defineProperty(plugins, self.NAME, { + configurable: true, + enumerable: true, + value: self + }); } - }) -}); -plugins.contexts = {}; + let path = isRuntime ? file.getRelativeDescriptor(isRuntime) : file.path; + let name = isRuntime ? path.replace(/^(plugin|color)s([\\\/])/, "$1$2") : "script-" + path; -var Contexts = Module("contexts", { - init: function () { - this.groupList = []; - this.groupMap = {}; - this.hiveProto = {}; - - this.builtin = this.addGroup("builtin", "Builtin items"); - this.user = this.addGroup("user", "User-defined items", null, true); - this.builtinGroups = [this.builtin, this.user]; - }, + if (!group) + group = this.addGroup(commands.nameRegexp + .iterate(name.replace(/\.[^.]*$/, "")) + .join("-"), + "Script group for " + file.path, + null, false); - cleanup: function () { - for (let hive in values(this.groupList)) - dactyl.trapErrors("cleanup", hive); - }, + Class.replaceProperty(self, "GROUP", group); + Class.replaceProperty(self, "group", group); - destroy: function () { - for (let hive in values(this.groupList)) - dactyl.trapErrors("destroy", hive); + return plugins.contexts[file.path] = self; + }, - for (let plugin in values(plugins.contexts)) - if (plugin.onUnload) - dactyl.trapErrors("onUnload", plugin); + Script: function Script(file, group) { + return this.Context(file, group, [this.modules.plugins, true]); }, context: null, @@ -165,34 +256,34 @@ var Contexts = Module("contexts", { return frame; }, - groups: Class.memoize(function () Object.create(Group.groupsProto, { - groups: { value: this.activeGroups().filter(function (g) g.filter(buffer.uri)) } + groups: Class.memoize(function () Object.create(this.groupsProto, { + groups: { value: this.activeGroups() }, })), - allGroups: Class.memoize(function () Object.create(Group.groupsProto, { - groups: { value: this.activeGroups() } + allGroups: Class.memoize(function () Object.create(this.groupsProto, { + groups: { value: this.initializedGroups() } })), - activeGroups: function (hive) + activeGroups: function (hive) this.initializedGroups().filter(function (g) g.filter(this), this.modules.buffer.uri), + + initializedGroups: function (hive) let (need = hive ? [hive] : Object.keys(this.hives)) this.groupList.filter(function (group) need.some(function (name) set.has(group, name))), - get hives() Group.hiveMap, - addGroup: function addGroup(name, description, filter, persist, replace) { let group = this.getGroup(name); if (group) name = group.name; if (!group) { - group = Group(name, description, filter, persist); + group = this.Group(name, description, filter, persist); this.groupList.unshift(group); this.groupMap[name] = group; this.hiveProto.__defineGetter__(name, function () group[this._hive]); } if (replace) { - dactyl.trapErrors("cleanup", group); + util.trapErrors("cleanup", group); if (description) group.description = description; if (filter) @@ -213,12 +304,12 @@ var Contexts = Module("contexts", { let group = this.getGroup(name); - dactyl.assert(!group || !group.builtin, "Cannot remove builtin group"); + util.assert(!group || !group.builtin, "Cannot remove builtin group"); if (group) { name = group.name; this.groupList.splice(this.groupList.indexOf(group), 1); - dactyl.trapErrors("destroy", group); + util.trapErrors("destroy", group); } if (this.context && this.context.group === group) @@ -242,6 +333,8 @@ var Contexts = Module("contexts", { }, bindMacro: function (args, default_, params) { + const { dactyl, events } = this.modules; + let process = util.identity; if (callable(params)) @@ -286,111 +379,59 @@ var Contexts = Module("contexts", { return action; }, - GroupFlag: function (name) ({ - names: ["-group", "-g"], - - description: "Group to which to add", - - type: ArgType("group", function (group) isString(group) ? contexts.getGroup(group, name) : group[name]), - - get default() (contexts.context && contexts.context.group || contexts.user)[name], - - completer: function (context) completion.group(context) - }), - withContext: function withContext(defaults, callback, self) this.withSavedValues(["context"], function () { this.context = defaults && update({}, defaults); return callback.call(self, this.context); }) }, { - Context: modules.Script = function Context(file, group, args) { - function Const(val) Class.Property({ enumerable: true, value: val }); - - let isPlugin = array.nth(io.getRuntimeDirectories("plugins"), - function (dir) dir.contains(file, true), - 0); - let isRuntime = array.nth(io.getRuntimeDirectories(""), - function (dir) dir.contains(file, true), - 0); - - let self = set.has(plugins, file.path) && plugins[file.path]; - if (self) { - if (set.has(self, "onUnload")) - self.onUnload(); - } - else { - let name = isPlugin ? file.getRelativeDescriptor(isPlugin).replace(File.PATH_SEP, "-") : file.leafName; - - self = update(modules.newContext.apply(null, args || [userContext]), { - NAME: Const(name.replace(/\..*/, "").replace(/-([a-z])/g, function (m, n1) n1.toUpperCase())), - - PATH: Const(file.path), - - CONTEXT: Const(self), - - unload: Const(function unload() { - if (plugins[this.NAME] === this || plugins[this.PATH] === this) - if (this.onUnload) - this.onUnload(); + Hive: Class("Hive", { + init: function init(group) { + this.group = group; + }, - if (plugins[this.NAME] === this) - delete plugins[this.NAME]; + cleanup: function cleanup() {}, + destroy: function destroy() {}, - if (plugins[this.PATH] === this) - delete plugins[this.PATH]; + get modifiable() this.group.modifiable, - if (!this.GROUP.builtin) - contexts.removeGroup(this.GROUP); - }) - }); - Class.replaceProperty(plugins, file.path, self); + get argsExtra() this.group.argsExtra, + get builtin() this.group.builtin, - // This belongs elsewhere - if (isPlugin && args) - Object.defineProperty(plugins, self.NAME, { - configurable: true, - enumerable: true, - value: self - }); - } + get name() this.group.name, + set name(val) this.group.name = val, - let path = isRuntime ? file.getRelativeDescriptor(isRuntime) : file.path; + get description() this.group.description, + set description(val) this.group.description = val, - if (!group) - group = contexts.addGroup((isRuntime ? "" : "script-") + - commands.nameRegexp.iterate(path.replace(/\.[^.]*$/, "")) - .join("-"), - "Script group for " + file.path, - null, false); + get filter() this.group.filter, + set filter(val) this.group.filter = val, - Class.replaceProperty(self, "GROUP", group); - Class.replaceProperty(self, "group", group); + get persist() this.group.persist, + set persist(val) this.group.persist = val, - return plugins.contexts[file.path] = self; - }, - Script: function Script(file, group) { - return this.Context(file, group, [plugins, true]); - } + get toStringParams() [this.name] + }) }, { - commands: function initCommands() { + commands: function initCommands(dactyl, modules, window) { + const { commands, contexts } = modules; commands.add(["gr[oup]"], "Create or select a group", function (args) { if (args.length > 0) { var name = Option.dequote(args[0]); - dactyl.assert(name !== "builtin", "Cannot modify builtin group"); - dactyl.assert(commands.validName.test(name), "Invalid group name"); + util.assert(name !== "builtin", "Cannot modify builtin group"); + util.assert(commands.validName.test(name), "Invalid group name"); var group = contexts.getGroup(name); } else if (args.bang) var group = args.context && args.context.group; else - return void completion.listCompleter("group", "", null, null); + return void modules.completion.listCompleter("group", "", null, null); - dactyl.assert(group || name, "No current group"); + util.assert(group || name, "No current group"); let filter = Group.compileFilter(args["-locations"]); if (!group || args.bang) @@ -418,7 +459,7 @@ var Contexts = Module("contexts", { bang: true, completer: function (context, args) { if (args.length == 1) - completion.group(context); + modules.completion.group(context); }, keepQuotes: true, options: [ @@ -460,7 +501,7 @@ var Contexts = Module("contexts", { arguments: [group.name], ignoreDefaults: true } - for (group in values(contexts.activeGroups())) + for (group in values(contexts.initializedGroups())) if (!group.builtin && group.persist) ].concat([{ command: this.name, arguments: ["user"] }]) }); @@ -468,13 +509,13 @@ var Contexts = Module("contexts", { commands.add(["delg[roup]"], "Delete a group", function (args) { - dactyl.assert(contexts.getGroup(args[0]), "No such group: " + args[0]); + util.assert(contexts.getGroup(args[0]), "No such group: " + args[0]); contexts.removeGroup(args[0]); }, { argCount: "1", completer: function (context, args) { - completion.group(context); + modules.completion.group(context); context.filters.push(function ({ item }) !item.builtin); } }); @@ -483,7 +524,7 @@ var Contexts = Module("contexts", { commands.add(["fini[sh]"], "Stop sourcing a script file", function (args) { - dactyl.assert(args.context, "E168: :finish used outside of a sourced file"); + util.assert(args.context, "E168: :finish used outside of a sourced file"); args.context.finished = true; }, { argCount: "0" }); @@ -545,16 +586,18 @@ var Contexts = Module("contexts", { argCount: "0" }); }, - completion: function initCompletion() { + completion: function initCompletion(dactyl, modules, window) { + const { completion, contexts } = modules; + completion.group = function group(context, active) { context.title = ["Group"]; - let uri = buffer.uri; + let uri = modules.buffer.uri; context.keys = { active: function (group) group.filter(uri), text: "name", - description: function (g) <>{g.filter.toXML ? g.filter.toXML() + <> </> : ""}{g.description || ""}</> + description: function (g) <>{g.filter.toXML ? g.filter.toXML(modules) + <> </> : ""}{g.description || ""}</> }; - context.completions = (active === undefined ? contexts.groupList : contexts.activeGroups(active)) + context.completions = (active === undefined ? contexts.groupList : contexts.initializedGroups(active)) .slice(0, -1); iter({ Active: true, Inactive: false }).forEach(function ([name, active]) { @@ -567,3 +610,8 @@ var Contexts = Module("contexts", { } }); +endModule(); + +} catch(e){ if (!e.stack) e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); } + +// vim: set fdm=marker sw=4 ts=4 et ft=javascript: diff --git a/common/modules/io.jsm b/common/modules/io.jsm index bb52400c..585b8e63 100644 --- a/common/modules/io.jsm +++ b/common/modules/io.jsm @@ -145,7 +145,7 @@ var IO = Module("io", { * silent: Whether errors should not be reported. */ source: function source(filename, params) { - const { Contexts, contexts } = modules; + const { contexts } = modules; defineModule.loadLog.push("sourcing " + filename); params = params || {}; @@ -167,7 +167,7 @@ var IO = Module("io", { // handle pure JavaScript files specially if (/\.js$/.test(filename)) { try { - var context = Contexts.Script(file, params.group); + var context = contexts.Script(file, params.group); dactyl.loadScript(uri.spec, context); dactyl.helpInitialized = false; } @@ -186,7 +186,7 @@ var IO = Module("io", { else if (/\.css$/.test(filename)) styles.registerSheet(uri.spec, false, true); else { - context = Contexts.Context(file, params.group); + context = contexts.Context(file, params.group); modules.commands.execute(file.read(), null, params.silent, null, { context: context, diff --git a/common/modules/overlay.jsm b/common/modules/overlay.jsm index c878c724..fe8ea1fd 100644 --- a/common/modules/overlay.jsm +++ b/common/modules/overlay.jsm @@ -157,6 +157,7 @@ var Overlay = Module("Overlay", { "commands", "completion", "config", + "contexts", "downloads", "finder", "highlight", @@ -172,8 +173,7 @@ var Overlay = Module("Overlay", { "util" ].forEach(function (name) defineModule.time("load", name, require, null, jsmodules, name)); - ["contexts", - "dactyl", + ["dactyl", "modes", "commandline", "abbreviations", diff --git a/common/modules/styles.jsm b/common/modules/styles.jsm index 245feccd..aee8f4c0 100644 --- a/common/modules/styles.jsm +++ b/common/modules/styles.jsm @@ -8,13 +8,13 @@ Components.utils.import("resource://dactyl/bootstrap.jsm"); defineModule("styles", { exports: ["Style", "Styles", "styles"], require: ["services", "util"], - use: ["template"] + use: ["contexts", "template"] }, this); function cssUri(css) "chrome-data:text/css," + encodeURI(css); var namespace = "@namespace html " + XHTML.uri.quote() + ";\n" + - "@namespace xul " + XUL.uri.quote() + ";\n" + - "@namespace dactyl " + NS.uri.quote() + ";\n"; + "@namespace xul " + XUL.uri.quote() + ";\n" + + "@namespace dactyl " + NS.uri.quote() + ";\n"; var Sheet = Struct("name", "id", "sites", "css", "hive", "agent"); Sheet.liveProperty = function (name) { @@ -614,8 +614,8 @@ var Styles = Module("Styles", { }); }, contexts: function (dactyl, modules, window) { - modules.Group.Hives("styles", - Class("LocalHive", modules.Group.Hive, { + modules.contexts.Hives("styles", + Class("LocalHive", Contexts.Hive, { init: function init(group) { init.superapply(this, arguments); diff --git a/common/modules/util.jsm b/common/modules/util.jsm index 18f7e83a..de87279a 100644 --- a/common/modules/util.jsm +++ b/common/modules/util.jsm @@ -1405,6 +1405,9 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), } catch (e) { dump(e + "\n"); } } + + // ctypes.open("libc.so.6").declare("kill", ctypes.default_abi, ctypes.void_t, ctypes.int, ctypes.int)( + // ctypes.open("libc.so.6").declare("getpid", ctypes.default_abi, ctypes.int)(), 2) }, /** @@ -1596,6 +1599,8 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), */ trapErrors: function trapErrors(func, self) { try { + if (isString(func)) + func = self[func]; return func.apply(self || this, Array.slice(arguments, 2)); } catch (e) { |