mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-23 08:28:01 +01:00
Make JS function completion better. Fix some other completion bugs. Dont complete JS after /[\]})"/.
This commit is contained in:
@@ -723,6 +723,8 @@ function History() //{{{
|
||||
function (args) { history.list(args.string, args.bang); },
|
||||
{
|
||||
bang: true,
|
||||
literal: true,
|
||||
completer: function (context) completion.history(context)
|
||||
// completer: function (filter) completion.history(filter)
|
||||
});
|
||||
|
||||
|
||||
@@ -602,7 +602,7 @@ function Commands() //{{{
|
||||
|
||||
if (complete)
|
||||
{
|
||||
if (argCount == "0" || args.length > 0 && (argCount == "1" || argCount == "?"))
|
||||
if (argCount == "0" || args.length > 0 && (/[1?]/.test(argCount)))
|
||||
complete.highlight(i, sub.length, "SPELLCHECK")
|
||||
}
|
||||
|
||||
@@ -639,9 +639,9 @@ function Commands() //{{{
|
||||
if (complete)
|
||||
args.completeArg = args.length - 1;
|
||||
|
||||
if (count <= 0)
|
||||
break;
|
||||
i += count;
|
||||
if (count <= 0 || i == str.length)
|
||||
break;
|
||||
}
|
||||
|
||||
if (complete)
|
||||
@@ -666,12 +666,14 @@ function Commands() //{{{
|
||||
}
|
||||
|
||||
// check for correct number of arguments
|
||||
if (!complete && (args.length == 0 && /^[1+]$/.test(argCount) ||
|
||||
// TODO: what is this for? -- djk
|
||||
literal && argCount == "+" && /^\s*$/.test(args.literalArg)))
|
||||
if (args.length == 0 && /^[1+]$/.test(argCount) ||
|
||||
literal && argCount == "+" && /^\s*$/.test(args.literalArg))
|
||||
{
|
||||
liberator.echoerr("E471: Argument required");
|
||||
return null;
|
||||
if (!complete)
|
||||
{
|
||||
liberator.echoerr("E471: Argument required");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (args.length == 1 && (argCount == "0") ||
|
||||
args.length > 1 && /^[01?]$/.test(argCount))
|
||||
|
||||
@@ -117,7 +117,6 @@ CompletionContext.prototype = {
|
||||
return [];
|
||||
let prefix = self.value.substring(minStart, context.offset);
|
||||
return context.items.map(function makeItem(item) ({ text: prefix + item.text, item: item.item }));
|
||||
//return [{ text: prefix + item.text, item: item.item } for ([i, item] in Iterator(context.items))];
|
||||
});
|
||||
return { start: minStart, items: util.Array.flatten(items), longestSubstring: this.longestAllSubstring }
|
||||
},
|
||||
@@ -157,13 +156,16 @@ CompletionContext.prototype = {
|
||||
get completions() this._completions || [],
|
||||
set completions(items)
|
||||
{
|
||||
// Accept a generator
|
||||
if (!(items instanceof Array))
|
||||
items = [x for (x in items)];
|
||||
delete this.cache.filtered;
|
||||
delete this.cache.filter;
|
||||
this.cache.rows = [];
|
||||
this.hasItems = items.length > 0;
|
||||
this._completions = items;
|
||||
let self = this;
|
||||
if (this.updateAsync)
|
||||
if (this.updateAsync && !this.noUpdate)
|
||||
liberator.callInMainThread(function () { self.onUpdate.call(self) });
|
||||
},
|
||||
|
||||
@@ -234,10 +236,9 @@ CompletionContext.prototype = {
|
||||
if (this.generate && !this.background)
|
||||
{
|
||||
// XXX
|
||||
let updateAsync = this.updateAsync;
|
||||
this.updateAsync = false;
|
||||
this.noUpdate = true;
|
||||
this.completions = items = this.generate();
|
||||
this.updateAsync = updateAsync;
|
||||
this.noUpdate = false;
|
||||
}
|
||||
this.cache.filter = this.filter;
|
||||
if (items == null)
|
||||
@@ -320,6 +321,7 @@ CompletionContext.prototype = {
|
||||
this.offset += count;
|
||||
if (this.quote)
|
||||
{
|
||||
this.offset += this.quote[0].length;
|
||||
this.quote[0] = "";
|
||||
this.quote[2] = "";
|
||||
}
|
||||
@@ -461,7 +463,6 @@ function Completion() //{{{
|
||||
let str = "";
|
||||
|
||||
let lastIdx = 0;
|
||||
let continuing = false;
|
||||
|
||||
let cacheKey = null;
|
||||
|
||||
@@ -545,12 +546,11 @@ function Completion() //{{{
|
||||
|
||||
this.eval = function eval(arg, key, tmp)
|
||||
{
|
||||
if (!("eval" in this.context.cache))
|
||||
if (!this.context.cache.eval)
|
||||
this.context.cache.eval = {};
|
||||
let cache = this.context.cache.eval;
|
||||
if (!key)
|
||||
key = arg;
|
||||
|
||||
if (key in cache)
|
||||
return cache[key];
|
||||
|
||||
@@ -608,23 +608,10 @@ function Completion() //{{{
|
||||
return ret;
|
||||
}
|
||||
|
||||
let i = start, c = ""; /* Current index and character, respectively. */
|
||||
let i = 0, c = ""; /* Current index and character, respectively. */
|
||||
|
||||
// We're starting afresh.
|
||||
if (start == 0)
|
||||
{
|
||||
stack = [];
|
||||
push("#root");
|
||||
}
|
||||
else
|
||||
{
|
||||
// A new statement may have been pushed onto the stack just after
|
||||
// the end of the last string. We'll throw it away for now, and
|
||||
// add it again later if it turns out to be valid.
|
||||
let s = top[STATEMENTS];
|
||||
if (s[s.length - 1] == start)
|
||||
s.pop();
|
||||
}
|
||||
stack = [];
|
||||
push("#root");
|
||||
|
||||
/* Build a parse stack, discarding entries as opening characters
|
||||
* match closing characters. The stack is walked from the top entry
|
||||
@@ -704,20 +691,11 @@ function Completion() //{{{
|
||||
this.context = context;
|
||||
let string = context.filter;
|
||||
|
||||
context.process = [null, function highlight(item, v) template.highlight(v, true)];
|
||||
context.compare = function ({item: {key: a}}, {item: {key: b}})
|
||||
{
|
||||
if (!isNaN(a) && !isNaN(b))
|
||||
return a - b;
|
||||
return String.localeCompare(a, b);
|
||||
}
|
||||
|
||||
let self = this;
|
||||
try
|
||||
{
|
||||
continuing = lastIdx && string.indexOf(str) == 0;
|
||||
str = string;
|
||||
buildStack.call(this, continuing ? lastIdx : 0);
|
||||
buildStack.call(this);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
@@ -729,6 +707,9 @@ function Completion() //{{{
|
||||
|
||||
/* Okay, have parse stack. Figure out what we're completing. */
|
||||
|
||||
if (/[\])}"';]/.test(str[lastIdx - 1]) && last != '"' && last != '"')
|
||||
return;
|
||||
|
||||
// Find any complete statements that we can eval before we eval our object.
|
||||
// This allows for things like: let doc = window.content.document; let elem = doc.createElement...; elem.<Tab>
|
||||
let prev = 0;
|
||||
@@ -788,35 +769,50 @@ function Completion() //{{{
|
||||
function fill(context, obj, name, compl, anchored, key, last, offset)
|
||||
{
|
||||
context.title = [name];
|
||||
context.key = name;
|
||||
context.anchored = anchored;
|
||||
context.filter = key;
|
||||
context.itemCache = context.parent.itemCache;
|
||||
if (compl)
|
||||
context.completions = compl;
|
||||
else
|
||||
context.generate = function () self.objectKeys(obj);
|
||||
context.key = name;
|
||||
|
||||
if (last != undefined)
|
||||
context.quote = [last, function (text) util.escapeString(text.substr(offset), ""), last];
|
||||
else // We're not looking for a quoted string, so filter out anything that's not a valid identifier
|
||||
context.filters.push(function (item) /^[\w$][\w\d$]*$/.test(item.text));
|
||||
if (!anchored)
|
||||
context.filters.push(function (item) util.compareIgnoreCase(item.text.substr(0, key.length), key));
|
||||
|
||||
compl.call(self, context, obj);
|
||||
}
|
||||
|
||||
function complete(objects, key, compl, string, last)
|
||||
{
|
||||
let orig = compl;
|
||||
if (!compl)
|
||||
compl = function (context, obj) {
|
||||
context.process = [null, function highlight(item, v) template.highlight(v, true)];
|
||||
if (!context.anchored)
|
||||
context.filters.push(function (item) util.compareIgnoreCase(item.text.substr(0, key.length), key));
|
||||
context.compare = function ({item: {key: a}}, {item: {key: b}})
|
||||
{
|
||||
if (!isNaN(a) && !isNaN(b))
|
||||
return a - b;
|
||||
return String.localeCompare(a, b);
|
||||
}
|
||||
context.generate = function () self.objectKeys(obj);
|
||||
}
|
||||
let filter = key + (string || "");
|
||||
for (let [,obj] in Iterator(objects))
|
||||
{
|
||||
this.context.fork(obj[1], top[OFFSET], this, fill, obj[0], obj[1], compl,
|
||||
true, key + (string || ""), last, key.length);
|
||||
try {
|
||||
this.context.fork(obj[1], top[OFFSET], this, fill,
|
||||
obj[0], obj[1], compl, compl != orig, filter, last, key.length);
|
||||
} catch(e) { liberator.reportError(e) }
|
||||
}
|
||||
if (orig)
|
||||
return;
|
||||
for (let [,obj] in Iterator(objects))
|
||||
{
|
||||
obj[1] += " (substrings)";
|
||||
this.context.fork(obj[1], top[OFFSET], this, fill, obj[0], obj[1], compl,
|
||||
false, key + (string || ""), last, key.length);
|
||||
this.context.fork(obj[1], top[OFFSET], this, fill,
|
||||
obj[0], obj[1], compl, false, filter, last, key.length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,19 +884,22 @@ function Completion() //{{{
|
||||
|
||||
// Split up the arguments
|
||||
let prev = get(-2)[OFFSET];
|
||||
let args = get(-2)[FULL_STATEMENTS].map(function splitArgs(s)
|
||||
let args = [];
|
||||
for (let [i, idx] in Iterator(get(-2)[FULL_STATEMENTS]))
|
||||
{
|
||||
let ret = str.substring(prev + 1, s);
|
||||
prev = s;
|
||||
return ret;
|
||||
});
|
||||
args.push(key);
|
||||
|
||||
let compl = completer.call(this, func, obj[0][0], string, args);
|
||||
if (!(compl instanceof Array))
|
||||
compl = [v for (v in compl)];
|
||||
let arg = str.substring(prev + 1, idx);
|
||||
prev = idx;
|
||||
args.__defineGetter__(i, function () self.eval(ret));
|
||||
}
|
||||
key = this.eval(key);
|
||||
obj[0][1] += "." + func + "(...";
|
||||
args.push(key + string);
|
||||
|
||||
compl = function (context, obj) {
|
||||
let res = completer.call(self, context, func, obj, args);
|
||||
if (res)
|
||||
context.completions = res;
|
||||
}
|
||||
obj[0][1] += "." + func + "(... [" + args.length + "]";
|
||||
return complete.call(this, obj, key, compl, string, last);
|
||||
}
|
||||
|
||||
@@ -935,20 +934,16 @@ function Completion() //{{{
|
||||
|
||||
let self = {
|
||||
|
||||
// FIXME
|
||||
get getKey() this._getKey || function (item, key) item[{ text: 0, description: 1, icon: 2 }[key]],
|
||||
set getKey(getKey) this._getKey = getKey,
|
||||
|
||||
setFunctionCompleter: function setFunctionCompleter(funcs, completers)
|
||||
{
|
||||
funcs = Array.concat(funcs);
|
||||
for (let [,func] in Iterator(funcs))
|
||||
{
|
||||
func.liberatorCompleter = function liberatorCompleter(func, obj, string, args) {
|
||||
func.liberatorCompleter = function liberatorCompleter(context, func, obj, args) {
|
||||
let completer = completers[args.length - 1];
|
||||
if (!completer)
|
||||
return [];
|
||||
return completer.call(this, this.eval(obj), this.eval(args.pop()) + string, args);
|
||||
return completer.call(this, context, obj, args);
|
||||
};
|
||||
}
|
||||
},
|
||||
@@ -957,9 +952,7 @@ function Completion() //{{{
|
||||
_runCompleter: function _runCompleter(name, filter)
|
||||
{
|
||||
let context = CompletionContext(filter);
|
||||
if (typeof name == "string")
|
||||
name = this[name];
|
||||
name.apply(this, [context].concat(Array.slice(arguments, 2)));
|
||||
context.fork.apply(context, ["run", 0, this, name].concat(Array.slice(arguments, 2)));
|
||||
while (context.incomplete)
|
||||
liberator.threadYield(true, true);
|
||||
return context.allItems;
|
||||
@@ -1121,7 +1114,6 @@ function Completion() //{{{
|
||||
text: [i + ": " + (tab.label || "(Untitled)"), i + ": " + url],
|
||||
url: url,
|
||||
indicator: indicator,
|
||||
i: i,
|
||||
icon: tab.image
|
||||
};
|
||||
});
|
||||
|
||||
@@ -366,7 +366,10 @@ function IO() //{{{
|
||||
liberator.registerObserver("load_completion", function ()
|
||||
{
|
||||
completion.setFunctionCompleter([ioManager.getFile, ioManager.expandPath],
|
||||
[function (obj, arg) completion.runCompleter("file", arg.replace(/[^\/]*$/, ""))]);
|
||||
[function (context, obj, args) {
|
||||
context.quote[2] = "";
|
||||
completion.file(context, true);
|
||||
}]);
|
||||
});
|
||||
|
||||
var ioManager = {
|
||||
|
||||
@@ -215,7 +215,7 @@ const liberator = (function () //{{{
|
||||
{
|
||||
argCount: "1",
|
||||
bang: true,
|
||||
completer: function (context) completion.dialog(context)
|
||||
completer: function (context, args) completion.dialog(context)
|
||||
});
|
||||
|
||||
// TODO: move this
|
||||
|
||||
@@ -263,9 +263,9 @@ function Mappings() //{{{
|
||||
completion.setFunctionCompleter(mappings.get,
|
||||
[
|
||||
null,
|
||||
function (obj, filter, args)
|
||||
function (context, obj, args)
|
||||
{
|
||||
let mode = this.eval(args[0]);
|
||||
let mode = args[0]
|
||||
return util.Array.flatten(
|
||||
[
|
||||
[[name, map.description] for ([i, name] in Iterator(map.names))]
|
||||
|
||||
@@ -700,7 +700,7 @@ function Options() //{{{
|
||||
context.title = ["Option"];
|
||||
context.quote = [prefix, util.identity, ""];
|
||||
context.keys = { text: "names", description: "description" };
|
||||
context.completions = [opt for (opt in opts)];
|
||||
context.completions = opts;
|
||||
return;
|
||||
}
|
||||
else if (prefix == "no")
|
||||
|
||||
Reference in New Issue
Block a user