mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-20 10:17:59 +01:00
Deal with some duplicated code, plus some collateral optimization.
This commit is contained in:
@@ -258,6 +258,31 @@ const Command = Class("Command", {
|
|||||||
optionMap: Class.memoize(function () array(this.options)
|
optionMap: Class.memoize(function () array(this.options)
|
||||||
.map(function (opt) opt.names.map(function (name) [name, opt]))
|
.map(function (opt) opt.names.map(function (name) [name, opt]))
|
||||||
.flatten.toObject()),
|
.flatten.toObject()),
|
||||||
|
newArgs: function () {
|
||||||
|
let res = [];
|
||||||
|
res.__proto__ = this.argsPrototype;
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
argsPrototype: Class.memoize(function () update([],
|
||||||
|
array([opt, opt.default] for (opt in values(this.options)) if (set.has(opt, "default")))
|
||||||
|
.toObject(),
|
||||||
|
{
|
||||||
|
__iterator__: function () array.iterItems(this),
|
||||||
|
command: this,
|
||||||
|
get literalArg() this.command.literal != null && this[this.command.literal] || "",
|
||||||
|
// TODO: string: Class.memoize(function () { ... }),
|
||||||
|
verify: function verify() {
|
||||||
|
if (this.argCount) {
|
||||||
|
dactyl.assert((this.length > 0 || !/^[1+]$/.test(this.command.argCount)) &&
|
||||||
|
(this.literal == null || !/[1+]/.test(this.command.argCount) || /\S/.test(this.literalArg || "")),
|
||||||
|
"E471: Argument required");
|
||||||
|
|
||||||
|
dactyl.assert((this.length == 0 || this.command.argCount !== "0") &&
|
||||||
|
(this.length <= 1 || !/^[01?]$/.test(this.command.argCount)),
|
||||||
|
"E488: Trailing characters");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})),
|
||||||
/**
|
/**
|
||||||
* @property {boolean|function(args)} When true, invocations of this
|
* @property {boolean|function(args)} When true, invocations of this
|
||||||
* command may contain private data which should be purged from
|
* command may contain private data which should be purged from
|
||||||
@@ -355,35 +380,26 @@ const ex = {
|
|||||||
let cmd = commands.get(meth);
|
let cmd = commands.get(meth);
|
||||||
dactyl.assert(cmd, "No such command");
|
dactyl.assert(cmd, "No such command");
|
||||||
|
|
||||||
|
let res = cmd.newArgs();
|
||||||
if (isObject(args[0]))
|
if (isObject(args[0]))
|
||||||
for (let [k, v] in Iterator(args.shift()))
|
for (let [k, v] in Iterator(args.shift()))
|
||||||
if (k == "!")
|
if (k == "!")
|
||||||
args.bang = v;
|
res.bang = v;
|
||||||
else if (k == "#")
|
else if (k == "#")
|
||||||
args.count = v;
|
res.count = v;
|
||||||
else {
|
else {
|
||||||
let opt = cmd.optionMap["-" + k];
|
let opt = cmd.optionMap["-" + k];
|
||||||
let val = opt.type && opt.type.parse(v);
|
let val = opt.type && opt.type.parse(v);
|
||||||
dactyl.assert(val != null && (typeof val !== "number" || !isNaN(val)),
|
dactyl.assert(val != null && (typeof val !== "number" || !isNaN(val)),
|
||||||
"No such option: " + k);
|
"No such option: " + k);
|
||||||
args[opt.names[0]] = val;
|
res[opt.names[0]] = val;
|
||||||
}
|
}
|
||||||
if (cmd.literal != null)
|
for (let [i, val] in array.iterItems(args))
|
||||||
args.literalArg = args[cmd.literal];
|
res[i] = String(val);
|
||||||
|
|
||||||
// FIXME: Duplicated in parseArgs.
|
res.verify();
|
||||||
|
|
||||||
dactyl.assert((args.length > 0 || !/^[1+]$/.test(this.argCount)) &&
|
return cmd.execute(res);
|
||||||
(this.literal == null || !/[1+]/.test(this.argCount) || /\S/.test(args.literalArg || "")),
|
|
||||||
"E471: Argument required");
|
|
||||||
|
|
||||||
// This logic eludes me... --Kris
|
|
||||||
dactyl.assert((args.length == 0 || this.argCount !== "0") &&
|
|
||||||
(args.length <= 1 || !/^[01?]$/.test(this.argCount)),
|
|
||||||
"E488: Trailing characters");
|
|
||||||
|
|
||||||
// TODO: memoize(args, "string", function () { ... });
|
|
||||||
return cmd.execute(args);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -683,261 +699,253 @@ const Commands = Module("commands", {
|
|||||||
* @returns {Args}
|
* @returns {Args}
|
||||||
*/
|
*/
|
||||||
parseArgs: function (str, params) {
|
parseArgs: function (str, params) {
|
||||||
function getNextArg(str) {
|
try {
|
||||||
if (str.substr(0, 2) === "<<" && hereDoc) {
|
function getNextArg(str) {
|
||||||
let arg = /^<<(\S*)/.exec(str)[1];
|
if (str.substr(0, 2) === "<<" && hereDoc) {
|
||||||
let count = arg.length + 2;
|
let arg = /^<<(\S*)/.exec(str)[1];
|
||||||
if (complete)
|
let count = arg.length + 2;
|
||||||
return [count, "", ""]
|
if (complete)
|
||||||
return [count, io.readHeredoc(arg), ""];
|
return [count, "", ""]
|
||||||
|
return [count, io.readHeredoc(arg), ""];
|
||||||
|
}
|
||||||
|
let [count, arg, quote] = Commands.parseArg(str, null, keepQuotes);
|
||||||
|
if (quote == "\\" && !complete)
|
||||||
|
return [,,,"Trailing \\"];
|
||||||
|
if (quote && !complete)
|
||||||
|
return [,,,"E114: Missing quote: " + quote];
|
||||||
|
return [count, arg, quote];
|
||||||
}
|
}
|
||||||
let [count, arg, quote] = Commands.parseArg(str, null, keepQuotes);
|
|
||||||
if (quote == "\\" && !complete)
|
|
||||||
return [,,,"Trailing \\"];
|
|
||||||
if (quote && !complete)
|
|
||||||
return [,,,"E114: Missing quote: " + quote];
|
|
||||||
return [count, arg, quote];
|
|
||||||
}
|
|
||||||
|
|
||||||
var { allowUnknownOptions, argCount, complete, extra, hereDoc, literal, options, keepQuotes } = params || {};
|
var { allowUnknownOptions, argCount, complete, extra, hereDoc, literal, options, keepQuotes } = params || {};
|
||||||
|
|
||||||
if (!options)
|
if (!options)
|
||||||
options = [];
|
options = [];
|
||||||
|
|
||||||
if (!argCount)
|
if (!argCount)
|
||||||
argCount = "*";
|
argCount = "*";
|
||||||
|
|
||||||
var args = []; // parsed options
|
var args = (params.newArgs || Array).call(params); // parsed options
|
||||||
args.__iterator__ = function () array.iterItems(this);
|
args.string = str; // for access to the unparsed string
|
||||||
args.string = str; // for access to the unparsed string
|
|
||||||
args.literalArg = "";
|
|
||||||
|
|
||||||
// FIXME!
|
// FIXME!
|
||||||
for (let [k, v] in Iterator(extra || []))
|
for (let [k, v] in Iterator(extra || []))
|
||||||
args[k] = v;
|
args[k] = v;
|
||||||
|
|
||||||
var invalid = false;
|
var invalid = false;
|
||||||
// FIXME: best way to specify these requirements?
|
// FIXME: best way to specify these requirements?
|
||||||
var onlyArgumentsRemaining = allowUnknownOptions || options.length == 0; // after a -- has been found
|
var onlyArgumentsRemaining = allowUnknownOptions || options.length == 0; // after a -- has been found
|
||||||
var arg = null;
|
var arg = null;
|
||||||
var count = 0; // the length of the argument
|
var count = 0; // the length of the argument
|
||||||
var i = 0;
|
var i = 0;
|
||||||
var completeOpts;
|
var completeOpts;
|
||||||
|
|
||||||
// XXX
|
// XXX
|
||||||
function matchOpts(arg) {
|
function matchOpts(arg) {
|
||||||
// Push possible option matches into completions
|
// Push possible option matches into completions
|
||||||
if (complete && !onlyArgumentsRemaining)
|
if (complete && !onlyArgumentsRemaining)
|
||||||
completeOpts = options.filter(function (opt) opt.multiple || !(opt.names[0] in args));
|
completeOpts = options.filter(function (opt) opt.multiple || !(opt.names[0] in args));
|
||||||
}
|
|
||||||
function resetCompletions() {
|
|
||||||
completeOpts = null;
|
|
||||||
args.completeArg = null;
|
|
||||||
args.completeOpt = null;
|
|
||||||
args.completeFilter = null;
|
|
||||||
args.completeStart = i;
|
|
||||||
args.quote = Commands.complQuote[""];
|
|
||||||
}
|
|
||||||
if (complete) {
|
|
||||||
resetCompletions();
|
|
||||||
matchOpts("");
|
|
||||||
args.completeArg = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function fail(error) {
|
|
||||||
if (complete)
|
|
||||||
complete.message = error;
|
|
||||||
else
|
|
||||||
dactyl.assert(false, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
outer:
|
|
||||||
while (i < str.length || complete) {
|
|
||||||
var argStart = i;
|
|
||||||
let re = /\s*/gy;
|
|
||||||
re.lastIndex = i;
|
|
||||||
i += re.exec(str)[0].length;
|
|
||||||
|
|
||||||
if (str[i] == "|") {
|
|
||||||
args.string = str.slice(0, i);
|
|
||||||
args.trailing = str.slice(i + 1);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (i == str.length && !complete)
|
function resetCompletions() {
|
||||||
break;
|
completeOpts = null;
|
||||||
|
args.completeArg = null;
|
||||||
if (complete)
|
args.completeOpt = null;
|
||||||
|
args.completeFilter = null;
|
||||||
|
args.completeStart = i;
|
||||||
|
args.quote = Commands.complQuote[""];
|
||||||
|
}
|
||||||
|
if (complete) {
|
||||||
resetCompletions();
|
resetCompletions();
|
||||||
|
matchOpts("");
|
||||||
var sub = str.substr(i);
|
args.completeArg = 0;
|
||||||
if ((!onlyArgumentsRemaining) && /^--(\s|$)/.test(sub)) {
|
|
||||||
onlyArgumentsRemaining = true;
|
|
||||||
i += 2;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var optname = "";
|
function fail(error) {
|
||||||
if (!onlyArgumentsRemaining) {
|
if (complete)
|
||||||
for (let [, opt] in Iterator(options)) {
|
complete.message = error;
|
||||||
for (let [, optname] in Iterator(opt.names)) {
|
else
|
||||||
if (sub.indexOf(optname) == 0) {
|
dactyl.assert(false, error);
|
||||||
invalid = false;
|
}
|
||||||
arg = null;
|
|
||||||
quote = null;
|
|
||||||
count = 0;
|
|
||||||
let sep = sub[optname.length];
|
|
||||||
if (sep == "=" || /\s/.test(sep) && opt.type != CommandOption.NOARG) {
|
|
||||||
[count, arg, quote, error] = getNextArg(sub.substr(optname.length + 1));
|
|
||||||
dactyl.assert(!error, error);
|
|
||||||
|
|
||||||
// if we add the argument to an option after a space, it MUST not be empty
|
outer:
|
||||||
if (sep != "=" && !quote && arg.length == 0)
|
while (i < str.length || complete) {
|
||||||
arg = null;
|
var argStart = i;
|
||||||
|
let re = /\s*/gy;
|
||||||
|
re.lastIndex = i;
|
||||||
|
i += re.exec(str)[0].length;
|
||||||
|
|
||||||
count++; // to compensate the "=" character
|
if (str[i] == "|") {
|
||||||
}
|
args.string = str.slice(0, i);
|
||||||
else if (!/\s/.test(sep) && sep != undefined) // this isn't really an option as it has trailing characters, parse it as an argument
|
args.trailing = str.slice(i + 1);
|
||||||
invalid = true;
|
break;
|
||||||
|
}
|
||||||
|
if (i == str.length && !complete)
|
||||||
|
break;
|
||||||
|
|
||||||
if (complete && !/[\s=]/.test(sep))
|
if (complete)
|
||||||
matchOpts(sub);
|
resetCompletions();
|
||||||
|
|
||||||
let context = null;
|
var sub = str.substr(i);
|
||||||
if (!complete && quote)
|
if ((!onlyArgumentsRemaining) && /^--(\s|$)/.test(sub)) {
|
||||||
fail("Invalid argument for option " + optname);
|
onlyArgumentsRemaining = true;
|
||||||
|
i += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!invalid) {
|
var optname = "";
|
||||||
if (complete && count > 0) {
|
if (!onlyArgumentsRemaining) {
|
||||||
args.completeStart += optname.length + 1;
|
for (let [, opt] in Iterator(options)) {
|
||||||
args.completeOpt = opt;
|
for (let [, optname] in Iterator(opt.names)) {
|
||||||
args.completeFilter = arg;
|
if (sub.indexOf(optname) == 0) {
|
||||||
args.quote = Commands.complQuote[quote] || Commands.complQuote[""];
|
invalid = false;
|
||||||
|
arg = null;
|
||||||
|
quote = null;
|
||||||
|
count = 0;
|
||||||
|
let sep = sub[optname.length];
|
||||||
|
if (sep == "=" || /\s/.test(sep) && opt.type != CommandOption.NOARG) {
|
||||||
|
[count, arg, quote, error] = getNextArg(sub.substr(optname.length + 1));
|
||||||
|
dactyl.assert(!error, error);
|
||||||
|
|
||||||
|
// if we add the argument to an option after a space, it MUST not be empty
|
||||||
|
if (sep != "=" && !quote && arg.length == 0)
|
||||||
|
arg = null;
|
||||||
|
|
||||||
|
count++; // to compensate the "=" character
|
||||||
}
|
}
|
||||||
if (!complete || arg != null) {
|
else if (!/\s/.test(sep) && sep != undefined) // this isn't really an option as it has trailing characters, parse it as an argument
|
||||||
if (opt.type) {
|
invalid = true;
|
||||||
let orig = arg;
|
|
||||||
arg = opt.type.parse(arg);
|
if (complete && !/[\s=]/.test(sep))
|
||||||
if (arg == null || (typeof arg == "number" && isNaN(arg))) {
|
matchOpts(sub);
|
||||||
if (!complete || orig != "" || args.completeStart != str.length)
|
|
||||||
fail("Invalid argument for " + opt.type.description + " option: " + optname);
|
let context = null;
|
||||||
if (complete)
|
if (!complete && quote)
|
||||||
complete.highlight(args.completeStart, count - 1, "SPELLCHECK");
|
fail("Invalid argument for option " + optname);
|
||||||
|
|
||||||
|
if (!invalid) {
|
||||||
|
if (complete && count > 0) {
|
||||||
|
args.completeStart += optname.length + 1;
|
||||||
|
args.completeOpt = opt;
|
||||||
|
args.completeFilter = arg;
|
||||||
|
args.quote = Commands.complQuote[quote] || Commands.complQuote[""];
|
||||||
|
}
|
||||||
|
if (!complete || arg != null) {
|
||||||
|
if (opt.type) {
|
||||||
|
let orig = arg;
|
||||||
|
arg = opt.type.parse(arg);
|
||||||
|
if (arg == null || (typeof arg == "number" && isNaN(arg))) {
|
||||||
|
if (!complete || orig != "" || args.completeStart != str.length)
|
||||||
|
fail("Invalid argument for " + opt.type.description + " option: " + optname);
|
||||||
|
if (complete)
|
||||||
|
complete.highlight(args.completeStart, count - 1, "SPELLCHECK");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we have a validator function
|
||||||
|
if (typeof opt.validator == "function") {
|
||||||
|
if (opt.validator.call(this, arg) == false) {
|
||||||
|
fail("Invalid argument for option: " + optname);
|
||||||
|
if (complete) // Always true.
|
||||||
|
complete.highlight(args.completeStart, count - 1, "SPELLCHECK");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// we have a validator function
|
// option allowed multiple times
|
||||||
if (typeof opt.validator == "function") {
|
if (opt.multiple)
|
||||||
if (opt.validator.call(this, arg) == false) {
|
args[opt.names[0]] = (args[opt.names[0]] || []).concat(arg);
|
||||||
fail("Invalid argument for option: " + optname);
|
else
|
||||||
if (complete) // Always true.
|
args[opt.names[0]] = opt.type == CommandOption.NOARG || arg;
|
||||||
complete.highlight(args.completeStart, count - 1, "SPELLCHECK");
|
|
||||||
}
|
i += optname.length + count;
|
||||||
}
|
if (i == str.length)
|
||||||
|
break outer;
|
||||||
|
continue outer;
|
||||||
}
|
}
|
||||||
|
// if it is invalid, just fall through and try the next argument
|
||||||
// option allowed multiple times
|
|
||||||
if (opt.multiple)
|
|
||||||
args[opt.names[0]] = (args[opt.names[0]] || []).concat(arg);
|
|
||||||
else
|
|
||||||
args[opt.names[0]] = opt.type == CommandOption.NOARG || arg;
|
|
||||||
|
|
||||||
i += optname.length + count;
|
|
||||||
if (i == str.length)
|
|
||||||
break outer;
|
|
||||||
continue outer;
|
|
||||||
}
|
}
|
||||||
// if it is invalid, just fall through and try the next argument
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
matchOpts(sub);
|
matchOpts(sub);
|
||||||
|
|
||||||
if (complete) {
|
if (complete) {
|
||||||
if (argCount == "0" || args.length > 0 && (/[1?]/.test(argCount)))
|
if (argCount == "0" || args.length > 0 && (/[1?]/.test(argCount)))
|
||||||
complete.highlight(i, sub.length, "SPELLCHECK");
|
complete.highlight(i, sub.length, "SPELLCHECK");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.length === literal) {
|
if (args.length === literal) {
|
||||||
|
if (complete)
|
||||||
|
args.completeArg = args.length;
|
||||||
|
|
||||||
|
let re = /(?:\s*(?=\n)|\s*)([^]*)/gy;
|
||||||
|
re.lastIndex = argStart || 0;
|
||||||
|
sub = re.exec(str)[1];
|
||||||
|
|
||||||
|
// Hack.
|
||||||
|
if (sub.substr(0, 2) === "<<" && hereDoc)
|
||||||
|
let ([count, arg] = getNextArg(sub)) {
|
||||||
|
sub = arg + sub.substr(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
args.push(sub);
|
||||||
|
args.quote = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if not an option, treat this token as an argument
|
||||||
|
let [count, arg, quote, error] = getNextArg(sub);
|
||||||
|
dactyl.assert(!error, error);
|
||||||
|
|
||||||
|
if (complete) {
|
||||||
|
args.quote = Commands.complQuote[quote] || Commands.complQuote[""];
|
||||||
|
args.completeFilter = arg || "";
|
||||||
|
}
|
||||||
|
else if (count == -1)
|
||||||
|
fail("Error parsing arguments: " + arg);
|
||||||
|
else if (!onlyArgumentsRemaining && /^-/.test(arg))
|
||||||
|
fail("Invalid option: " + arg);
|
||||||
|
|
||||||
|
if (arg != null)
|
||||||
|
args.push(arg);
|
||||||
if (complete)
|
if (complete)
|
||||||
args.completeArg = args.length;
|
args.completeArg = args.length - 1;
|
||||||
|
|
||||||
let re = /(?:\s*(?=\n)|\s*)([^]*)/gy;
|
i += count;
|
||||||
re.lastIndex = argStart || 0;
|
if (count <= 0 || i == str.length)
|
||||||
sub = re.exec(str)[1];
|
break;
|
||||||
|
|
||||||
// Hack.
|
|
||||||
if (sub.substr(0, 2) === "<<" && hereDoc)
|
|
||||||
let ([count, arg] = getNextArg(sub)) {
|
|
||||||
sub = arg + sub.substr(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
args.literalArg = sub;
|
|
||||||
args.push(sub);
|
|
||||||
args.quote = null;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if not an option, treat this token as an argument
|
if (complete && args.trailing == null) {
|
||||||
let [count, arg, quote, error] = getNextArg(sub);
|
if (args.completeOpt) {
|
||||||
dactyl.assert(!error, error);
|
let opt = args.completeOpt;
|
||||||
|
let context = complete.fork(opt.names[0], args.completeStart);
|
||||||
if (complete) {
|
context.filter = args.completeFilter;
|
||||||
args.quote = Commands.complQuote[quote] || Commands.complQuote[""];
|
if (typeof opt.completer == "function")
|
||||||
args.completeFilter = arg || "";
|
var compl = opt.completer(context, args);
|
||||||
|
else
|
||||||
|
compl = opt.completer || [];
|
||||||
|
context.title = [opt.names[0]];
|
||||||
|
context.quote = args.quote;
|
||||||
|
if (compl)
|
||||||
|
context.completions = compl;
|
||||||
|
}
|
||||||
|
complete.advance(args.completeStart);
|
||||||
|
complete.keys = { text: "names", description: "description" };
|
||||||
|
complete.title = ["Options"];
|
||||||
|
if (completeOpts)
|
||||||
|
complete.completions = completeOpts;
|
||||||
}
|
}
|
||||||
else if (count == -1)
|
|
||||||
fail("Error parsing arguments: " + arg);
|
|
||||||
else if (!onlyArgumentsRemaining && /^-/.test(arg))
|
|
||||||
fail("Invalid option: " + arg);
|
|
||||||
|
|
||||||
if (arg != null)
|
if (args.verify)
|
||||||
args.push(arg);
|
args.verify();
|
||||||
if (complete)
|
|
||||||
args.completeArg = args.length - 1;
|
|
||||||
|
|
||||||
i += count;
|
return args;
|
||||||
if (count <= 0 || i == str.length)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
catch (e if complete && e instanceof FailedAssertion) {
|
||||||
if (complete && args.trailing == null) {
|
complete.message = e;
|
||||||
if (args.completeOpt) {
|
return args;
|
||||||
let opt = args.completeOpt;
|
|
||||||
let context = complete.fork(opt.names[0], args.completeStart);
|
|
||||||
context.filter = args.completeFilter;
|
|
||||||
if (typeof opt.completer == "function")
|
|
||||||
var compl = opt.completer(context, args);
|
|
||||||
else
|
|
||||||
compl = opt.completer || [];
|
|
||||||
context.title = [opt.names[0]];
|
|
||||||
context.quote = args.quote;
|
|
||||||
if (compl)
|
|
||||||
context.completions = compl;
|
|
||||||
}
|
|
||||||
complete.advance(args.completeStart);
|
|
||||||
complete.keys = { text: "names", description: "description" };
|
|
||||||
complete.title = ["Options"];
|
|
||||||
if (completeOpts)
|
|
||||||
complete.completions = completeOpts;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for correct number of arguments
|
|
||||||
if (args.length == 0 && /^[1+]$/.test(argCount) ||
|
|
||||||
literal != null && /[1+]/.test(argCount) && !/\S/.test(args.literalArg || "")) {
|
|
||||||
if (!complete)
|
|
||||||
fail("E471: Argument required");
|
|
||||||
}
|
|
||||||
else if (args.length == 1 && (argCount == "0") ||
|
|
||||||
args.length > 1 && /^[01?]$/.test(argCount))
|
|
||||||
fail("E488: Trailing characters");
|
|
||||||
|
|
||||||
for (let opt in values(options))
|
|
||||||
if (set.has(opt, "default") && args[opt.names[0]] === undefined)
|
|
||||||
args[opt.names[0]] = opt.default;
|
|
||||||
|
|
||||||
return args;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -528,6 +528,8 @@ function memoize(obj, key, getter) {
|
|||||||
obj.__defineGetter__(key, function replace() (
|
obj.__defineGetter__(key, function replace() (
|
||||||
Class.replaceProperty(this.instance || this, key, null),
|
Class.replaceProperty(this.instance || this, key, null),
|
||||||
Class.replaceProperty(this.instance || this, key, getter.call(this, key))));
|
Class.replaceProperty(this.instance || this, key, getter.call(this, key))));
|
||||||
|
obj.__defineSetter__(key, function replace(val)
|
||||||
|
Class.replaceProperty(this.instance || this, key, val));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user