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

More completion stuff.

This commit is contained in:
Kris Maglione
2008-11-23 23:40:40 +00:00
parent fef1cecb75
commit 7d8eb88954
15 changed files with 136 additions and 110 deletions

View File

@@ -338,7 +338,10 @@ function Bookmarks() //{{{
liberator.echo(deletedCount + " bookmark(s) with url `" + url + "' deleted", commandline.FORCE_SINGLELINE); liberator.echo(deletedCount + " bookmark(s) with url `" + url + "' deleted", commandline.FORCE_SINGLELINE);
}, },
{ completer: function (context) completion.bookmark(context.filter) }); {
completer: function (context) completion.bookmark(context.filter),
literal: true
});
/////////////////////////////////////////////////////////////////////////////}}} /////////////////////////////////////////////////////////////////////////////}}}
////////////////////// PUBLIC SECTION ////////////////////////////////////////// ////////////////////// PUBLIC SECTION //////////////////////////////////////////
@@ -631,7 +634,7 @@ function History() //{{{
let filter = context.filter; let filter = context.filter;
var sh = getWebNavigation().sessionHistory; var sh = getWebNavigation().sessionHistory;
var completions = []; var completions = [];
for (let i = sh.index - 1; i >= 0; i--) for (let i in util.range(sh.index, 0, true))
{ {
var entry = sh.getEntryAtIndex(i, false); var entry = sh.getEntryAtIndex(i, false);
var url = entry.URI.spec; var url = entry.URI.spec;
@@ -641,7 +644,8 @@ function History() //{{{
} }
return [0, completions]; return [0, completions];
}, },
count: true count: true,
literal: true
}); });
commands.add(["fo[rward]", "fw"], commands.add(["fo[rward]", "fw"],
@@ -692,7 +696,8 @@ function History() //{{{
} }
return [0, completions]; return [0, completions];
}, },
count: true count: true,
literal: true
}); });
commands.add(["hist[ory]", "hs"], commands.add(["hist[ory]", "hs"],

View File

@@ -512,7 +512,10 @@ function Buffer() //{{{
stylesheetSwitchAll(window.content, args); stylesheetSwitchAll(window.content, args);
}, },
{ completer: function (context) completion.alternateStylesheet(context.filter) }); {
completer: function (context) completion.alternateStylesheet(context.filter),
literal: true
});
commands.add(["re[load]"], commands.add(["re[load]"],
"Reload current page", "Reload current page",

View File

@@ -80,7 +80,7 @@ function Command(specs, description, action, extraInfo) //{{{
this.names = expandedSpecs.names; // return all command name aliases this.names = expandedSpecs.names; // return all command name aliases
this.description = description || ""; this.description = description || "";
this.action = action; this.action = action;
this.argCount = extraInfo.argCount || ""; this.argCount = extraInfo.argCount || 0;
this.completer = extraInfo.completer || null; this.completer = extraInfo.completer || null;
this.hereDoc = extraInfo.hereDoc || false; this.hereDoc = extraInfo.hereDoc || false;
this.options = extraInfo.options || []; this.options = extraInfo.options || [];
@@ -425,7 +425,7 @@ function Commands() //{{{
argCount = "*"; argCount = "*";
if (literal) if (literal)
var literalIndex = parseInt(argCount) - 1 || 0; var literalIndex = argCount == "+" ? 0 : Math.max(argCount - 1, 0);
var args = {}; // parsed options var args = {}; // parsed options
args.arguments = []; // remaining arguments args.arguments = []; // remaining arguments
@@ -499,36 +499,19 @@ function Commands() //{{{
arg = null; arg = null;
quote = null; quote = null;
count = 0; count = 0;
// no value to the option let sep = sub[optname.length];
if (optname.length >= sub.length) if (sep == "=" || /\s/.test(sep) && opt[1] != this.OPTION_NOARG)
{
count = 0;
}
else if (sub[optname.length] == "=")
{ {
[count, arg, quote] = getNextArg(sub.substr(optname.length + 1)); [count, arg, quote] = getNextArg(sub.substr(optname.length + 1));
// 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 count++; // to compensate the "=" character
} }
else if (/\s/.test(sub[optname.length])) else if (sep != null) // this isn't really an option as it has trailing characters, parse it as an argument
{ {
if (opt[1] != this.OPTION_NOARG)
{
[count, arg, quote] = getNextArg(sub.substr(optname.length + 1));
if (count == -1)
// if we add the argument to an option after a space, it MUST not be empty
if (!quote && arg.length == 0)
arg = null;
count++; // to compensate the " " character
}
else
count = 1; // the space
}
else
{
// this isn't really an option as it has trailing characters, parse it as an argument
invalid = true; invalid = true;
} }
@@ -589,6 +572,12 @@ function Commands() //{{{
} }
} }
if (complete)
{
if (argCount == "0" || args.arguments.length > 0 && (argCount == "1" || argCount == "?"))
complete.highlight(i, sub.length, "SPELLCHECK")
}
if (literal && args.arguments.length == literalIndex) if (literal && args.arguments.length == literalIndex)
{ {
args.literalArg = sub; args.literalArg = sub;
@@ -643,7 +632,7 @@ function Commands() //{{{
} }
// check for correct number of arguments // check for correct number of arguments
if (args.arguments.length == 0 && (argCount == "1" || argCount == "+") && !complete) if (!complete && (args.arguments.length == 0 && (argCount == "1" || argCount == "+") || literal && argCount == "+" && /^\s*$/.test(literalArg)))
{ {
liberator.echoerr("E471: Argument required"); liberator.echoerr("E471: Argument required");
return null; return null;
@@ -835,7 +824,7 @@ function Commands() //{{{
} }
}, },
{ {
argCount: "2", argCount: 2,
bang: true, bang: true,
completer: function (context) completion.userCommand(context.filter), completer: function (context) completion.userCommand(context.filter),
options: [ options: [

View File

@@ -53,11 +53,12 @@ function CompletionContext(editor, name, offset)
this.parent = parent; this.parent = parent;
this.editor = parent.editor; this.editor = parent.editor;
this.offset = parent.offset + (offset || 0); this.offset = parent.offset + (offset || 0);
this.__defineGetter__("tabPressed", function () this.top.tabPressed); this.__defineGetter__("contextList", function () this.top.contextList);
this.__defineGetter__("onUpdate", function () this.top.onUpdate); this.__defineGetter__("onUpdate", function () this.top.onUpdate);
this.__defineGetter__("selectionTypes", function () this.top.selectionTypes);
this.__defineGetter__("tabPressed", function () this.top.tabPressed);
this.__defineGetter__("updateAsync", function () this.top.updateAsync); this.__defineGetter__("updateAsync", function () this.top.updateAsync);
this.__defineGetter__("value", function () this.top.value); this.__defineGetter__("value", function () this.top.value);
this.__defineGetter__("selectionTypes", function () this.top.selectionTypes);
this.incomplete = false; this.incomplete = false;
} }
else else
@@ -105,8 +106,6 @@ CompletionContext.prototype = {
get caret() (this.editor ? this.editor.selection.getRangeAt(0).startOffset : this.value.length) - this.offset, get caret() (this.editor ? this.editor.selection.getRangeAt(0).startOffset : this.value.length) - this.offset,
get contextList() [v for ([k, v] in Iterator(this.contexts))],
get createRow() this._createRow || template.completionRow, // XXX get createRow() this._createRow || template.completionRow, // XXX
set createRow(createRow) this._createRow = createRow, set createRow(createRow) this._createRow = createRow,
@@ -132,6 +131,7 @@ CompletionContext.prototype = {
fork: function fork(name, offset, completer, self) fork: function fork(name, offset, completer, self)
{ {
let context = new CompletionContext(this, name, offset); let context = new CompletionContext(this, name, offset);
this.contextList.push(context);
if (completer) if (completer)
return completer.apply(self, [context].concat(Array.slice(arguments, 4))); return completer.apply(self, [context].concat(Array.slice(arguments, 4)));
return context; return context;
@@ -146,16 +146,14 @@ CompletionContext.prototype = {
const editor = this.editor; const editor = this.editor;
let sel = editor.selectionController.getSelection(selType); let sel = editor.selectionController.getSelection(selType);
if (length == 0) if (length == 0)
{
sel.removeAllRanges(); sel.removeAllRanges();
editor.selectionController.repaintSelection(selType); else
return; {
let range = editor.selection.getRangeAt(0).cloneRange();
range.setStart(range.startContainer, this.offset + start);
range.setEnd(range.startContainer, this.offset + start + length);
sel.addRange(range);
} }
let range = editor.selection.getRangeAt(0).cloneRange();
range.setStart(range.startContainer, this.offset + start);
range.setEnd(range.startContainer, this.offset + start + length);
sel.addRange(range);
editor.selectionController.repaintSelection(selType); editor.selectionController.repaintSelection(selType);
} }
catch (e) {} catch (e) {}
@@ -169,10 +167,11 @@ CompletionContext.prototype = {
// Not ideal. // Not ideal.
for (let type in this.selectionTypes) for (let type in this.selectionTypes)
this.highlight(0, 0, type); this.highlight(0, 0, type);
this.updateAsync = false; this.contextList = [];
this.offset = 0;
this.selectionTypes = {}; this.selectionTypes = {};
this.tabPressed = false; this.tabPressed = false;
this.offset = 0; this.updateAsync = false;
this.value = this.editor ? this.editor.rootElement.textContent : this._value; this.value = this.editor ? this.editor.rootElement.textContent : this._value;
//for (let key in (k for ([k, v] in Iterator(self.contexts)) if (v.offset > this.caret))) //for (let key in (k for ([k, v] in Iterator(self.contexts)) if (v.offset > this.caret)))
// delete this.contexts[key]; // delete this.contexts[key];
@@ -1239,8 +1238,9 @@ function Completion() //{{{
root.containerOpen = true; root.containerOpen = true;
context.cache.items = util.map(util.range(0, root.childCount), function (i) { context.cache.items = util.map(util.range(0, root.childCount), function (i) {
let child = root.getChild(i); let child = root.getChild(i);
let query = child.uri.substring(begin.length, child.uri.length - end.length); let rest = child.uri.length - end.length;
if (end == "" || child.uri.substr(-end.length) == end) let query = child.uri.substring(begin.length, rest);
if (child.uri.substr(rest) == end && query.indexOf("&") == -1)
return [decodeURIComponent(query.replace("+", "%20")), return [decodeURIComponent(query.replace("+", "%20")),
child.title, child.title,
child.icon]; child.icon];
@@ -1430,11 +1430,14 @@ function Completion() //{{{
return [0, this.filter(cmds, filter)]; return [0, this.filter(cmds, filter)];
}, },
userMapping: function userMapping(filter, modes) userMapping: function userMapping(context, args, modes)
{ {
// TODO: add appropriate getters to l.mappings liberator.dump(args);
let maps = [[m.names[0], ""] for (m in mappings.getUserIterator(modes))]; if (args.completeArg == 0)
return [0, this.filter(maps, filter)]; {
let maps = [[m.names[0], ""] for (m in mappings.getUserIterator(modes))];
context.items = this.filter(maps, args.arguments[0]);
}
} }
// }}} // }}}
}; };

View File

@@ -173,7 +173,7 @@ function Editor() //{{{
editor.listAbbreviations(mode, lhs || ""); editor.listAbbreviations(mode, lhs || "");
}, },
{ {
argCount: "2", argCount: 2,
literal: true, literal: true,
serial: function () [ serial: function () [
{ {

View File

@@ -111,7 +111,7 @@ function AutoCommands() //{{{
} }
}, },
{ {
argCount: "3", argCount: 3,
bang: true, bang: true,
completer: function (context) completion.autocmdEvent(context.filter), completer: function (context) completion.autocmdEvent(context.filter),
literal: true literal: true
@@ -125,8 +125,8 @@ function AutoCommands() //{{{
commands.get("doautocmd").action.call(this, args.string); commands.get("doautocmd").action.call(this, args.string);
}, },
{ {
argCount: "+", completer: function (context) completion.autocmdEvent(context.filter),
completer: function (context) completion.autocmdEvent(context.filter) literal: true
} }
); );
@@ -136,6 +136,8 @@ function AutoCommands() //{{{
function (args) function (args)
{ {
args = args.string; args = args.string;
if (/^\s*$/.test(args))
return liberator.echo("No matching autocommands");
let [, event, url] = args.match(/^(\S+)(?:\s+(\S+))?$/); let [, event, url] = args.match(/^(\S+)(?:\s+(\S+))?$/);
url = url || buffer.URL; url = url || buffer.URL;
@@ -161,9 +163,8 @@ function AutoCommands() //{{{
} }
}, },
{ {
// TODO: Vim actually just displays "No matching autocommands" when no arg is specified completer: function (context) completion.autocmdEvent(context.filter),
argCount: "+", literal: true
completer: function (context) completion.autocmdEvent(context.filter)
} }
); );
@@ -718,7 +719,8 @@ function Events() //{{{
}, },
{ {
bang: true, bang: true,
completer: function (context) completion.macro(context.filter) completer: function (context) completion.macro(context.filter),
literal: true
}); });
commands.add(["macros"], commands.add(["macros"],
@@ -729,7 +731,10 @@ function Events() //{{{
var str = template.tabular(["Macro", "Keys"], [], events.getMacros(args.string)); var str = template.tabular(["Macro", "Keys"], [], events.getMacros(args.string));
liberator.echo(str, commandline.FORCE_MULTILINE); liberator.echo(str, commandline.FORCE_MULTILINE);
}, },
{ completer: function (context) completion.macro(context.filter) }); {
completer: function (context) completion.macro(context.filter),
literal: true
});
commands.add(["pl[ay]"], commands.add(["pl[ay]"],
"Replay a recorded macro", "Replay a recorded macro",

View File

@@ -339,7 +339,8 @@ function IO() //{{{
}, },
{ {
bang: true, bang: true,
completer: function (context) completion.shellCommand(filter) completer: function (context) completion.shellCommand(context.filter),
literal: true
}); });
/////////////////////////////////////////////////////////////////////////////}}} /////////////////////////////////////////////////////////////////////////////}}}

View File

@@ -239,29 +239,30 @@ const liberator = (function () //{{{
"Execute the specified menu item from the command line", "Execute the specified menu item from the command line",
function (args) function (args)
{ {
var item = args.string; let args = args.string;
var items = getMenuItems(); let items = getMenuItems();
if (!items.some(function (i) i.fullMenuPath == item)) if (!items.some(function (i) i.fullMenuPath == args))
{ {
liberator.echoerr("E334: Menu not found: " + item); liberator.echoerr("E334: Menu not found: " + args);
return; return;
} }
for (let i = 0; i < items.length; i++) for (let [i, item] in Iterator(items))
{ {
if (items[i].fullMenuPath == item) if (item.fullMenuPath == args)
items[i].doCommand(); item.doCommand();
} }
}, },
{ {
argCount: "+", // NOTE: single arg may contain unescaped whitespace argCount: "+",
// TODO: add this as a standard menu completion function // TODO: add this as a standard menu completion function
completer: function (context) completer: function (context)
{ {
let completions = getMenuItems().map(function (item) [item.fullMenuPath, item.label]); let completions = getMenuItems().map(function (item) [item.fullMenuPath, item.label]);
return [0, completion.filter(completions, context.filter)]; return [0, completion.filter(completions, context.filter)];
} },
literal: true
}); });
commands.add(["exe[cute]"], commands.add(["exe[cute]"],
@@ -307,7 +308,8 @@ const liberator = (function () //{{{
}, },
{ {
bang: true, bang: true,
completer: function (context) completion.help(context.filter) completer: function (context) completion.help(context.filter),
literal: true
}); });
commands.add(["javas[cript]", "js"], commands.add(["javas[cript]", "js"],
@@ -335,7 +337,8 @@ const liberator = (function () //{{{
{ {
bang: true, bang: true,
completer: function (context) completion.javascript(context), completer: function (context) completion.javascript(context),
hereDoc: true hereDoc: true,
literal: true
}); });
commands.add(["loadplugins", "lpl"], commands.add(["loadplugins", "lpl"],
@@ -468,7 +471,8 @@ const liberator = (function () //{{{
else else
return completion.javascript(context); return completion.javascript(context);
}, },
count: true count: true,
literal: true
}); });
commands.add(["ve[rsion]"], commands.add(["ve[rsion]"],

View File

@@ -184,8 +184,8 @@ function Mappings() //{{{
modeDescription = modeDescription ? " in " + modeDescription + " mode" : ""; modeDescription = modeDescription ? " in " + modeDescription + " mode" : "";
const opts = { const opts = {
argCount: "2", argCount: 2,
completer: function (context) completion.userMapping(context.filter, modes), completer: function (context, args) completion.userMapping(context, args, modes),
options: [ options: [
[["<silent>", "<Silent>"], commands.OPTION_NOARG] [["<silent>", "<Silent>"], commands.OPTION_NOARG]
], ],
@@ -224,13 +224,7 @@ function Mappings() //{{{
"Remove a mapping" + modeDescription, "Remove a mapping" + modeDescription,
function (args) function (args)
{ {
args = args.string; args = args.arguments[1];
if (!args)
{
liberator.echoerr("E474: Invalid argument");
return;
}
let found = false; let found = false;
for (let [,mode] in Iterator(modes)) for (let [,mode] in Iterator(modes))
@@ -244,7 +238,10 @@ function Mappings() //{{{
if (!found) if (!found)
liberator.echoerr("E31: No such mapping"); liberator.echoerr("E31: No such mapping");
}, },
{ completer: function (context) completion.userMapping(context.filter, modes) }); {
argCount: "1",
completer: function (context, args) completion.userMapping(context, args, modes)
});
} }
/////////////////////////////////////////////////////////////////////////////}}} /////////////////////////////////////////////////////////////////////////////}}}

View File

@@ -397,7 +397,8 @@ function Options() //{{{
completer: function (context, args, special, count) completer: function (context, args, special, count)
{ {
return commands.get("set").completer(context.filter, special, count, { scope: options.OPTION_SCOPE_LOCAL }); return commands.get("set").completer(context.filter, special, count, { scope: options.OPTION_SCOPE_LOCAL });
} },
literal: true
} }
); );
@@ -413,7 +414,8 @@ function Options() //{{{
completer: function (context, args, special, count) completer: function (context, args, special, count)
{ {
return commands.get("set").completer(context.filter, special, count, { scope: options.OPTION_SCOPE_GLOBAL }); return commands.get("set").completer(context.filter, special, count, { scope: options.OPTION_SCOPE_GLOBAL });
} },
literal: true
} }
); );
@@ -801,6 +803,7 @@ function Options() //{{{
} }
return [len, completion.filter(completions, filter, true)]; return [len, completion.filter(completions, filter, true)];
}, },
literal: true,
serial: function () [ serial: function () [
{ {
command: this.name, command: this.name,

View File

@@ -426,7 +426,7 @@ liberator.registerObserver("load_commands", function ()
} }
}, },
{ {
argCount: "2", argCount: 2,
bang: true, bang: true,
completer: function (context, args, bang) { completer: function (context, args, bang) {
let compl = []; let compl = [];
@@ -463,7 +463,7 @@ liberator.registerObserver("load_commands", function ()
styles.removeSheet(args["-name"], args.arguments[0], args.literalArg, args["-index"], false); styles.removeSheet(args["-name"], args.arguments[0], args.literalArg, args["-index"], false);
}, },
{ {
argCount: "2", argCount: 2,
// FIXME: Ugly. // FIXME: Ugly.
completer: function (context) [0, completion.filter( completer: function (context) [0, completion.filter(
[[i, <>{s.sites.join(",")}: {s.css.replace("\n", "\\n")}</>] [[i, <>{s.sites.join(",")}: {s.css.replace("\n", "\\n")}</>]
@@ -507,7 +507,7 @@ liberator.registerObserver("load_commands", function ()
liberator.echoerr(error); liberator.echoerr(error);
}, },
{ {
argCount: "2", argCount: 2,
bang: true, bang: true,
// TODO: add this as a standard highlight completion function? // TODO: add this as a standard highlight completion function?
completer: function (context) [0, completer: function (context) [0,

View File

@@ -354,7 +354,8 @@ function Tabs() //{{{
{ {
bang: true, bang: true,
count: true, count: true,
completer: function (context) completion.buffer(context.filter) completer: function (context) completion.buffer(context.filter),
literal: true
}); });
// TODO: this should open in a new tab positioned directly after the current one, not at the end // TODO: this should open in a new tab positioned directly after the current one, not at the end
@@ -368,7 +369,8 @@ function Tabs() //{{{
}, },
{ {
argCount: "+", argCount: "+",
completer: function (context) completion.ex(context.filter) completer: function (context) completion.ex(context.filter),
literal: true
}); });
commands.add(["tabl[ast]", "bl[ast]"], commands.add(["tabl[ast]", "bl[ast]"],
@@ -478,7 +480,8 @@ function Tabs() //{{{
{ {
bang: true, bang: true,
count: true, count: true,
completer: function (context) completion.buffer(context.filter) completer: function (context) completion.buffer(context.filter),
literal: true
}); });
commands.add(["buffers", "files", "ls", "tabs"], commands.add(["buffers", "files", "ls", "tabs"],
@@ -548,7 +551,8 @@ function Tabs() //{{{
}, },
{ {
bang: true, bang: true,
completer: function (context) completion.url(context) completer: function (context) completion.url(context),
literal: true
}); });
commands.add(["tabde[tach]"], commands.add(["tabde[tach]"],
@@ -634,7 +638,8 @@ function Tabs() //{{{
} }
return [0, completions]; return [0, completions];
}, },
count: true count: true,
literal: true
}); });
commands.add(["undoa[ll]"], commands.add(["undoa[ll]"],

View File

@@ -500,7 +500,10 @@ function CommandLine() //{{{
if (str != null) if (str != null)
command.action(str); command.action(str);
}, },
{ completer: function (context) completion.javascript(context) }); {
completer: function (context) completion.javascript(context),
literal: true
});
}); });
commands.add(["mes[sages]"], commands.add(["mes[sages]"],

View File

@@ -349,10 +349,18 @@ const util = { //{{{
return color ? string : [s for each (s in string)].join(""); return color ? string : [s for each (s in string)].join("");
}, },
range: function (start, end) range: function (start, end, reverse)
{ {
while (start < end) if (!reverse)
yield start++; {
while (start < end)
yield start++;
}
else
{
while (start >= end)
yield --start;
}
}, },
interruptableRange: function (start, end, time) interruptableRange: function (start, end, time)

View File

@@ -283,19 +283,15 @@ const config = { //{{{
{ {
liberator.open(args); liberator.open(args);
} }
else if (special)
BrowserReloadSkipCache();
else else
{ BrowserReload();
if (special)
BrowserReloadSkipCache();
else
BrowserReload();
}
}, },
{ {
bang: true, bang: true,
literal: true, completer: function (context) completion.url(context),
argCount: 0, literal: true
completer: function (context) completion.url(context)
}); });
commands.add(["redr[aw]"], commands.add(["redr[aw]"],
@@ -347,7 +343,8 @@ const config = { //{{{
}, },
{ {
argCount: "+", argCount: "+",
completer: function (context) completion.sidebar(context.filter) completer: function (context) completion.sidebar(context.filter),
literal: true
}); });
commands.add(["winc[lose]", "wc[lose]"], commands.add(["winc[lose]", "wc[lose]"],
@@ -366,7 +363,10 @@ const config = { //{{{
else else
liberator.open("about:blank", liberator.NEW_WINDOW); liberator.open("about:blank", liberator.NEW_WINDOW);
}, },
{ completer: function (context) completion.url(context) }); {
completer: function (context) completion.url(context),
literal: true
});
/////////////////////////////////////////////////////////////////////////////}}} /////////////////////////////////////////////////////////////////////////////}}}
////////////////////// OPTIONS ///////////////////////////////////////////////// ////////////////////// OPTIONS /////////////////////////////////////////////////