1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2026-01-03 12:34:16 +01:00

Better list option parsing and serialization.

This commit is contained in:
Kris Maglione
2010-09-24 15:24:21 -04:00
parent fa20629524
commit 0753c9505e
8 changed files with 121 additions and 66 deletions

View File

@@ -50,8 +50,11 @@ const Option = Class("Option", {
this._op = Option.ops[this.type];
if (arguments.length > 3)
this.defaultValue = defaultValue;
if (arguments.length > 3) {
if (this.type == "string")
defaultValue = Commands.quote(defaultValue);
this.defaultValue = this.joinValues(this.parseValues(defaultValue));
}
if (extraInfo)
update(this, extraInfo);
@@ -75,7 +78,7 @@ const Option = Class("Option", {
* @param {value} value The option value.
* @returns {value|string[]}
*/
parseValues: function (value) value,
parseValues: function (value) Option.dequote(value),
/**
* Returns <b>values</b> packed in the appropriate format for the option
@@ -84,7 +87,7 @@ const Option = Class("Option", {
* @param {value|string[]} values The option value.
* @returns {value}
*/
joinValues: function (vals) vals,
joinValues: function (vals) Commands.quote(vals),
/** @property {value|string[]} The option value or array of values. */
get values() this.getValues(this.scope),
@@ -376,8 +379,8 @@ const Option = Class("Option", {
re.toString = function () Option.unparseRegex(this);
return re;
},
unparseRegex: function (re) re.bang + re.source.replace(/\\(.)/g, function (m, n1) n1 == "/" ? n1 : m) +
(typeof re.result == "string" ? ":" + re.result : ""),
unparseRegex: function (re) re.bang + Option.quote(re.source.replace(/\\(.)/g, function (m, n1) n1 == "/" ? n1 : m)) +
(typeof re.result == "string" ? ":" + Option.quote(re.result) : ""),
getKey: {
stringlist: function (k) this.values.indexOf(k) >= 0,
@@ -393,24 +396,46 @@ const Option = Class("Option", {
},
joinValues: {
charlist: function (vals) vals.join(""),
stringlist: function (vals) vals.join(","),
stringmap: function (vals) [k + ":" + v for ([k, v] in Iterator(vals))].join(","),
regexlist: function (vals) vals.map(Option.unparseRegex).join(","),
charlist: function (vals) Commands.quote(vals.join("")),
stringlist: function (vals) vals.map(Option.quote).join(","),
stringmap: function (vals) [Option.quote(k) + ":" + Option.quote(v) for ([k, v] in Iterator(vals))].join(","),
regexlist: function (vals) vals.join(","),
get regexmap() this.regexlist
},
parseValues: {
number: function (value) Number(value),
boolean: function (value) value == "true" || value == true ? true : false,
charlist: function (value) Array.slice(value),
stringlist: function (value) (value === "") ? [] : value.split(","),
stringmap: function (value) array(util.split(v, /:/g, 2) for (v in values(value.split(",")))).toObject(),
regexlist: function (value) (value === "") ? [] : value.split(",").map(Option.parseRegex),
regexmap: function (value) value.split(",").map(function (v) util.split(v, /:/g, 2))
.map(function ([k, v]) v != null ? Option.parseRegex(k, v) : Option.parseRegex(".?", k))
number: function (value) Number(Option.dequote(value)),
boolean: function (value) Option.dequote(value) == "true" || value == true ? true : false,
charlist: function (value) Array.slice(Option.dequote(value)),
stringlist: function (value) (value === "") ? [] : Option.splitList(value),
stringmap: function (value) array(util.split(v, /:/g, 2) for (v in values(Option.splitList(value)))).toObject(),
regexlist: function (value) (value === "") ? [] : Option.splitList(value).map(Option.parseRegex),
regexmap: function (value) Option.splitList(value)
.map(function (v) util.split(v, /:/g, 2))
.map(function ([k, v]) v != null ? Option.parseRegex(k, v) : Option.parseRegex(".?", k))
},
dequote: function (value) {
let arg;
[, arg, Option._quote] = Commands.parseArg(String(value), "");
Option._splitAt = 0;
return arg;
},
splitList: function (value) {
let res = [];
Option._splitAt = 0;
do {
if (count !== undefined)
Option._splitAt += count + 1;
var [count, arg, quote] = Commands.parseArg(value, /,/);
Option._quote = quote; // FIXME
res.push(arg);
value = value.slice(count + 1);
} while (value.length);
return res;
},
quote: function quote(str) Commands.quoteArg[/[\s"'\\,]|^$/.test(str) ? "'" : ""](str),
ops: {
boolean: function (operator, values, scope, invert) {
if (operator != "=")
@@ -640,7 +665,7 @@ const Options = Module("options", {
if (!scope)
scope = Option.SCOPE_BOTH;
if (name in this._optionMap && (this._optionMap[name].scope & scope))
if (this._optionMap[name] && (this._optionMap[name].scope & scope))
return this._optionMap[name];
return null;
},
@@ -661,7 +686,7 @@ const Options = Module("options", {
function opts(opt) {
for (let opt in Iterator(options)) {
let option = {
isDefault: opt.value == opt.defaultValue,
isDefault: opt.value === opt.defaultValue,
name: opt.name,
default: opt.defaultValue,
pre: "\u00a0\u00a0", // Unicode nonbreaking space.
@@ -1261,8 +1286,8 @@ const Options = Module("options", {
serialize: function () [
{
command: this.name,
arguments: [opt.type == "boolean" ? (opt.value ? "" : "no") + opt.name
: opt.name + "=" + opt.value]
literalArg: [opt.type == "boolean" ? (opt.value ? "" : "no") + opt.name
: opt.name + "=" + opt.value]
}
for (opt in options)
if (!opt.getter && opt.value != opt.defaultValue && (opt.scope & Option.SCOPE_GLOBAL))
@@ -1276,6 +1301,9 @@ const Options = Module("options", {
},
update({
bang: true,
completer: function (context, args) {
return setCompleter(context, args);
},
domains: function (args) array.flatten(args.map(function (spec) {
try {
let opt = options.parseOpt(spec);
@@ -1287,9 +1315,7 @@ const Options = Module("options", {
}
return [];
})),
completer: function (context, args) {
return setCompleter(context, args);
},
keepQuotes: true,
privateData: function (args) args.some(function (spec) {
let opt = options.parseOpt(spec);
return opt.option && opt.option.privateData &&
@@ -1347,33 +1373,30 @@ const Options = Module("options", {
return;
}
let len = context.filter.length;
switch (opt.type) {
case "boolean":
if (!completer)
completer = function () [["true", ""], ["false", ""]];
break;
case "regexlist":
newValues = context.filter.split(",");
newValues = Option.splitList(context.filter);
// Fallthrough
case "stringlist":
let target = newValues.pop() || "";
len = target.length;
var target = newValues.pop() || "";
break;
case "stringmap":
case "regexmap":
let vals = context.filter.split(",");
let vals = Option.splitList(context.filter);
target = vals.pop() || "";
len = target.length - (target.indexOf(":") + 1);
break;
case "charlist":
len = 0;
Option._splitAt += target.indexOf(":") ? target.indexOf(":") + 1 : 0;
break;
}
// TODO: Highlight when invalid
context.advance(context.filter.length - len);
context.advance(Option._splitAt);
context.filter = target != null ? target : Option.dequote(context.filter);
context.title = ["Option Value"];
context.quote = Commands.complQuote[Option._quote] || Commands.complQuote[""]
// Not Vim compatible, but is a significant enough improvement
// that it's worth breaking compatibility.
if (isArray(newValues)) {