// Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2012 Kris Maglione <maglione.k at Gmail>
+// Copyright (c) 2008-2014 Kris Maglione <maglione.k at Gmail>
//
// This work is licensed for reuse under an MIT license. Details are
// given in the LICENSE.txt file included with this file.
*/
var CommandOption = Struct("names", "type", "validator", "completer", "multiple", "description", "default");
-CommandOption.defaultValue("description", function () "");
-CommandOption.defaultValue("type", function () CommandOption.NOARG);
-CommandOption.defaultValue("multiple", function () false);
+CommandOption.defaultValue("description", () => "");
+CommandOption.defaultValue("type", () => CommandOption.NOARG);
+CommandOption.defaultValue("multiple", () => false);
var ArgType = Struct("description", "parse");
update(CommandOption, {
* @property {object} The option doesn't accept an argument.
* @final
*/
- NOARG: ArgType("no arg", function (arg) !arg || null),
+ NOARG: ArgType("no arg", arg => !arg || null),
/**
* @property {object} The option accepts a boolean argument.
* @final
* @property {object} The option accepts a string argument.
* @final
*/
- STRING: ArgType("string", function (val) val),
+ STRING: ArgType("string", val => val),
/**
* @property {object} The option accepts a stringmap argument.
* @final
*/
- STRINGMAP: ArgType("stringmap", function (val, quoted) Option.parse.stringmap(quoted)),
+ STRINGMAP: ArgType("stringmap", (val, quoted) => Option.parse.stringmap(quoted)),
/**
* @property {object} The option accepts an integer argument.
* @final
* @param {Args} args The Args object passed to {@link #action}.
* @param {Object} modifiers Any modifiers to be passed to {@link #action}.
*/
- execute: function execute(args, modifiers) {
+ execute: function execute(args, modifiers={}) {
const { dactyl } = this.modules;
let context = args.context;
if (this.deprecated)
this.warn(context, "deprecated", _("warn.deprecated", ":" + this.name, this.deprecated));
- modifiers = modifiers || {};
-
if (args.count != null && !this.count)
throw FailedAssertion(_("command.noCount"));
if (args.bang && !this.bang)
extra: extra
}),
- complained: Class.Memoize(function () ({})),
+ complained: Class.Memoize(function () RealSet()),
/**
* @property {[string]} All of this command's name specs. e.g., "com[mand]"
parsedSpecs: Class.Memoize(function () Command.parseSpecs(this.specs)),
/** @property {[string]} All of this command's short names, e.g., "com" */
- shortNames: Class.Memoize(function () array.compact(this.parsedSpecs.map(function (n) n[1]))),
+ shortNames: Class.Memoize(function () array.compact(this.parsedSpecs.map(n => n[1]))),
/**
* @property {[string]} All of this command's long names, e.g., "command"
*/
- longNames: Class.Memoize(function () this.parsedSpecs.map(function (n) n[0])),
+ longNames: Class.Memoize(function () this.parsedSpecs.map(n => n[0])),
/** @property {string} The command's canonical name. */
name: Class.Memoize(function () this.longNames[0]),
_options: [],
optionMap: Class.Memoize(function () array(this.options)
- .map(function (opt) opt.names.map(function (name) [name, opt]))
+ .map(opt => opt.names.map(name => [name, opt]))
.flatten().toObject()),
newArgs: function newArgs(base) {
explicitOpts: Class.Memoize(function () ({})),
- has: function AP_has(opt) Set.has(this.explicitOpts, opt) || typeof opt === "number" && Set.has(this, opt),
+ has: function AP_has(opt) hasOwnProperty(this.explicitOpts, opt)
+ || typeof opt === "number" && hasOwnProperty(this, opt),
get literalArg() this.command.literal != null && this[this.command.literal] || "",
{ configurable: true, enumerable: true, get: function () opt.default };
if (prop.get && !prop.set)
- prop.set = function (val) { Class.replaceProperty(this, opt.names[0], val) };
+ prop.set = function (val) { Class.replaceProperty(this, opt.names[0], val); };
Object.defineProperty(res, opt.names[0], prop);
}
});
warn: function warn(context, type, message) {
let loc = !context ? "" : [context.file, context.line, " "].join(":");
- if (!Set.add(this.complained, type + ":" + (context ? context.file : "[Command Line]")))
+ let key = type + ":" + (context ? context.file : "[Command Line]");
+
+ if (!this.complained.add(key))
this.modules.dactyl.warn(loc + message);
}
}, {
hasName: function hasName(specs, name)
- specs.some(function ([long, short])
+ specs.some(([long, short]) =>
name.indexOf(short) == 0 && long.indexOf(name) == 0),
// TODO: do we really need more than longNames as a convenience anyway?
*/
cache: function cache() {
- let self = this;
let { cache } = this.modules;
this.cached = true;
- let cached = cache.get(this.cacheKey, function () {
- self.cached = false;
+ let cached = cache.get(this.cacheKey, () => {
+ this.cached = false;
this.modules.moduleManager.initDependencies("commands");
let map = {};
- for (let [name, cmd] in Iterator(self._map))
+ for (let [name, cmd] in Iterator(this._map))
if (cmd.sourceModule)
map[name] = { sourceModule: cmd.sourceModule, isPlaceholder: true };
let specs = [];
- for (let cmd in values(self._list))
- for each (let spec in cmd.parsedSpecs)
+ for (let cmd of this._list)
+ for (let spec of cmd.parsedSpecs)
specs.push(spec.concat(cmd.name));
return { map: map, specs: specs };
if (this.cached)
this.modules.initDependencies("commands");
this.cached = false;
- return array.iterValues(this._list.sort(function (a, b) a.name > b.name))
+ return array.iterValues(this._list.sort((a, b) => a.name > b.name));
},
/** @property {string} The last executed Ex command line. */
repeat: null,
/**
- * Adds a new command to the builtin hive. Accessible only to core
- * dactyl code. Plugins should use group.commands.add instead.
+ * Adds a new command to the builtin hive. Accessible only to core dactyl
+ * code. Plugins should use group.commands.add instead.
*
- * @param {[string]} specs The names by which this command can be
- * invoked. The first name specified is the command's canonical
- * name.
+ * @param {[string]} specs 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
+ * @optional
+ * @param {boolean} replace Replace an existing command of the same name.
+ * @optional
*/
- add: function add(specs, description, action, extra, replace) {
+ add: function add(specs, description, action, extra={}, replace=false) {
const { commands, contexts } = this.modules;
- extra = extra || {};
if (!extra.definedAt)
extra.definedAt = contexts.getCaller(Components.stack.caller);
if (!extra.sourceModule)
let name = names[0];
if (this.name != "builtin") {
- util.assert(!names.some(function (name) name in commands.builtin._map),
+ util.assert(!names.some(name => name in commands.builtin._map),
_("command.cantReplace", name));
- util.assert(replace || names.every(function (name) !(name in this._map), this),
+ util.assert(replace || names.every(name => !(name in this._map)),
_("command.wontReplace", name));
}
this.remove(name);
}
- let self = this;
- let closure = function () self._map[name];
+ let closure = () => this._map[name];
- memoize(this._map, name, function () commands.Command(specs, description, action, extra));
+ memoize(this._map, name, () => commands.Command(specs, description, action, extra));
if (!extra.hidden)
memoize(this._list, this._list.length, closure);
for (let alias in values(names.slice(1)))
return name;
},
- _add: function _add(names, description, action, extra, replace) {
+ _add: function _add(names, description, action, extra={}, replace=false) {
const { contexts } = this.modules;
-
- extra = extra || {};
extra.definedAt = contexts.getCaller(Components.stack.caller.caller);
return this.add.apply(this, arguments);
},
*/
get: function get(name, full) {
let cmd = this._map[name]
- || !full && array.nth(this._list, function (cmd) cmd.hasName(name), 0)
+ || !full && this._list.find(cmd => cmd.hasName(name))
|| null;
if (!cmd && full) {
- let name = array.nth(this.specs, function (spec) Command.hasName(spec, name), 0);
+ // Hrm. This is wrong. -Kris
+ let name = this._specs.find(spec => Command.hasName(spec, name));
return name && this.get(name);
}
util.assert(this.group.modifiable, _("command.cantDelete"));
let cmd = this.get(name);
- this._list = this._list.filter(function (c) c !== cmd);
+ this._list = this._list.filter(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),
+ get userHives() this.allHives.filter(h => h !== this.builtin),
/**
* Executes an Ex command script.
const { commandline, completion } = this.modules;
function completerToString(completer) {
if (completer)
- return [k for ([k, v] in Iterator(config.completers)) if (completer == completion.closure[v])][0] || "custom";
+ return [k for ([k, v] in Iterator(config.completers)) if (completer == completion.bound[v])][0] || "custom";
return "";
}
// TODO: allow matching of aliases?
- function cmds(hive) hive._list.filter(function (cmd) cmd.name.indexOf(filter || "") == 0)
+ function cmds(hive) hive._list.filter(cmd => cmd.name.startsWith(filter || ""))
- let hives = (hives || this.userHives).map(function (h) [h, cmds(h)]).filter(function ([h, c]) c.length);
+ let hives = (hives || this.userHives).map(h => [h, cmds(h)])
+ .filter(([h, c]) => c.length);
let list = ["table", {},
["tr", { highlight: "Title" },
["td", { style: "padding-right: 1ex;" }, _("title.Complete")],
["td", { style: "padding-right: 1ex;" }, _("title.Definition")]],
["col", { style: "min-width: 6em; padding-right: 1em;" }],
- hives.map(function ([hive, cmds]) let (i = 0) [
+ hives.map(([hive, cmds]) => let (i = 0) [
["tr", { style: "height: .5ex;" }],
- cmds.map(function (cmd)
+ cmds.map(cmd =>
["tr", {},
["td", { highlight: "Title" }, !i++ ? hive.name : ""],
["td", {}, cmd.bang ? "!" : " "],
/** @property {Iterator(Command)} @private */
iterator: function iterator() iter.apply(null, this.hives.array)
- .sort(function (a, b) a.serialGroup - b.serialGroup || a.name > b.name)
+ .sort((a, b) => (a.serialGroup - b.serialGroup ||
+ a.name > b.name))
.iterValues(),
/** @property {string} The last executed Ex command line. */
return group._add.apply(group, arguments);
},
- addUserCommand: deprecated("group.commands.add", { get: function addUserCommand() this.user.closure._add }),
+ addUserCommand: deprecated("group.commands.add", { get: function addUserCommand() this.user.bound._add }),
getUserCommands: deprecated("iter(group.commands)", function getUserCommands() iter(this.user).toArray()),
- removeUserCommand: deprecated("group.commands.remove", { get: function removeUserCommand() this.user.closure.remove }),
+ removeUserCommand: deprecated("group.commands.remove", { get: function removeUserCommand() this.user.bound.remove }),
/**
* Returns the specified command invocation object serialized to
let defaults = {};
if (args.ignoreDefaults)
- defaults = array(this.options).map(function (opt) [opt.names[0], opt.default])
+ defaults = array(this.options).map(opt => [opt.names[0], opt.default])
.toObject();
for (let [opt, val] in Iterator(args.options || {})) {
* any of the command's names.
* @returns {Command}
*/
- get: function get(name, full) iter(this.hives).map(function ([i, hive]) hive.get(name, full))
- .nth(util.identity, 0),
+ get: function get(name, full) iter(this.hives).map(([i, hive]) => hive.get(name, full))
+ .find(util.identity),
/**
* Returns true if a command invocation contains a URL referring to the
hasDomain: function hasDomain(command, host) {
try {
for (let [cmd, args] in this.subCommands(command))
- if (Array.concat(cmd.domains(args)).some(function (domain) util.isSubdomain(domain, host)))
+ if (Array.concat(cmd.domains(args)).some(domain => util.isSubdomain(domain, host)))
return true;
}
catch (e) {
* Args object.
* @returns {Args}
*/
- parseArgs: function parseArgs(str, params) {
+ parseArgs: function parseArgs(str, params={}) {
const self = this;
- function getNextArg(str, _keepQuotes) {
- if (arguments.length < 2)
- _keepQuotes = keepQuotes;
-
+ function getNextArg(str, _keepQuotes=keepQuotes) {
if (str.substr(0, 2) === "<<" && hereDoc) {
let arg = /^<<(\S*)/.exec(str)[1];
let count = arg.length + 2;
try {
- var { allowUnknownOptions, argCount, complete, extra, hereDoc, literal, options, keepQuotes } = params || {};
+ var { allowUnknownOptions, argCount, complete, extra, hereDoc, literal, options, keepQuotes } = params;
if (!options)
options = [];
let matchOpts = function matchOpts(arg) {
// Push possible option matches into completions
if (complete && !onlyArgumentsRemaining)
- completeOpts = options.filter(function (opt) opt.multiple || !Set.has(args, opt.names[0]));
+ completeOpts = options.filter(opt => (opt.multiple || !hasOwnProperty(args, opt.names[0])));
};
let resetCompletions = function resetCompletions() {
completeOpts = null;
if (!onlyArgumentsRemaining) {
for (let [, opt] in Iterator(options)) {
for (let [, optname] in Iterator(opt.names)) {
- if (sub.indexOf(optname) == 0) {
+ if (sub.startsWith(optname)) {
let count = 0;
let invalid = false;
let arg, quote, quoted;
if (arg == null || (typeof arg == "number" && isNaN(arg))) {
if (!complete || orig != "" || args.completeStart != str.length)
- fail(_("command.invalidOptTypeArg", opt.type.description, optname, argString));
+ fail(_("command.invalidOptTypeArg", opt.type.description, optname, quoted));
if (complete)
complete.highlight(args.completeStart, count - 1, "SPELLCHECK");
}
// we have a validator function
if (typeof opt.validator == "function") {
if (opt.validator(arg, quoted) == false && (arg || !complete)) {
- fail(_("command.invalidOptArg", optname, argString));
+ fail(_("command.invalidOptArg", optname, quoted));
if (complete) // Always true.
complete.highlight(args.completeStart, count - 1, "SPELLCHECK");
}
if (sub.substr(0, 2) === "<<" && hereDoc)
let ([count, arg] = getNextArg(sub)) {
sub = arg + sub.substr(count);
- }
+ };
args.push(sub);
args.quote = null;
context.filter = args.completeFilter;
if (isArray(arg))
- context.filters.push(function (item) arg.indexOf(item.text) === -1);
+ context.filters.push(item => arg.indexOf(item.text) === -1);
if (typeof opt.completer == "function")
var compl = opt.completer(context, args);
let quote = null;
let len = str.length;
- function fixEscapes(str) str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}|(.))/g, function (m, n1) n1 || m);
+ function fixEscapes(str) str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}|(.))/g,
+ (m, n1) => n1 || m);
// Fix me.
if (isString(sep))
context.title = ["Command"];
context.keys = { text: "longNames", description: "description" };
if (group)
- context.generate = function () group._list;
+ context.generate = () => group._list;
else
- context.generate = function () modules.commands.hives.map(function (h) h._list).flatten();
+ context.generate = () => modules.commands.hives.map(h => h._list).flatten();
};
// provides completions for ex commands, including their arguments
function (args) {
let cmd = args[0];
- util.assert(!cmd || cmd.split(",").every(commands.validName.closure.test),
+ util.assert(!cmd || cmd.split(",").every(commands.validName.bound.test),
_("command.invalidName", cmd));
if (args.length <= 1)
return dactyl.userEval(completer);
});
if (callable(result))
- return result.apply(this, Array.slice(arguments));
+ return result.apply(this, arguments);
else
return context.completions = result;
};
}
else
- completerFunc = function (context) modules.completion.closure[config.completers[completer]](context);
+ completerFunc = context => modules.completion.bound[config.completers[completer]](context);
}
let added = args["-group"].add(cmd.split(","),
literal: 1,
serialize: function () array(commands.userHives)
- .filter(function (h) h.persist)
- .map(function (hive) [
+ .filter(h => h.persist)
+ .map(hive => [
{
command: this.name,
bang: true,
ignoreDefaults: true
}
for (cmd in hive) if (cmd.persist)
- ], this)
+ ])
.flatten().array
});
]
})),
iterateIndex: function (args) let (tags = help.tags)
- this.iterate(args).filter(function (cmd) cmd.hive === commands.builtin || Set.has(tags, cmd.helpTag)),
+ this.iterate(args).filter(cmd => (cmd.hive === commands.builtin || hasOwnProperty(tags, cmd.helpTag))),
format: {
headings: ["Command", "Group", "Description"],
description: function (cmd) template.linkifyHelp(cmd.description + (cmd.replacementText ? ": " + cmd.action : "")),
mappings.add([modes.COMMAND],
["@:"], "Repeat the last Ex command",
- function (args) {
+ function ({ count }) {
if (commands.repeat) {
- for (let i in util.interruptibleRange(0, Math.max(args.count, 1), 100))
+ for (let i in util.interruptibleRange(0, Math.max(count, 1), 100))
dactyl.execute(commands.repeat);
}
else
}
});
-let quote = function quote(q, list, map) {
- map = map || Commands.quoteMap;
+let quote = function quote(q, list, map=Commands.quoteMap) {
let re = RegExp("[" + list + "]", "g");
- function quote(str) q + String.replace(str, re, function ($0) $0 in map ? map[$0] : ("\\" + $0)) + q;
+ function quote(str) (q + String.replace(str, re, $0 => ($0 in map ? map[$0] : ("\\" + $0)))
+ + q);
quote.list = list;
return quote;
};
Commands.quoteMap = {
"\n": "\\n",
- "\t": "\\t",
+ "\t": "\\t"
};
Commands.quoteArg = {
} 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:
+// vim: set fdm=marker sw=4 sts=4 ts=8 et ft=javascript: