1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-23 11:27:58 +01:00

Begining of parseArgs-based completion; only works for :style, for now. Should probably be made intrinsic.

This commit is contained in:
Kris Maglione
2008-11-20 23:13:01 +00:00
parent aa13986142
commit 00f4b80232
4 changed files with 95 additions and 38 deletions

View File

@@ -104,8 +104,6 @@ Command.prototype = {
let self = this; let self = this;
function parseArgs(args) commands.parseArgs(args, this.options, this.argCount, false, this.literal);
if (this.hereDoc) if (this.hereDoc)
{ {
let matches = args.match(/(.*)<<\s*(\S+)$/); let matches = args.match(/(.*)<<\s*(\S+)$/);
@@ -114,7 +112,7 @@ Command.prototype = {
commandline.inputMultiline(new RegExp("^" + matches[2] + "$", "m"), commandline.inputMultiline(new RegExp("^" + matches[2] + "$", "m"),
function (args) function (args)
{ {
args = parseArgs.call(self, matches[1] + "\n" + args); args = this.parseArgs(matches[1] + "\n" + args);
if (args) if (args)
self.action.call(self, args, special, count, modifiers); self.action.call(self, args, special, count, modifiers);
@@ -123,7 +121,7 @@ Command.prototype = {
} }
} }
args = parseArgs.call(this, args); args = this.parseArgs(args);
if (args) if (args)
this.action.call(this, args, special, count, modifiers); this.action.call(this, args, special, count, modifiers);
@@ -158,7 +156,9 @@ Command.prototype = {
} }
} }
return false; return false;
} },
parseArgs: function (args, complete) commands.parseArgs(args, this.options, this.argCount, false, this.literal, complete)
}; //}}} }; //}}}
@@ -186,7 +186,7 @@ function Commands() //{{{
function quote(q, list) function quote(q, list)
{ {
let re = RegExp("[" + list + "]", "g"); let re = RegExp("[" + list + "]", "g");
return function (str) q + str.replace(re, function ($0, $1) $1 in quoteMap ? quoteMap[$1] : "\\" + $1) + q; return function (str) q + String.replace(str, re, function ($0, $1) $1 in quoteMap ? quoteMap[$1] : "\\" + $1) + q;
} }
const quoteArg = { const quoteArg = {
'"': quote('"', '\n\t"\\\\'), '"': quote('"', '\n\t"\\\\'),
@@ -440,9 +440,38 @@ function Commands() //{{{
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;
// XXX
function matchOpts(arg)
{
// Push possible option matches into completions
if (!onlyArgumentsRemaining && !quote)
args.completions = [[opt[0][0], opt[0][0]] for ([i, opt] in Iterator(options)) if (opt[0][0].indexOf(arg) == 0)];
//args.completions = util.Array.flatten(
// options.map(function ([names]) names.filter(
// function (name) name.indexOf(arg) == 0)));
}
function resetCompletions()
{
args.completeArg = null;
args.completeOpt = null;
args.completeStart = i;
args.completions = [];
args.quote = quoteArg[""];
}
if (complete)
{
resetCompletions();
matchOpts("");
args.completeArg = 0;
}
outer: outer:
while (i < str.length) while (i < str.length)
{ {
if (complete)
resetCompletions();
// skip whitespace // skip whitespace
if (/\s/.test(str[i])) if (/\s/.test(str[i]))
{ {
@@ -471,6 +500,7 @@ function Commands() //{{{
invalid = false; invalid = false;
arg = null; arg = null;
quote = null; quote = null;
count = 0;
// no value to the option // no value to the option
if (optname.length >= sub.length) if (optname.length >= sub.length)
{ {
@@ -504,21 +534,28 @@ function Commands() //{{{
invalid = true; invalid = true;
} }
if (quote)
{
if (complete) if (complete)
{ {
args.completions = opt[3] || []; args.completeStart += optname.length + count;
if (typeof args.completions == "function") if (quote || !invalid && count)
args.completions = args.completions(); {
args.quote = quoteArg[sub[optname.length + 1]] || quoteArg[""]; args.completeOpt = opt[0][0];
args.quote = quoteArg[quote] || quoteArg[""];
if (typeof opt[3] == "function")
var compl = opt[3]();
else
compl = opt[3] || [];
args.completions = completion.filter(compl.map(function ([k, v]) [args.quote(k), v]), arg);;
return args; return args;
} }
}
else if (quote)
{
liberator.echoerr("Invalid argument for option " + optname); liberator.echoerr("Invalid argument for option " + optname);
return null; return null;
} }
if (!invalid) if (!invalid && (!complete || count))
{ {
let type = argTypes[opt[1]]; let type = argTypes[opt[1]];
if (type) if (type)
@@ -526,6 +563,9 @@ function Commands() //{{{
arg = type.parse(arg); arg = type.parse(arg);
if (arg == null || arg == NaN) if (arg == null || arg == NaN)
{ {
if (complete)
commandline.highlight(completions.completeStart, arg.length, "SPELLCHECK");
else
liberator.echoerr("Invalid argument for " + type.description + "option: " + optname); liberator.echoerr("Invalid argument for " + type.description + "option: " + optname);
return null; return null;
} }
@@ -536,6 +576,9 @@ function Commands() //{{{
{ {
if (opt[2].call(this, arg) == false) if (opt[2].call(this, arg) == false)
{ {
if (complete)
commandline.highlight(completions.completeStart, arg.length, "SPELLCHECK");
else
liberator.echoerr("Invalid argument for option: " + optname); liberator.echoerr("Invalid argument for option: " + optname);
return null; return null;
} }
@@ -555,12 +598,20 @@ function Commands() //{{{
{ {
args.literalArg = sub; args.literalArg = sub;
args.arguments.push(sub); args.arguments.push(sub);
if (complete)
args.completeArg = args.arguments.length;
break; break;
} }
// if not an option, treat this token as an argument // if not an option, treat this token as an argument
var [count, arg] = getNextArg(sub); var [count, arg, quote] = getNextArg(sub);
if (count == -1) if (complete)
{
args.quote = quoteArg[quote] || quoteArg[""];
args.completeArg = args.arguments.length;
matchOpts(arg);
}
else if (count == -1)
{ {
liberator.echoerr("Error parsing arguments: " + arg); liberator.echoerr("Error parsing arguments: " + arg);
return null; return null;
@@ -573,12 +624,16 @@ function Commands() //{{{
if (arg != null) if (arg != null)
args.arguments.push(arg); args.arguments.push(arg);
if (complete)
args.completeArg = args.arguments.length;
i += count; // hopefully count is always > 0, otherwise we get an endless loop if (count <= 0)
throw Error("count <= 0"); // Shouldn't happen.
i += count;
} }
// check for correct number of arguments // check for correct number of arguments
if (args.arguments.length == 0 && (argCount == "1" || argCount == "+")) if (args.arguments.length == 0 && (argCount == "1" || argCount == "+") && !complete)
{ {
liberator.echoerr("E471: Argument required"); liberator.echoerr("E471: Argument required");
return null; return null;
@@ -586,6 +641,7 @@ function Commands() //{{{
else if (args.arguments.length == 1 && (argCount == "0") || else if (args.arguments.length == 1 && (argCount == "0") ||
args.arguments.length > 1 && (argCount == "0" || argCount == "1" || argCount == "?")) args.arguments.length > 1 && (argCount == "0" || argCount == "1" || argCount == "?"))
{ {
if (!complete)
liberator.echoerr("E488: Trailing characters"); liberator.echoerr("E488: Trailing characters");
return null; return null;
} }
@@ -609,29 +665,26 @@ function Commands() //{{{
} }
// 0 - count, 1 - cmd, 2 - special, 3 - args, 4 - heredoc tag // 0 - count, 1 - cmd, 2 - special, 3 - args, 4 - heredoc tag
var matches = str.match(/^:*(\d+|%)?([a-zA-Z]+|!)(!)?(?:\s*(.*?)\s*)?$/); let matches = str.match(/^:*(\d+|%)?([a-zA-Z]+|!)(!)?(?:\s*(.*?))?$/);
//var matches = str.match(/^:*(\d+|%)?([a-zA-Z]+|!)(!)?(?:\s*(.*?)\s*)?$/);
if (!matches) if (!matches)
return [null, null, null, null, null]; return [null, null, null, null, null];
matches.shift(); let [, count, cmd, special, args, heredoc] = matches;
// parse count // parse count
if (matches[0]) if (count)
matches[0] = matches[0] == "%" ? this.COUNT_ALL: parseInt(matches[0], 10); count = count == "%" ? this.COUNT_ALL: parseInt(count, 10);
else else
matches[0] = this.COUNT_NONE; count = this.COUNT_NONE;
matches[2] = !!matches[2]; if (args)
matches.push(null);
if (matches[3])
{ {
tag = matches[3].match(/<<\s*(\w+)\s*$/); tag = args.match(/<<\s*(\w+)\s*$/);
if (tag && tag[1]) if (tag && tag[1])
matches[4] = tag[1]; heredoc = tag[1];
} }
else
matches[3] = "";
return matches; return [count, cmd, !!special, args || "", heredoc];
}, },
get quoteArg() quoteArg, get quoteArg() quoteArg,

View File

@@ -166,7 +166,7 @@ function Completion() //{{{
obj = obj.wrappedJSObject; obj = obj.wrappedJSObject;
// v[0] in orig and orig[v[0]] catch different cases. XPCOM // v[0] in orig and orig[v[0]] catch different cases. XPCOM
// objects are problematic, to say the least. // objects are problematic, to say the least.
compl.push([v for (v in this.iter(obj)) if (v[0] in orig || orig[v[0]] != undefined)]) compl.push([v for (v in this.iter(obj)) if (v[0] in orig || orig[v[0]] !== undefined)])
// And if wrappedJSObject happens to be available, // And if wrappedJSObject happens to be available,
// return that, too. // return that, too.
if (orig.wrappedJSObject) if (orig.wrappedJSObject)
@@ -961,7 +961,7 @@ function Completion() //{{{
{ {
matches = str.match(/^:*\d*(?:\w+[\s!]|!)\s*/); matches = str.match(/^:*\d*(?:\w+[\s!]|!)\s*/);
exLength = matches ? matches[0].length : 0; exLength = matches ? matches[0].length : 0;
compObject = command.completer.call(this, args, special); compObject = command.completer.call(command, args, special);
if (compObject instanceof Array) // for now at least, let completion functions return arrays instead of objects if (compObject instanceof Array) // for now at least, let completion functions return arrays instead of objects
compObject = { start: compObject[0], items: compObject[1] }; compObject = { start: compObject[0], items: compObject[1] };
} }

View File

@@ -430,7 +430,11 @@ liberator.registerObserver("load_commands", function ()
argCount: "2", argCount: "2",
bang: true, bang: true,
completer: function (filter) { completer: function (filter) {
let compl = []; let args = this.parseArgs(filter, true);
let compl = args ? args.completions : [];
if (args && args.completeOpt)
return [args.completeStart, compl];
try try
{ {
compl.push([content.location.host, "Current Host"]); compl.push([content.location.host, "Current Host"]);
@@ -442,7 +446,7 @@ liberator.registerObserver("load_commands", function ()
}, },
hereDoc: true, hereDoc: true,
literal: true, literal: true,
options: [[["-name", "-n"], commands.OPTION_STRING], options: [[["-name", "-n"], commands.OPTION_STRING, null, function () [[k, v.css] for ([k, v] in Iterator(styles.userNames))]],
[["-append", "-a"], commands.OPTION_NOARG]], [["-append", "-a"], commands.OPTION_NOARG]],
serial: function () [ serial: function () [
{ {

View File

@@ -295,7 +295,7 @@ const util = { //{{{
XML.ignoreWhitespace = false; XML.ignoreWhitespace = false;
if (object === null) if (object === null)
return "null"; return "null\n";
if (typeof object != "object") if (typeof object != "object")
return false; return false;