1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-20 15:07:57 +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

@@ -189,7 +189,15 @@ const Command = Class("Command", {
* @returns {Args}
* @see Commands#parseArgs
*/
parseArgs: function (args, complete, extra) commands.parseArgs(args, this.options, this.argCount, false, this.literal, complete, extra),
parseArgs: function (args, complete, extra) commands.parseArgs(args, {
allowUnknownOptions: !!this.allowUnknownOptions,
argCount: this.argCount,
complete: complete,
extra: extra,
keepQuotes: !!this.keepQuotes,
literal: this.literal,
options: this.options
}),
/**
* @property {string[]} All of this command's name specs. e.g., "com[mand]"
@@ -405,16 +413,15 @@ const Commands = Module("commands", {
*/
commandToString: function (args) {
let res = [args.command + (args.bang ? "!" : "")];
function quote(str) Commands.quoteArg[/[\s"'\\]|^$/.test(str) ? "'" : ""](str);
for (let [opt, val] in Iterator(args.options || {})) {
let chr = /^-.$/.test(opt) ? " " : "=";
if (val != null)
opt += chr + quote(val);
opt += chr + Commands.quote(val);
res.push(opt);
}
for (let [, arg] in Iterator(args.arguments || []))
res.push(quote(arg));
res.push(Commands.quote(arg));
let str = args.literalArg;
if (str)
@@ -556,7 +563,7 @@ const Commands = Module("commands", {
*/
parseArgs: function (str, options, argCount, allowUnknownOptions, literal, complete, extra) {
function getNextArg(str) {
let [count, arg, quote] = Commands.parseArg(str);
let [count, arg, quote] = Commands.parseArg(str, null, keepQuotes);
if (quote == "\\" && !complete)
return [,,,"Trailing \\"];
if (quote && !complete)
@@ -564,6 +571,11 @@ const Commands = Module("commands", {
return [count, arg, quote];
}
let keepQuotes;
if (isObject(options))
({ allowUnknownOptions, argCount, complete, extra, literal, options, keepQuotes }) = options;
if (!options)
options = [];
@@ -581,7 +593,7 @@ const Commands = Module("commands", {
var invalid = false;
// FIXME: best way to specify these requirements?
var onlyArgumentsRemaining = allowUnknownOptions || options.length == 0 || false; // after a -- has been found
var onlyArgumentsRemaining = allowUnknownOptions || options.length == 0; // after a -- has been found
var arg = null;
var count = 0; // the length of the argument
var i = 0;
@@ -866,19 +878,26 @@ const Commands = Module("commands", {
}
}, {
// returns [count, parsed_argument]
parseArg: function (str) {
parseArg: function (str, sep, keepQuotes) {
let arg = "";
let quote = null;
let len = str.length;
while (str.length && !/^\s/.test(str)) {
// Fix me.
if (isString(sep))
sep = RegExp(sep);
sep = sep != null ? sep : /\s/;
let re1 = RegExp("^" + (sep.source === "" ? "(?!)" : sep.source));
let re2 = RegExp(/^()((?:[^\\S"']|\\.)+)((?:\\$)?)/.source.replace("S", sep.source));
while (str.length && !re1.test(str)) {
let res;
if ((res = str.match = str.match(/^()((?:[^\\\s"']|\\.)+)((?:\\$)?)/)))
arg += res[2].replace(/\\(.)/g, "$1");
else if ((res = str.match(/^(")((?:[^\\"]|\\.)*)("?)/)))
arg += eval(res[0] + (res[3] ? "" : '"'));
else if ((res = str.match(/^(')((?:[^']|'')*)('?)/)))
arg += res[2].replace("''", "'", "g");
if ((res = re2.exec(str)))
arg += keepQuotes ? res[0] : res[2].replace(/\\(.)/g, "$1");
else if ((res = /^(")((?:[^\\"]|\\.)*)("?)/.exec(str)))
arg += keepQuotes ? res[0] : eval(res[0] + (res[3] ? "" : '"'));
else if ((res = /^(')((?:[^']|'')*)('?)/.exec(str)))
arg += keepQuotes ? res[0] : res[2].replace("''", "'", "g");
else
break;
@@ -890,7 +909,9 @@ const Commands = Module("commands", {
}
return [len - str.length, arg, quote];
}
},
quote: function quote(str) Commands.quoteArg[/[\s"'\\]|^$/.test(str) ? "'" : ""](str)
}, {
completion: function () {
completion.command = function command(context) {
@@ -1155,8 +1176,9 @@ const Commands = Module("commands", {
(function () {
Commands.quoteMap = {
"\n": "n",
"\t": "t"
"\n": "\\n",
"\t": "\\t",
"'": "''"
};
function quote(q, list) {
let re = RegExp("[" + list + "]", "g");
@@ -1166,14 +1188,14 @@ const Commands = Module("commands", {
};
Commands.complQuote = {
'"': ['"', quote("", '\n\t"\\\\'), '"'],
"'": ["'", quote("", "\\\\'"), "'"],
"'": ["'", quote("", "'"), "'"],
"": ["", quote("", "\\\\ '\""), ""]
};
Commands.quoteArg = {
'"': quote('"', '\n\t"\\\\'),
"'": quote("'", "\\\\'"),
"": quote("", "\\\\ '\"")
"'": quote("'", "'"),
"": quote("", "\\\\\\s'\"")
};
Commands.parseBool = function (arg) {