mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-23 10:37:59 +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); },
|
function (args) { history.list(args.string, args.bang); },
|
||||||
{
|
{
|
||||||
bang: true,
|
bang: true,
|
||||||
|
literal: true,
|
||||||
|
completer: function (context) completion.history(context)
|
||||||
// completer: function (filter) completion.history(filter)
|
// completer: function (filter) completion.history(filter)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -602,7 +602,7 @@ function Commands() //{{{
|
|||||||
|
|
||||||
if (complete)
|
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")
|
complete.highlight(i, sub.length, "SPELLCHECK")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,9 +639,9 @@ function Commands() //{{{
|
|||||||
if (complete)
|
if (complete)
|
||||||
args.completeArg = args.length - 1;
|
args.completeArg = args.length - 1;
|
||||||
|
|
||||||
if (count <= 0)
|
|
||||||
break;
|
|
||||||
i += count;
|
i += count;
|
||||||
|
if (count <= 0 || i == str.length)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (complete)
|
if (complete)
|
||||||
@@ -666,13 +666,15 @@ function Commands() //{{{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check for correct number of arguments
|
// check for correct number of arguments
|
||||||
if (!complete && (args.length == 0 && /^[1+]$/.test(argCount) ||
|
if (args.length == 0 && /^[1+]$/.test(argCount) ||
|
||||||
// TODO: what is this for? -- djk
|
literal && argCount == "+" && /^\s*$/.test(args.literalArg))
|
||||||
literal && argCount == "+" && /^\s*$/.test(args.literalArg)))
|
{
|
||||||
|
if (!complete)
|
||||||
{
|
{
|
||||||
liberator.echoerr("E471: Argument required");
|
liberator.echoerr("E471: Argument required");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (args.length == 1 && (argCount == "0") ||
|
else if (args.length == 1 && (argCount == "0") ||
|
||||||
args.length > 1 && /^[01?]$/.test(argCount))
|
args.length > 1 && /^[01?]$/.test(argCount))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -117,7 +117,6 @@ CompletionContext.prototype = {
|
|||||||
return [];
|
return [];
|
||||||
let prefix = self.value.substring(minStart, context.offset);
|
let prefix = self.value.substring(minStart, context.offset);
|
||||||
return context.items.map(function makeItem(item) ({ text: prefix + item.text, item: item.item }));
|
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 }
|
return { start: minStart, items: util.Array.flatten(items), longestSubstring: this.longestAllSubstring }
|
||||||
},
|
},
|
||||||
@@ -157,13 +156,16 @@ CompletionContext.prototype = {
|
|||||||
get completions() this._completions || [],
|
get completions() this._completions || [],
|
||||||
set completions(items)
|
set completions(items)
|
||||||
{
|
{
|
||||||
|
// Accept a generator
|
||||||
|
if (!(items instanceof Array))
|
||||||
|
items = [x for (x in items)];
|
||||||
delete this.cache.filtered;
|
delete this.cache.filtered;
|
||||||
delete this.cache.filter;
|
delete this.cache.filter;
|
||||||
this.cache.rows = [];
|
this.cache.rows = [];
|
||||||
this.hasItems = items.length > 0;
|
this.hasItems = items.length > 0;
|
||||||
this._completions = items;
|
this._completions = items;
|
||||||
let self = this;
|
let self = this;
|
||||||
if (this.updateAsync)
|
if (this.updateAsync && !this.noUpdate)
|
||||||
liberator.callInMainThread(function () { self.onUpdate.call(self) });
|
liberator.callInMainThread(function () { self.onUpdate.call(self) });
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -234,10 +236,9 @@ CompletionContext.prototype = {
|
|||||||
if (this.generate && !this.background)
|
if (this.generate && !this.background)
|
||||||
{
|
{
|
||||||
// XXX
|
// XXX
|
||||||
let updateAsync = this.updateAsync;
|
this.noUpdate = true;
|
||||||
this.updateAsync = false;
|
|
||||||
this.completions = items = this.generate();
|
this.completions = items = this.generate();
|
||||||
this.updateAsync = updateAsync;
|
this.noUpdate = false;
|
||||||
}
|
}
|
||||||
this.cache.filter = this.filter;
|
this.cache.filter = this.filter;
|
||||||
if (items == null)
|
if (items == null)
|
||||||
@@ -320,6 +321,7 @@ CompletionContext.prototype = {
|
|||||||
this.offset += count;
|
this.offset += count;
|
||||||
if (this.quote)
|
if (this.quote)
|
||||||
{
|
{
|
||||||
|
this.offset += this.quote[0].length;
|
||||||
this.quote[0] = "";
|
this.quote[0] = "";
|
||||||
this.quote[2] = "";
|
this.quote[2] = "";
|
||||||
}
|
}
|
||||||
@@ -461,7 +463,6 @@ function Completion() //{{{
|
|||||||
let str = "";
|
let str = "";
|
||||||
|
|
||||||
let lastIdx = 0;
|
let lastIdx = 0;
|
||||||
let continuing = false;
|
|
||||||
|
|
||||||
let cacheKey = null;
|
let cacheKey = null;
|
||||||
|
|
||||||
@@ -545,12 +546,11 @@ function Completion() //{{{
|
|||||||
|
|
||||||
this.eval = function eval(arg, key, tmp)
|
this.eval = function eval(arg, key, tmp)
|
||||||
{
|
{
|
||||||
if (!("eval" in this.context.cache))
|
if (!this.context.cache.eval)
|
||||||
this.context.cache.eval = {};
|
this.context.cache.eval = {};
|
||||||
let cache = this.context.cache.eval;
|
let cache = this.context.cache.eval;
|
||||||
if (!key)
|
if (!key)
|
||||||
key = arg;
|
key = arg;
|
||||||
|
|
||||||
if (key in cache)
|
if (key in cache)
|
||||||
return cache[key];
|
return cache[key];
|
||||||
|
|
||||||
@@ -608,23 +608,10 @@ function Completion() //{{{
|
|||||||
return ret;
|
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 = [];
|
stack = [];
|
||||||
push("#root");
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Build a parse stack, discarding entries as opening characters
|
/* Build a parse stack, discarding entries as opening characters
|
||||||
* match closing characters. The stack is walked from the top entry
|
* match closing characters. The stack is walked from the top entry
|
||||||
@@ -704,20 +691,11 @@ function Completion() //{{{
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
let string = context.filter;
|
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;
|
let self = this;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
continuing = lastIdx && string.indexOf(str) == 0;
|
|
||||||
str = string;
|
str = string;
|
||||||
buildStack.call(this, continuing ? lastIdx : 0);
|
buildStack.call(this);
|
||||||
}
|
}
|
||||||
catch (e)
|
catch (e)
|
||||||
{
|
{
|
||||||
@@ -729,6 +707,9 @@ function Completion() //{{{
|
|||||||
|
|
||||||
/* Okay, have parse stack. Figure out what we're completing. */
|
/* 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.
|
// 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>
|
// This allows for things like: let doc = window.content.document; let elem = doc.createElement...; elem.<Tab>
|
||||||
let prev = 0;
|
let prev = 0;
|
||||||
@@ -788,35 +769,50 @@ function Completion() //{{{
|
|||||||
function fill(context, obj, name, compl, anchored, key, last, offset)
|
function fill(context, obj, name, compl, anchored, key, last, offset)
|
||||||
{
|
{
|
||||||
context.title = [name];
|
context.title = [name];
|
||||||
context.key = name;
|
|
||||||
context.anchored = anchored;
|
context.anchored = anchored;
|
||||||
context.filter = key;
|
context.filter = key;
|
||||||
context.itemCache = context.parent.itemCache;
|
context.itemCache = context.parent.itemCache;
|
||||||
if (compl)
|
context.key = name;
|
||||||
context.completions = compl;
|
|
||||||
else
|
|
||||||
context.generate = function () self.objectKeys(obj);
|
|
||||||
|
|
||||||
if (last != undefined)
|
if (last != undefined)
|
||||||
context.quote = [last, function (text) util.escapeString(text.substr(offset), ""), last];
|
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
|
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));
|
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)
|
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))
|
for (let [,obj] in Iterator(objects))
|
||||||
{
|
{
|
||||||
this.context.fork(obj[1], top[OFFSET], this, fill, obj[0], obj[1], compl,
|
try {
|
||||||
true, key + (string || ""), last, key.length);
|
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))
|
for (let [,obj] in Iterator(objects))
|
||||||
{
|
{
|
||||||
obj[1] += " (substrings)";
|
obj[1] += " (substrings)";
|
||||||
this.context.fork(obj[1], top[OFFSET], this, fill, obj[0], obj[1], compl,
|
this.context.fork(obj[1], top[OFFSET], this, fill,
|
||||||
false, key + (string || ""), last, key.length);
|
obj[0], obj[1], compl, false, filter, last, key.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -888,19 +884,22 @@ function Completion() //{{{
|
|||||||
|
|
||||||
// Split up the arguments
|
// Split up the arguments
|
||||||
let prev = get(-2)[OFFSET];
|
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);
|
let arg = str.substring(prev + 1, idx);
|
||||||
prev = s;
|
prev = idx;
|
||||||
return ret;
|
args.__defineGetter__(i, function () self.eval(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)];
|
|
||||||
key = this.eval(key);
|
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);
|
return complete.call(this, obj, key, compl, string, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -935,20 +934,16 @@ function Completion() //{{{
|
|||||||
|
|
||||||
let self = {
|
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)
|
setFunctionCompleter: function setFunctionCompleter(funcs, completers)
|
||||||
{
|
{
|
||||||
funcs = Array.concat(funcs);
|
funcs = Array.concat(funcs);
|
||||||
for (let [,func] in Iterator(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];
|
let completer = completers[args.length - 1];
|
||||||
if (!completer)
|
if (!completer)
|
||||||
return [];
|
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)
|
_runCompleter: function _runCompleter(name, filter)
|
||||||
{
|
{
|
||||||
let context = CompletionContext(filter);
|
let context = CompletionContext(filter);
|
||||||
if (typeof name == "string")
|
context.fork.apply(context, ["run", 0, this, name].concat(Array.slice(arguments, 2)));
|
||||||
name = this[name];
|
|
||||||
name.apply(this, [context].concat(Array.slice(arguments, 2)));
|
|
||||||
while (context.incomplete)
|
while (context.incomplete)
|
||||||
liberator.threadYield(true, true);
|
liberator.threadYield(true, true);
|
||||||
return context.allItems;
|
return context.allItems;
|
||||||
@@ -1121,7 +1114,6 @@ function Completion() //{{{
|
|||||||
text: [i + ": " + (tab.label || "(Untitled)"), i + ": " + url],
|
text: [i + ": " + (tab.label || "(Untitled)"), i + ": " + url],
|
||||||
url: url,
|
url: url,
|
||||||
indicator: indicator,
|
indicator: indicator,
|
||||||
i: i,
|
|
||||||
icon: tab.image
|
icon: tab.image
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -366,7 +366,10 @@ function IO() //{{{
|
|||||||
liberator.registerObserver("load_completion", function ()
|
liberator.registerObserver("load_completion", function ()
|
||||||
{
|
{
|
||||||
completion.setFunctionCompleter([ioManager.getFile, ioManager.expandPath],
|
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 = {
|
var ioManager = {
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ const liberator = (function () //{{{
|
|||||||
{
|
{
|
||||||
argCount: "1",
|
argCount: "1",
|
||||||
bang: true,
|
bang: true,
|
||||||
completer: function (context) completion.dialog(context)
|
completer: function (context, args) completion.dialog(context)
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: move this
|
// TODO: move this
|
||||||
|
|||||||
@@ -263,9 +263,9 @@ function Mappings() //{{{
|
|||||||
completion.setFunctionCompleter(mappings.get,
|
completion.setFunctionCompleter(mappings.get,
|
||||||
[
|
[
|
||||||
null,
|
null,
|
||||||
function (obj, filter, args)
|
function (context, obj, args)
|
||||||
{
|
{
|
||||||
let mode = this.eval(args[0]);
|
let mode = args[0]
|
||||||
return util.Array.flatten(
|
return util.Array.flatten(
|
||||||
[
|
[
|
||||||
[[name, map.description] for ([i, name] in Iterator(map.names))]
|
[[name, map.description] for ([i, name] in Iterator(map.names))]
|
||||||
|
|||||||
@@ -700,7 +700,7 @@ function Options() //{{{
|
|||||||
context.title = ["Option"];
|
context.title = ["Option"];
|
||||||
context.quote = [prefix, util.identity, ""];
|
context.quote = [prefix, util.identity, ""];
|
||||||
context.keys = { text: "names", description: "description" };
|
context.keys = { text: "names", description: "description" };
|
||||||
context.completions = [opt for (opt in opts)];
|
context.completions = opts;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (prefix == "no")
|
else if (prefix == "no")
|
||||||
|
|||||||
Reference in New Issue
Block a user