mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-23 09:17:59 +01:00
More completion stuff.
This commit is contained in:
@@ -240,10 +240,10 @@ function Bookmarks() //{{{
|
|||||||
"Set the default search engine",
|
"Set the default search engine",
|
||||||
"string", "google",
|
"string", "google",
|
||||||
{
|
{
|
||||||
completer: function (filter) completion.url("", "s")[1],
|
completer: function (filter) completion._url(filter, "s").items,
|
||||||
validator: function (value)
|
validator: function (value)
|
||||||
{
|
{
|
||||||
return completion.url("", "s")[1].some(function (s) s[0] == value);
|
return completion._url("", "s").items.some(function (s) s[0] == value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -350,7 +350,6 @@ function Bookmarks() //{{{
|
|||||||
{
|
{
|
||||||
if (bypassCache) // Is this really necessary anymore?
|
if (bypassCache) // Is this really necessary anymore?
|
||||||
cache.load();
|
cache.load();
|
||||||
|
|
||||||
return completion.cached("bookmarks", filter, function () cache.bookmarks, "filterURLArray", tags);
|
return completion.cached("bookmarks", filter, function () cache.bookmarks, "filterURLArray", tags);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -564,7 +564,7 @@ function Buffer() //{{{
|
|||||||
{
|
{
|
||||||
argCount: "?",
|
argCount: "?",
|
||||||
bang: true,
|
bang: true,
|
||||||
completer: function (filter) completion.file(filter)
|
completer: function (filter, bang, args, context) completion.file(context)
|
||||||
});
|
});
|
||||||
|
|
||||||
commands.add(["st[op]"],
|
commands.add(["st[op]"],
|
||||||
@@ -578,7 +578,7 @@ function Buffer() //{{{
|
|||||||
{
|
{
|
||||||
argCount: "?",
|
argCount: "?",
|
||||||
bang: true,
|
bang: true,
|
||||||
completer: function (filter) completion.url(filter, "bhf")
|
completer: function (filter, bang, args, context) completion.url(context, "bhf")
|
||||||
});
|
});
|
||||||
|
|
||||||
commands.add(["zo[om]"],
|
commands.add(["zo[om]"],
|
||||||
|
|||||||
@@ -112,8 +112,7 @@ Command.prototype = {
|
|||||||
commandline.inputMultiline(new RegExp("^" + matches[2] + "$", "m"),
|
commandline.inputMultiline(new RegExp("^" + matches[2] + "$", "m"),
|
||||||
function (args)
|
function (args)
|
||||||
{
|
{
|
||||||
args = this.parseArgs(matches[1] + "\n" + args);
|
args = self.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);
|
||||||
});
|
});
|
||||||
@@ -122,7 +121,6 @@ Command.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
args = this.parseArgs(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);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -32,31 +32,78 @@ modules._cleanEval = function (__liberator_eval_arg, __liberator_eval_tmp)
|
|||||||
return window.eval(__liberator_eval_arg);
|
return window.eval(__liberator_eval_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CompletionContext(editor, offset)
|
function CompletionContext(editor, name, offset)
|
||||||
{
|
{
|
||||||
|
if (!name)
|
||||||
|
name = "";
|
||||||
|
|
||||||
if (editor instanceof arguments.callee)
|
if (editor instanceof arguments.callee)
|
||||||
{
|
{
|
||||||
let parent = editor;
|
let parent = editor;
|
||||||
|
name = parent.name + "/" + name;
|
||||||
|
this.contexts = parent.contexts;
|
||||||
|
if (name in this.contexts)
|
||||||
|
return this.contexts[name];
|
||||||
|
this.contexts[name] = this;
|
||||||
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.parent.tabPressed);
|
this.__defineGetter__("tabPressed", function () this.parent.tabPressed);
|
||||||
this.contexts = this.parent.contexts;
|
this.__defineGetter__("onUpdate", function () this.parent.onUpdate);
|
||||||
|
this.incomplete = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
this.offset = offset || 0;
|
this.offset = offset || 0;
|
||||||
this.tabPressed = false;
|
this.tabPressed = false;
|
||||||
this.contexts = {};
|
this.onUpdate = function () true;
|
||||||
|
this.contexts = { name: this };
|
||||||
|
this.__defineGetter__("incomplete", function () this.contextList.some(function (c) c.parent && c.incomplete));
|
||||||
|
this.reset();
|
||||||
}
|
}
|
||||||
|
this.name = name || "";
|
||||||
|
this._items = []; // FIXME
|
||||||
this.selectionTypes = {};
|
this.selectionTypes = {};
|
||||||
}
|
}
|
||||||
CompletionContext.prototype = {
|
CompletionContext.prototype = {
|
||||||
|
// Temporary
|
||||||
|
get allItems()
|
||||||
|
{
|
||||||
|
let minStart = Math.min.apply(Math, [context.offset for ([k, context] in Iterator(this.contexts)) if (context.items.length && context.hasItems)]);
|
||||||
|
let items = [];
|
||||||
|
for each (let [k, context] in Iterator(this.contexts))
|
||||||
|
{
|
||||||
|
let prefix = this.value.substring(minStart, context.offset);
|
||||||
|
if (context.hasItems)
|
||||||
|
{
|
||||||
|
items.push(context.items.map(function (item) {
|
||||||
|
if (!("text" in item))
|
||||||
|
item = { icon: item[2], text: item[0], description: item[1] };
|
||||||
|
else // FIXME
|
||||||
|
item = util.Array.assocToObj([x for (x in Iterator(item))]);
|
||||||
|
item.text = prefix + item.text;
|
||||||
|
return item;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { start: minStart, items: util.Array.flatten(items) }
|
||||||
|
},
|
||||||
|
|
||||||
get caret() this.editor.selection.getRangeAt(0).startOffset - this.offset,
|
get caret() this.editor.selection.getRangeAt(0).startOffset - this.offset,
|
||||||
|
|
||||||
|
get contextList() [v for ([k, v] in Iterator(this.contexts))],
|
||||||
|
|
||||||
get filter() this.value.substr(this.offset, this.caret),
|
get filter() this.value.substr(this.offset, this.caret),
|
||||||
|
|
||||||
|
get items() this._items,
|
||||||
|
set items(items)
|
||||||
|
{
|
||||||
|
this.hasItems = items.length > 0;
|
||||||
|
this._items = items;
|
||||||
|
this.onUpdate.call(this);
|
||||||
|
},
|
||||||
|
|
||||||
get value() this.editor.rootElement.textContent,
|
get value() this.editor.rootElement.textContent,
|
||||||
|
|
||||||
advance: function (count)
|
advance: function (count)
|
||||||
@@ -64,12 +111,12 @@ CompletionContext.prototype = {
|
|||||||
this.offset += count;
|
this.offset += count;
|
||||||
},
|
},
|
||||||
|
|
||||||
fork: function (name, offset)
|
fork: function (name, offset, completer, self)
|
||||||
{
|
{
|
||||||
if (!(name in this.contexts))
|
let context = new CompletionContext(this, name, offset);
|
||||||
this.contexts[name] = new CompletionContext(this);
|
if (completer)
|
||||||
this.contexts[name].offset = this.offset + offset;
|
return completer.apply(self, [context].concat(Array.slice(arguments, 4)));
|
||||||
return this.contexts[name];
|
return context;
|
||||||
},
|
},
|
||||||
|
|
||||||
highlight: function (start, length, type)
|
highlight: function (start, length, type)
|
||||||
@@ -98,14 +145,23 @@ CompletionContext.prototype = {
|
|||||||
|
|
||||||
reset: function ()
|
reset: function ()
|
||||||
{
|
{
|
||||||
|
let self = this;
|
||||||
|
if (this.parent)
|
||||||
|
throw Error();
|
||||||
// Not ideal.
|
// Not ideal.
|
||||||
for (let type in this.selectionTypes)
|
for each (let type in this.selectionTypes)
|
||||||
this.highlight(0, 0, type);
|
this.highlight(0, 0, type);
|
||||||
this.selectionTypes = {};
|
this.selectionTypes = {};
|
||||||
this.tabPressed = false;
|
this.tabPressed = false;
|
||||||
this.offset = 0;
|
this.offset = 0;
|
||||||
|
//for (let key in (k for ([k, v] in Iterator(self.contexts)) if (v.offset > this.caret)))
|
||||||
|
// delete this.contexts[key];
|
||||||
|
for each (let context in this.contexts)
|
||||||
|
{
|
||||||
|
context.hasItems = false;
|
||||||
|
context.incomplete = false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function Completion() //{{{
|
function Completion() //{{{
|
||||||
@@ -130,23 +186,6 @@ function Completion() //{{{
|
|||||||
var cacheResults = {}
|
var cacheResults = {}
|
||||||
var substrings = [];
|
var substrings = [];
|
||||||
var historyCache = [];
|
var historyCache = [];
|
||||||
var historyResult = null;
|
|
||||||
var completionCache = [];
|
|
||||||
|
|
||||||
var historyTimer = new util.Timer(50, 100, function histTimer() {
|
|
||||||
let comp = [];
|
|
||||||
for (let i in util.range(0, historyResult.matchCount))
|
|
||||||
comp.push([historyResult.getValueAt(i),
|
|
||||||
historyResult.getCommentAt(i),
|
|
||||||
historyResult.getImageAt(i)]);
|
|
||||||
|
|
||||||
//let foo = ["", "IGNORED", "FAILURE", "NOMATCH", "SUCCESS", "NOMATCH_ONGOING", "SUCCESS_ONGOING"];
|
|
||||||
|
|
||||||
// TODO: we need to have a "completionCacheAfter" to allow cpt=slf
|
|
||||||
historyCache = comp;
|
|
||||||
commandline.setCompletions({ get items() completionCache.concat(historyCache),
|
|
||||||
incompleteResult: historyResult.searchResult >= historyResult.RESULT_NOMATCH_ONGOING ? true : false });
|
|
||||||
});
|
|
||||||
|
|
||||||
function Javascript()
|
function Javascript()
|
||||||
{
|
{
|
||||||
@@ -228,6 +267,8 @@ function Completion() //{{{
|
|||||||
// Things we can dereference
|
// Things we can dereference
|
||||||
if (["object", "string", "function"].indexOf(typeof obj) == -1)
|
if (["object", "string", "function"].indexOf(typeof obj) == -1)
|
||||||
continue;
|
continue;
|
||||||
|
if (!obj)
|
||||||
|
continue;
|
||||||
|
|
||||||
// XPCNativeWrappers, etc, don't show all accessible
|
// XPCNativeWrappers, etc, don't show all accessible
|
||||||
// members until they're accessed, so, we look at
|
// members until they're accessed, so, we look at
|
||||||
@@ -431,7 +472,7 @@ function Completion() //{{{
|
|||||||
lastIdx = i;
|
lastIdx = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.complete = function complete(context)
|
this.complete = function (context)
|
||||||
{
|
{
|
||||||
this.context = context;
|
this.context = context;
|
||||||
let string = context.filter;
|
let string = context.filter;
|
||||||
@@ -446,10 +487,10 @@ function Completion() //{{{
|
|||||||
catch (e)
|
catch (e)
|
||||||
{
|
{
|
||||||
if (e.message != "Invalid JS")
|
if (e.message != "Invalid JS")
|
||||||
Components.utils.reportError(e);
|
liberator.reportError(e);
|
||||||
// liberator.dump(util.escapeString(string) + ": " + e + "\n" + e.stack);
|
// liberator.dump(util.escapeString(string) + ": " + e + "\n" + e.stack);
|
||||||
lastIdx = 0;
|
lastIdx = 0;
|
||||||
return [0, []];
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Okay, have parse stack. Figure out what we're completing. */
|
/* Okay, have parse stack. Figure out what we're completing. */
|
||||||
@@ -488,7 +529,7 @@ function Completion() //{{{
|
|||||||
cacheKey = str.substring(statement, dot);
|
cacheKey = str.substring(statement, dot);
|
||||||
obj = self.eval(s, cacheKey, obj);
|
obj = self.eval(s, cacheKey, obj);
|
||||||
}
|
}
|
||||||
return obj;
|
return [[obj], str.substring(statement, stop + 1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getObjKey(frame)
|
function getObjKey(frame)
|
||||||
@@ -498,7 +539,7 @@ function Completion() //{{{
|
|||||||
let end = (frame == -1 ? lastIdx : get(frame + 1)[OFFSET]);
|
let end = (frame == -1 ? lastIdx : get(frame + 1)[OFFSET]);
|
||||||
|
|
||||||
cacheKey = null;
|
cacheKey = null;
|
||||||
let obj = [modules, window]; // Default objects;
|
let obj = [[modules, "modules"], [window, "window"]]; // Default objects;
|
||||||
/* Is this an object dereference? */
|
/* Is this an object dereference? */
|
||||||
if (dot < statement) // No.
|
if (dot < statement) // No.
|
||||||
dot = statement - 1;
|
dot = statement - 1;
|
||||||
@@ -509,6 +550,16 @@ function Completion() //{{{
|
|||||||
return [dot + 1 + space.length, obj, key];
|
return [dot + 1 + space.length, obj, key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function complete(objects, key, compl, string, last)
|
||||||
|
{
|
||||||
|
for (let [,obj] in Iterator(objects))
|
||||||
|
{
|
||||||
|
let ctxt = this.context.fork(obj[1], top[OFFSET]);
|
||||||
|
ctxt.title = [obj[1]];
|
||||||
|
ctxt.items = this.filter(compl || this.objectKeys(obj[0]), key + (string || ""), last, key.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// In a string. Check if we're dereferencing an object.
|
// In a string. Check if we're dereferencing an object.
|
||||||
// Otherwise, do nothing.
|
// Otherwise, do nothing.
|
||||||
if (last == "'" || last == '"')
|
if (last == "'" || last == '"')
|
||||||
@@ -537,7 +588,7 @@ function Completion() //{{{
|
|||||||
// Yes. If the [ starts at the begining of a logical
|
// Yes. If the [ starts at the begining of a logical
|
||||||
// statement, we're in an array literal, and we're done.
|
// statement, we're in an array literal, and we're done.
|
||||||
if (get(-3, 0, STATEMENTS) == get(-2)[OFFSET])
|
if (get(-3, 0, STATEMENTS) == get(-2)[OFFSET])
|
||||||
return [0, []];
|
return;
|
||||||
|
|
||||||
// Begining of the statement upto the opening [
|
// Begining of the statement upto the opening [
|
||||||
let obj = getObj(-3, get(-2)[OFFSET]);
|
let obj = getObj(-3, get(-2)[OFFSET]);
|
||||||
@@ -546,8 +597,7 @@ function Completion() //{{{
|
|||||||
// Now eval the key, to process any referenced variables.
|
// Now eval the key, to process any referenced variables.
|
||||||
key = this.eval(key);
|
key = this.eval(key);
|
||||||
|
|
||||||
let compl = this.objectKeys(obj);
|
return complete.call(this, obj, key, null, string, last);
|
||||||
return [top[OFFSET], this.filter(compl, key + string, last, key.length)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is this a function call?
|
// Is this a function call?
|
||||||
@@ -561,7 +611,7 @@ function Completion() //{{{
|
|||||||
|
|
||||||
// Does the opening "(" mark a function call?
|
// Does the opening "(" mark a function call?
|
||||||
if (get(-3, 0, FUNCTIONS) != get(-2)[OFFSET])
|
if (get(-3, 0, FUNCTIONS) != get(-2)[OFFSET])
|
||||||
return [0, []]; // No. We're done.
|
return; // No. We're done.
|
||||||
|
|
||||||
let [offset, obj, func] = getObjKey(-3);
|
let [offset, obj, func] = getObjKey(-3);
|
||||||
let key = str.substring(get(-2, 0, STATEMENTS), top[OFFSET]) + "''";
|
let key = str.substring(get(-2, 0, STATEMENTS), top[OFFSET]) + "''";
|
||||||
@@ -574,7 +624,7 @@ function Completion() //{{{
|
|||||||
if (!completer)
|
if (!completer)
|
||||||
completer = this.completers[func];
|
completer = this.completers[func];
|
||||||
if (!completer)
|
if (!completer)
|
||||||
return [0, []];
|
return;
|
||||||
|
|
||||||
// Split up the arguments
|
// Split up the arguments
|
||||||
let prev = get(-2)[OFFSET];
|
let prev = get(-2)[OFFSET];
|
||||||
@@ -590,11 +640,11 @@ function Completion() //{{{
|
|||||||
if (!(compl instanceof Array))
|
if (!(compl instanceof Array))
|
||||||
compl = [v for (v in compl)];
|
compl = [v for (v in compl)];
|
||||||
key = this.eval(key);
|
key = this.eval(key);
|
||||||
return [top[OFFSET], this.filter(compl, key + string, last, key.length)];
|
return complete.call(this, obj, key, compl, string, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
return [0, []];
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -603,23 +653,28 @@ function Completion() //{{{
|
|||||||
* key = "baz"
|
* key = "baz"
|
||||||
*
|
*
|
||||||
* str = "foo"
|
* str = "foo"
|
||||||
* obj = [liberator, window]
|
* obj = [modules, window]
|
||||||
* key = "foo"
|
* key = "foo"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let [offset, obj, key] = getObjKey(-1);
|
let [offset, obj, key] = getObjKey(-1);
|
||||||
|
|
||||||
if (!/^(?:\w[\w\d]*)?$/.test(key))
|
if (!/^(?:\w[\w\d]*)?$/.test(key))
|
||||||
return [0, []]; /* Not a word. Forget it. Can this even happen? */
|
return; /* Not a word. Forget it. Can this even happen? */
|
||||||
|
|
||||||
let compl = this.objectKeys(obj);
|
top[OFFSET] = offset;
|
||||||
return [offset, this.filter(compl, key)];
|
return complete.call(this, obj, key);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let javascript = new Javascript();
|
let javascript = new Javascript();
|
||||||
|
|
||||||
function buildSubstrings(str, filter)
|
function buildSubstrings(str, filter)
|
||||||
{
|
{
|
||||||
|
if (substrings.length)
|
||||||
|
{
|
||||||
|
substrings = substrings.filter(function strIndex(s) str.indexOf(s) >= 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (filter == "")
|
if (filter == "")
|
||||||
return;
|
return;
|
||||||
let length = filter.length;
|
let length = filter.length;
|
||||||
@@ -662,12 +717,7 @@ function Completion() //{{{
|
|||||||
filtered.push([compitem, item[1], favicon ? item[2] : null]);
|
filtered.push([compitem, item[1], favicon ? item[2] : null]);
|
||||||
|
|
||||||
if (longest)
|
if (longest)
|
||||||
{
|
buildSubstrings(str, filter);
|
||||||
if (substrings.length == 0)
|
|
||||||
buildSubstrings(str, filter);
|
|
||||||
else
|
|
||||||
substrings = substrings.filter(function strIndex(s) str.indexOf(s) >= 0);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -740,19 +790,9 @@ function Completion() //{{{
|
|||||||
|
|
||||||
// returns the longest common substring
|
// returns the longest common substring
|
||||||
// used for the 'longest' setting for wildmode
|
// used for the 'longest' setting for wildmode
|
||||||
getLongestSubstring: function getLongestSubstring()
|
get longestSubstring () substrings.reduce(function (a, b) a.length > b.length ? a : b, ""),
|
||||||
{
|
|
||||||
if (substrings.length == 0)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
var longest = substrings[0];
|
get substrings() substrings.slice(),
|
||||||
for (let i = 1; i < substrings.length; i++)
|
|
||||||
{
|
|
||||||
if (substrings[i].length > longest.length)
|
|
||||||
longest = substrings[i];
|
|
||||||
}
|
|
||||||
return longest;
|
|
||||||
},
|
|
||||||
|
|
||||||
// generic filter function, also builds substrings needed
|
// generic filter function, also builds substrings needed
|
||||||
// for :set wildmode=list:longest, if necessary
|
// for :set wildmode=list:longest, if necessary
|
||||||
@@ -853,10 +893,7 @@ function Completion() //{{{
|
|||||||
filtered.push(elem);
|
filtered.push(elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
filtered = filtered.concat(additionalCompletions);
|
return filtered.concat(additionalCompletions);
|
||||||
if (options.get("wildoptions").has("sort"))
|
|
||||||
filtered = filtered.sort(function (a, b) util.compareIgnoreCase(a[0], b[0]));;
|
|
||||||
return filtered;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// generic helper function which checks if the given "items" array pass "filter"
|
// generic helper function which checks if the given "items" array pass "filter"
|
||||||
@@ -963,6 +1000,7 @@ function Completion() //{{{
|
|||||||
let rtp = options["runtimepath"].split(",");
|
let rtp = options["runtimepath"].split(",");
|
||||||
|
|
||||||
rtp.forEach(function (path) {
|
rtp.forEach(function (path) {
|
||||||
|
// FIXME: Now! Very, very broken.
|
||||||
schemes = schemes.concat([[c[0].replace(/\.vimp$/, ""), ""]
|
schemes = schemes.concat([[c[0].replace(/\.vimp$/, ""), ""]
|
||||||
for each (c in completion.file(path + "/colors/", true)[1])]);
|
for each (c in completion.file(path + "/colors/", true)[1])]);
|
||||||
});
|
});
|
||||||
@@ -972,15 +1010,20 @@ function Completion() //{{{
|
|||||||
|
|
||||||
command: function command(context)
|
command: function command(context)
|
||||||
{
|
{
|
||||||
|
context.title = ["Command"];
|
||||||
if (!context.filter)
|
if (!context.filter)
|
||||||
return { start: 0, items: [[c.name, c.description] for (c in commands)] };
|
context.items = [[c.name, c.description] for (c in commands)];
|
||||||
else
|
else
|
||||||
return { start: 0, items: this.filter([[c.longNames, c.description] for (c in commands)], context.filter, true) };
|
context.items = this.filter([[c.longNames, c.description] for (c in commands)], context.filter, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
dialog: function dialog(filter) [0, this.filter(config.dialogs, filter)],
|
dialog: function dialog(filter) [0, this.filter(config.dialogs, filter)],
|
||||||
|
|
||||||
directory: function (filter, tail) [0, this.file(filter, tail)[1].filter(function (f) f[1] == "Directory")],
|
directory: function (context, tail)
|
||||||
|
{
|
||||||
|
this.file(context, tail);
|
||||||
|
context.items = context.items.filter(function (i) i[1] == "Directory");
|
||||||
|
},
|
||||||
|
|
||||||
environment: function environment(filter)
|
environment: function environment(filter)
|
||||||
{
|
{
|
||||||
@@ -1014,7 +1057,8 @@ function Completion() //{{{
|
|||||||
// then get completions of the command name
|
// then get completions of the command name
|
||||||
let [count, cmd, special, args] = commands.parseCommand(context.filter);
|
let [count, cmd, special, args] = commands.parseCommand(context.filter);
|
||||||
let [, prefix, junk] = context.filter.match(/^(:*\d*)\w*(.?)/) || [];
|
let [, prefix, junk] = context.filter.match(/^(:*\d*)\w*(.?)/) || [];
|
||||||
context.advance(junk.length)
|
context.advance(prefix.length)
|
||||||
|
context.items = []; // XXX
|
||||||
if (!junk)
|
if (!junk)
|
||||||
return this.command(context);
|
return this.command(context);
|
||||||
|
|
||||||
@@ -1023,40 +1067,38 @@ function Completion() //{{{
|
|||||||
let compObject = { start: 0, items: [] };
|
let compObject = { start: 0, items: [] };
|
||||||
if (command && command.completer)
|
if (command && command.completer)
|
||||||
{
|
{
|
||||||
[prefix] = context.filter.match(/^(?:\w+[\s!]|!)\s*/);
|
[prefix] = context.filter.match(/^(?:\w*[\s!]|!)\s*/);
|
||||||
context.advance((prefix || "").length);
|
context = context.fork(cmd, prefix.length);
|
||||||
|
this.filterString = context.filter;
|
||||||
args = command.parseArgs(context.filter, true);
|
args = command.parseArgs(context.filter, true);
|
||||||
liberator.dump(args);
|
|
||||||
if (args)
|
if (args)
|
||||||
{
|
{
|
||||||
// XXX, XXX, XXX
|
// XXX, XXX, XXX
|
||||||
compObject = command.completer.call(command, args.string, special, args, context);
|
compObject = command.completer.call(command, args.string, special, args, context);
|
||||||
liberator.dump(compObject);
|
|
||||||
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] };
|
||||||
if (compObject == null)
|
|
||||||
compObject = { start: context.offset, items: context.items };
|
|
||||||
else
|
|
||||||
compObject.start += context.offset;
|
|
||||||
if (args.completions)
|
if (args.completions)
|
||||||
{
|
{
|
||||||
if (!compObject.items.length)
|
let argContext = context.fork("args", args.completionStart);
|
||||||
compObject.start = args.completeStart + context.offset;
|
argContext.title = [args.completeOpt || "Options"];
|
||||||
if (args.completeStart + context.offset == compObject.start)
|
argContext.items = args.completions;
|
||||||
compObject.items = args.completions.concat(compObject.items);
|
}
|
||||||
|
if (compObject != null)
|
||||||
|
{
|
||||||
|
context.advance(compObject.start);
|
||||||
|
context.title = ["Completions"];
|
||||||
|
context.items = compObject.items;
|
||||||
}
|
}
|
||||||
liberator.dump(compObject);
|
|
||||||
liberator.dump("\n");
|
|
||||||
}
|
}
|
||||||
|
//liberator.dump([[v.name, v.offset, v.items.length, v.hasItems] for each (v in context.contexts)]);
|
||||||
}
|
}
|
||||||
return compObject;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: support file:// and \ or / path separators on both platforms
|
// TODO: support file:// and \ or / path separators on both platforms
|
||||||
// if "tail" is true, only return names without any directory components
|
// if "tail" is true, only return names without any directory components
|
||||||
file: function file(filter, tail)
|
file: function file(context, tail)
|
||||||
{
|
{
|
||||||
let [, dir, compl] = filter.match(/^((?:.*[\/\\])?)(.*?)$/);
|
let [dir] = context.filter.match(/^(?:.*[\/\\])?/);
|
||||||
// dir == "" is expanded inside readDirectory to the current dir
|
// dir == "" is expanded inside readDirectory to the current dir
|
||||||
|
|
||||||
let generate = function ()
|
let generate = function ()
|
||||||
@@ -1085,37 +1127,35 @@ function Completion() //{{{
|
|||||||
return mapped;
|
return mapped;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
context.title = ["Path", "Type"];
|
||||||
if (tail)
|
if (tail)
|
||||||
return [dir.length, this.cached("file-" + dir, compl, generate, "filter", [true])];
|
context.advance(dir.length);
|
||||||
else
|
context.items = this.cached("file-" + dir, context.filter, generate, "filter", true);
|
||||||
return [0, this.cached("file-" + dir, filter, generate, "filter", [true])];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
help: function help(filter)
|
help: function help(filter)
|
||||||
{
|
{
|
||||||
var files = config.helpFiles;
|
let res = [];
|
||||||
var res = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < files.length; i++)
|
for (let [, file] in Iterator(config.helpFiles))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var xmlhttp = new XMLHttpRequest();
|
var xmlhttp = new XMLHttpRequest();
|
||||||
xmlhttp.open("GET", "chrome://liberator/locale/" + files[i], false);
|
xmlhttp.open("GET", "chrome://liberator/locale/" + file, false);
|
||||||
xmlhttp.send(null);
|
xmlhttp.send(null);
|
||||||
}
|
}
|
||||||
catch (e)
|
catch (e)
|
||||||
{
|
{
|
||||||
liberator.log("Error opening chrome://liberator/locale/" + files[i], 1);
|
liberator.log("Error opening chrome://liberator/locale/" + file, 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var doc = xmlhttp.responseXML;
|
let doc = xmlhttp.responseXML;
|
||||||
var elems = doc.getElementsByClassName("tag");
|
res.push(Array.map(doc.getElementsByClassName("tag"),
|
||||||
for (let j = 0; j < elems.length; j++)
|
function (elem) [elem.textContent, file]));
|
||||||
res.push([elems[j].textContent, files[i]]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [0, this.filter(res, filter)];
|
return [0, this.filter(util.Array.flatten(res), filter)];
|
||||||
},
|
},
|
||||||
|
|
||||||
highlightGroup: function highlightGroup(filter) commands.get("highlight").completer(filter), // XXX
|
highlightGroup: function highlightGroup(filter) commands.get("highlight").completer(filter), // XXX
|
||||||
@@ -1140,11 +1180,14 @@ function Completion() //{{{
|
|||||||
|
|
||||||
preference: function preference(filter) commands.get("set").completer(filter, true), // XXX
|
preference: function preference(filter) commands.get("set").completer(filter, true), // XXX
|
||||||
|
|
||||||
search: function search(filter)
|
search: function search(context)
|
||||||
{
|
{
|
||||||
let [, keyword, args] = filter.match(/^\s*(\S*)\s*(.*)/);
|
let [, keyword, args] = context.filter.match(/^\s*(\S*)\s*(.*)/);
|
||||||
let keywords = bookmarks.getKeywords();
|
let keywords = bookmarks.getKeywords();
|
||||||
let engines = this.filter(keywords.concat(bookmarks.getSearchEngines()), filter, false, true);
|
let engines = this.filter(keywords.concat(bookmarks.getSearchEngines()), context.filter, false, true);
|
||||||
|
|
||||||
|
context.title = ["Search Keywords"];
|
||||||
|
context.items = engines;
|
||||||
|
|
||||||
// NOTE: While i like the result of the code, due to the History simplification
|
// NOTE: While i like the result of the code, due to the History simplification
|
||||||
// that code is too slow to be here. We might use a direct Places History query instead for better speed
|
// that code is too slow to be here. We might use a direct Places History query instead for better speed
|
||||||
@@ -1172,58 +1215,50 @@ function Completion() //{{{
|
|||||||
// let searches = this.cached("searches-" + keyword, args, generate, "filter", [false, true]);
|
// let searches = this.cached("searches-" + keyword, args, generate, "filter", [false, true]);
|
||||||
// searches = searches.map(function (a) (a = a.concat(), a[0] = keyword + " " + a[0], a));
|
// searches = searches.map(function (a) (a = a.concat(), a[0] = keyword + " " + a[0], a));
|
||||||
// return [0, searches.concat(engines)];
|
// return [0, searches.concat(engines)];
|
||||||
return [0, engines];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// XXX: Move to bookmarks.js?
|
// XXX: Move to bookmarks.js?
|
||||||
searchEngineSuggest: function searchEngineSuggest(filter, engineAliases)
|
searchEngineSuggest: function (context, engineAliases)
|
||||||
{
|
{
|
||||||
this.filterString = filter;
|
this.filterString = context.filter;
|
||||||
if (!filter)
|
if (!filter)
|
||||||
return [0, []];
|
return [0, []];
|
||||||
|
|
||||||
var engineList = (engineAliases || options["suggestengines"]).split(",");
|
let engineList = (engineAliases || options["suggestengines"] || "google").split(",");
|
||||||
var responseType = "application/x-suggestions+json";
|
let responseType = "application/x-suggestions+json";
|
||||||
var ss = Components.classes["@mozilla.org/browser/search-service;1"]
|
let ss = Components.classes["@mozilla.org/browser/search-service;1"]
|
||||||
.getService(Components.interfaces.nsIBrowserSearchService);
|
.getService(Components.interfaces.nsIBrowserSearchService);
|
||||||
|
let matches = query.match(RegExp("^\s*(" + name + "\\s+)(.*)$")) || [];
|
||||||
|
if (matches[1])
|
||||||
|
context.advance(matches[1].length);
|
||||||
|
query = context.filter;
|
||||||
|
|
||||||
var completions = [];
|
let completions = [];
|
||||||
engineList.forEach(function (name) {
|
engineList.forEach(function (name) {
|
||||||
var query = filter;
|
let engine = ss.getEngineByAlias(name);
|
||||||
var queryURI;
|
|
||||||
var engine = ss.getEngineByAlias(name);
|
|
||||||
var reg = new RegExp("^\s*(" + name + "\\s+)(.*)$");
|
|
||||||
var matches = query.match(reg);
|
|
||||||
if (matches)
|
|
||||||
query = matches[2];
|
|
||||||
|
|
||||||
if (engine && engine.supportsResponseType(responseType))
|
if (engine && engine.supportsResponseType(responseType))
|
||||||
queryURI = engine.getSubmission(query, responseType).uri.asciiSpec;
|
var queryURI = engine.getSubmission(query, responseType).uri.asciiSpec;
|
||||||
else
|
else
|
||||||
return [0, []];
|
return;
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest();
|
let xhr = new XMLHttpRequest();
|
||||||
xhr.open("GET", queryURI, false);
|
xhr.open("GET", queryURI, false);
|
||||||
xhr.send(null);
|
xhr.send(null);
|
||||||
|
|
||||||
var json = Components.classes["@mozilla.org/dom/json;1"]
|
let json = Components.classes["@mozilla.org/dom/json;1"]
|
||||||
.createInstance(Components.interfaces.nsIJSON);
|
.createInstance(Components.interfaces.nsIJSON);
|
||||||
var results = json.decode(xhr.responseText)[1];
|
let results = json.decode(xhr.responseText)[1];
|
||||||
if (!results)
|
if (!results)
|
||||||
return [0, []];
|
return;
|
||||||
|
|
||||||
results.forEach(function (item) {
|
let ctxt = context.fork(engine.name, (matches[1] || "").length);
|
||||||
// make sure we receive strings, otherwise a man-in-the-middle attack
|
ctxt.title = [engine.name + " Suggestions"];
|
||||||
// could return objects which toString() method could be called to
|
// make sure we receive strings, otherwise a man-in-the-middle attack
|
||||||
// execute untrusted code
|
// could return objects which toString() method could be called to
|
||||||
if (typeof item != "string")
|
// execute untrusted code
|
||||||
return [0, []];
|
ctxt.items = [[item, ""] for ([k, item] in results) if (typeof item == "string")];
|
||||||
|
|
||||||
completions.push([(matches ? matches[1] : "") + item, engine.name + " suggestion"]);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return [0, completions];
|
|
||||||
},
|
},
|
||||||
|
|
||||||
shellCommand: function shellCommand(filter)
|
shellCommand: function shellCommand(filter)
|
||||||
@@ -1288,84 +1323,67 @@ function Completion() //{{{
|
|||||||
// may consist of search engines, filenames, bookmarks and history,
|
// may consist of search engines, filenames, bookmarks and history,
|
||||||
// depending on the 'complete' option
|
// depending on the 'complete' option
|
||||||
// if the 'complete' argument is passed like "h", it temporarily overrides the complete option
|
// if the 'complete' argument is passed like "h", it temporarily overrides the complete option
|
||||||
url: function url(filter, complete)
|
url: function url(context, complete)
|
||||||
{
|
{
|
||||||
function getMoreItems(count, maxTime)
|
this.filterString = context.filter;
|
||||||
{
|
|
||||||
maxTime = maxTime || 5000; // maximum time to wait, default 5 sec
|
|
||||||
count = count || 10;
|
|
||||||
|
|
||||||
var completions = [];
|
|
||||||
historyResult = null;
|
|
||||||
let then = new Date().getTime();
|
|
||||||
for (let now = then; now - then < maxTime; now = new Date().getTime())
|
|
||||||
{
|
|
||||||
liberator.threadYield();
|
|
||||||
if (!historyResult)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (historyResult.searchResult == historyResult.RESULT_SUCCESS ||
|
|
||||||
historyResult.searchResult == historyResult.RESULT_NOMATCH ||
|
|
||||||
(historyResult.searchResult == historyResult.RESULT_SUCCESS_ONGOING &&
|
|
||||||
historyResult.matchCount >= count + numLocationCompletions))
|
|
||||||
{
|
|
||||||
//liberator.dump("Got " + historyResult.matchCount + " more results after " + (now - then) + " ms with result: " + historyResult.searchResult);
|
|
||||||
//completionService.stopSearch();
|
|
||||||
for (let i in util.range(numLocationCompletions, historyResult.matchCount))
|
|
||||||
completions.push([historyResult.getValueAt(i),
|
|
||||||
historyResult.getCommentAt(i),
|
|
||||||
historyResult.getImageAt(i)]);
|
|
||||||
numLocationCompletions = historyResult.matchCount;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return completions;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.filterString = filter;
|
|
||||||
var completions = [];
|
|
||||||
var numLocationCompletions = 0; // how many async completions did we already return to the caller?
|
var numLocationCompletions = 0; // how many async completions did we already return to the caller?
|
||||||
var start = 0;
|
var start = 0;
|
||||||
var skip = filter.match("^(.*" + options["urlseparator"] + ")(.*)"); // start after the last 'urlseparator'
|
var skip = context.filter.match("^.*" + options["urlseparator"]); // start after the last 'urlseparator'
|
||||||
if (skip)
|
if (skip)
|
||||||
{
|
context.advance(skip[0].length);
|
||||||
start += skip[1].length;
|
|
||||||
filter = skip[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
var cpt = complete || options["complete"];
|
let opts = {
|
||||||
var suggestEngineAlias = options["suggestengines"] || "google";
|
s: this.search,
|
||||||
// join all completion arrays together
|
f: this.file,
|
||||||
for (let c in util.Array.iterator(cpt))
|
S: this.searchEngineSuggest,
|
||||||
{
|
b: function (context)
|
||||||
if (c == "s")
|
|
||||||
completions = completions.concat(this.search(filter)[1]);
|
|
||||||
else if (c == "f")
|
|
||||||
completions = completions.concat(this.file(filter, false)[1]);
|
|
||||||
else if (c == "S")
|
|
||||||
completions = completions.concat(this.searchEngineSuggest(filter, suggestEngineAlias)[1]);
|
|
||||||
else if (c == "b")
|
|
||||||
completions = completions.concat(bookmarks.get(filter));
|
|
||||||
else if (c == "l" && completionService) // add completions like Firefox's smart location bar
|
|
||||||
{
|
{
|
||||||
historyCache = [];
|
context.title = ["Bookmark", "Title"];
|
||||||
completionCache = completions.slice(); // make copy of current results
|
context.items = bookmarks.get(context.filter)
|
||||||
|
},
|
||||||
|
l: function (context)
|
||||||
|
{
|
||||||
|
if (!completionService)
|
||||||
|
return
|
||||||
|
context.title = ["Smart Completions"];
|
||||||
|
context.incomplete = true;
|
||||||
|
if (context.items.length)
|
||||||
|
context.hasItems = true; // XXX
|
||||||
|
let timer = new util.Timer(50, 100, function () {
|
||||||
|
let result = context.result;
|
||||||
|
context.items = [
|
||||||
|
[result.getValueAt(i), result.getCommentAt(i), result.getImageAt(i)]
|
||||||
|
for (i in util.range(0, result.matchCount))
|
||||||
|
];
|
||||||
|
context.incomplete = result.searchResult >= result.RESULT_NOMATCH_ONGOING;
|
||||||
|
let filter = context.filter;
|
||||||
|
context.items.forEach(function ([item]) buildSubstrings(item, filter));
|
||||||
|
});
|
||||||
completionService.stopSearch();
|
completionService.stopSearch();
|
||||||
completionService.startSearch(filter, "", historyResult, {
|
completionService.startSearch(context.filter, "", context.result, {
|
||||||
onSearchResult: function onSearchResult(search, result) {
|
onSearchResult: function onSearchResult(search, result) {
|
||||||
historyResult = result;
|
context.result = result;
|
||||||
//liberator.dump("Search result in " + historyResult.matchCount + " results with retval: " + historyResult.searchResult);
|
timer.tell();
|
||||||
historyTimer.tell();
|
|
||||||
if (result.searchResult <= result.RESULT_SUCCESS)
|
if (result.searchResult <= result.RESULT_SUCCESS)
|
||||||
historyTimer.flush();
|
timer.flush();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
Array.forEach(complete || options["complete"],
|
||||||
|
function (c) context.fork(c, 0, opts[c], completion));
|
||||||
|
},
|
||||||
|
|
||||||
// TODO: incomplete result should be set conditionally
|
// FIXME: Temporary
|
||||||
return { start: start, items: completions, getMoreItems: getMoreItems, incompleteResult: true };
|
_url: function (filter, complete)
|
||||||
|
{
|
||||||
|
let context = new CompletionContext({
|
||||||
|
selection: { getRangeAt: function () ({ startOffset: filter.length }) },
|
||||||
|
rootElement: { textContent: filter }
|
||||||
|
});
|
||||||
|
this.url(context, complete);
|
||||||
|
return context.allItems;
|
||||||
},
|
},
|
||||||
|
|
||||||
userCommand: function userCommand(filter)
|
userCommand: function userCommand(filter)
|
||||||
|
|||||||
@@ -218,13 +218,13 @@ function AutoCommands() //{{{
|
|||||||
|
|
||||||
var list = template.generic(
|
var list = template.generic(
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr class="hl-Title">
|
||||||
<td class="hl-Title" colspan="2">----- Auto Commands -----</td>
|
<td colspan="2">----- Auto Commands -----</td>
|
||||||
</tr>
|
</tr>
|
||||||
{
|
{
|
||||||
template.map(cmds, function ([event, items])
|
template.map(cmds, function ([event, items])
|
||||||
<tr>
|
<tr class="hl-Title">
|
||||||
<td class="hl-Title" colspan="2">{event}</td>
|
<td colspan="2">{event}</td>
|
||||||
</tr>
|
</tr>
|
||||||
+
|
+
|
||||||
template.map(items, function (item)
|
template.map(items, function (item)
|
||||||
@@ -562,9 +562,7 @@ function Events() //{{{
|
|||||||
liberator.echoerr("Interrupted");
|
liberator.echoerr("Interrupted");
|
||||||
else
|
else
|
||||||
liberator.echoerr("Processing " + event.type + " event: " + (e.echoerr || e));
|
liberator.echoerr("Processing " + event.type + " event: " + (e.echoerr || e));
|
||||||
liberator.dump(e);
|
liberator.reportError(e);
|
||||||
if (Components.utils.reportError)
|
|
||||||
Components.utils.reportError(e);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1128,7 +1126,7 @@ function Events() //{{{
|
|||||||
// if (events.wantsModeReset)
|
// if (events.wantsModeReset)
|
||||||
// {
|
// {
|
||||||
// events.wantsModeReset = false;
|
// events.wantsModeReset = false;
|
||||||
modes.reset();
|
modes.reset();
|
||||||
// }
|
// }
|
||||||
// }, 0);
|
// }, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ function IO() //{{{
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
argCount: "?",
|
argCount: "?",
|
||||||
completer: function (filter) completion.file(filter, true),
|
completer: function (filter, bang, args, context) completion.file(context, true),
|
||||||
literal: true
|
literal: true
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -268,7 +268,7 @@ function IO() //{{{
|
|||||||
{
|
{
|
||||||
argCount: "?",
|
argCount: "?",
|
||||||
bang: true,
|
bang: true,
|
||||||
completer: function (filter) completion.file(filter, true)
|
completer: function (filter, bang, args, context) completion.file(context, true)
|
||||||
});
|
});
|
||||||
|
|
||||||
commands.add(["runt[ime]"],
|
commands.add(["runt[ime]"],
|
||||||
@@ -301,7 +301,7 @@ function IO() //{{{
|
|||||||
{
|
{
|
||||||
argCount: "1",
|
argCount: "1",
|
||||||
bang: true,
|
bang: true,
|
||||||
completer: function (filter) completion.file(filter, true)
|
completer: function (filter, bang, args, context) completion.file(context, true)
|
||||||
});
|
});
|
||||||
|
|
||||||
commands.add(["!", "run"],
|
commands.add(["!", "run"],
|
||||||
@@ -893,8 +893,7 @@ lookup:
|
|||||||
catch (e)
|
catch (e)
|
||||||
{
|
{
|
||||||
let message = "Sourcing file: " + (e.echoerr || file.path + ": " + e);
|
let message = "Sourcing file: " + (e.echoerr || file.path + ": " + e);
|
||||||
if (Components.utils.reportError)
|
liberator.reportError(e);
|
||||||
Components.utils.reportError(e);
|
|
||||||
if (!silent)
|
if (!silent)
|
||||||
liberator.echoerr(message);
|
liberator.echoerr(message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,9 +57,7 @@ const liberator = (function () //{{{
|
|||||||
catch (e)
|
catch (e)
|
||||||
{
|
{
|
||||||
toJavaScriptConsole();
|
toJavaScriptConsole();
|
||||||
if (Components.utils.reportError)
|
liberator.reportError(e);
|
||||||
Components.utils.reportError(e);
|
|
||||||
liberator.dump(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1087,6 +1085,23 @@ const liberator = (function () //{{{
|
|||||||
goQuitApplication();
|
goQuitApplication();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
reportError: function (error)
|
||||||
|
{
|
||||||
|
if (Components.utils.reportError)
|
||||||
|
Components.utils.reportError(error);
|
||||||
|
let obj = {
|
||||||
|
toString: function () error.toString(),
|
||||||
|
stack: { toString: function () "\n" + error.stack.replace(/^/mg, "\t") }
|
||||||
|
};
|
||||||
|
for (let [k, v] in Iterator(error))
|
||||||
|
{
|
||||||
|
if (!(k in obj))
|
||||||
|
obj[k] = v;
|
||||||
|
}
|
||||||
|
liberator.dump(obj);
|
||||||
|
liberator.dump("");
|
||||||
|
},
|
||||||
|
|
||||||
restart: function ()
|
restart: function ()
|
||||||
{
|
{
|
||||||
const nsIAppStartup = Components.interfaces.nsIAppStartup;
|
const nsIAppStartup = Components.interfaces.nsIAppStartup;
|
||||||
|
|||||||
@@ -548,7 +548,7 @@ function Tabs() //{{{
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
bang: true,
|
bang: true,
|
||||||
completer: function (filter) completion.url(filter)
|
completer: function (filter, bang, args, context) completion.url(context)
|
||||||
});
|
});
|
||||||
|
|
||||||
commands.add(["tabde[tach]"],
|
commands.add(["tabde[tach]"],
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ const template = {
|
|||||||
// that we cannot even try/catch it
|
// that we cannot even try/catch it
|
||||||
if (/^\[JavaPackage.*\]$/.test(arg))
|
if (/^\[JavaPackage.*\]$/.test(arg))
|
||||||
return <>[JavaPackage]</>;
|
return <>[JavaPackage]</>;
|
||||||
if (processStrings)
|
if (processStrings && false)
|
||||||
arg = String(arg).replace("\n", "\\n", "g");
|
arg = String(arg).replace("\n", "\\n", "g");
|
||||||
return <span class="hl-Object">{arg}</span>;
|
return <span class="hl-Object">{arg}</span>;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -117,7 +117,8 @@ function CommandLine() //{{{
|
|||||||
if (events.feedingKeys)
|
if (events.feedingKeys)
|
||||||
return;
|
return;
|
||||||
completionContext.reset();
|
completionContext.reset();
|
||||||
commandline.setCompletions(completion.ex(completionContext));
|
completionContext.fork("ex", 0, completion.ex, completion);
|
||||||
|
commandline.setCompletions(completionContext.allItems);
|
||||||
});
|
});
|
||||||
|
|
||||||
// the containing box for the promptWidget and commandWidget
|
// the containing box for the promptWidget and commandWidget
|
||||||
@@ -156,7 +157,8 @@ function CommandLine() //{{{
|
|||||||
liberator.registerCallback("complete", modes.EX, function (str) {
|
liberator.registerCallback("complete", modes.EX, function (str) {
|
||||||
completionContext.reset();
|
completionContext.reset();
|
||||||
completionContext.tabPressed = true;
|
completionContext.tabPressed = true;
|
||||||
return completion.ex(completionContext);
|
completionContext.fork("ex", 0, completion.ex, completion);
|
||||||
|
return completionContext.allItems;
|
||||||
});
|
});
|
||||||
liberator.registerCallback("change", modes.EX, function (command) {
|
liberator.registerCallback("change", modes.EX, function (command) {
|
||||||
completion.cancel(); // cancel any previous completion function
|
completion.cancel(); // cancel any previous completion function
|
||||||
@@ -584,6 +586,10 @@ function CommandLine() //{{{
|
|||||||
commandWidget.focus();
|
commandWidget.focus();
|
||||||
|
|
||||||
completionContext = new CompletionContext(commandWidget.inputField.editor);
|
completionContext = new CompletionContext(commandWidget.inputField.editor);
|
||||||
|
completionContext.onUpdate = function ()
|
||||||
|
{
|
||||||
|
commandline.setCompletions(this.allItems);
|
||||||
|
};
|
||||||
// open the completion list automatically if wanted
|
// open the completion list automatically if wanted
|
||||||
if (/\s/.test(cmd) &&
|
if (/\s/.test(cmd) &&
|
||||||
options.get("wildoptions").has("auto") &&
|
options.get("wildoptions").has("auto") &&
|
||||||
@@ -815,17 +821,12 @@ function CommandLine() //{{{
|
|||||||
historyIndex = UNINITIALIZED;
|
historyIndex = UNINITIALIZED;
|
||||||
|
|
||||||
// TODO: call just once, and not on each <Tab>
|
// TODO: call just once, and not on each <Tab>
|
||||||
var wim = options["wildmode"].split(",");
|
let wildmode = options["wildmode"].split(",");
|
||||||
var hasList = false;
|
let wildType = wildmode[Math.min(wildIndex++, wildmode.length - 1)];
|
||||||
var longest = false;
|
|
||||||
var full = false;
|
let hasList = /^list(:|$)/.test(wildType);
|
||||||
var wildType = wim[wildIndex++] || wim[wim.length - 1];
|
let longest = /(^|:)longest$/.test(wildType);
|
||||||
if (wildType == "list" || wildType == "list:full" || wildType == "list:longest")
|
let full = !longest && /(^|:)full/.test(wildType);
|
||||||
hasList = true;
|
|
||||||
if (wildType == "longest" || wildType == "list:longest")
|
|
||||||
longest = true;
|
|
||||||
else if (wildType == "full" || wildType == "list:full")
|
|
||||||
full = true;
|
|
||||||
|
|
||||||
// we need to build our completion list first
|
// we need to build our completion list first
|
||||||
if (completionIndex == UNINITIALIZED)
|
if (completionIndex == UNINITIALIZED)
|
||||||
@@ -837,20 +838,22 @@ function CommandLine() //{{{
|
|||||||
|
|
||||||
// sort the completion list
|
// sort the completion list
|
||||||
// TODO: might not make sense anymore with our advanced completions, we should just sort when necessary
|
// TODO: might not make sense anymore with our advanced completions, we should just sort when necessary
|
||||||
if (options.get("wildoptions").has("sort"))
|
// FIXME: CompletionContext
|
||||||
completions.items.sort(function (a, b) String.localeCompare(a[0], b[0]));
|
//if (options.get("wildoptions").has("sort"))
|
||||||
|
// completions.items.sort(function (a, b) String.localeCompare(a[0], b[0]));
|
||||||
|
|
||||||
completionList.setItems(completions.items);
|
completionList.setItems(completionContext.allItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (completions.items.length == 0)
|
if (completions.items.length == 0)
|
||||||
{
|
{
|
||||||
// try to fetch more items, if possible
|
// Wait for items to come available
|
||||||
// TODO: also use that code when we DO have completions but too few
|
// TODO: also use that code when we DO have completions but too few
|
||||||
if (completions.getMoreItems)
|
let end = Date.now() + 5000;
|
||||||
|
while (completionContext.incomplete && completions.items.length == 0 && Date.now() < end)
|
||||||
{
|
{
|
||||||
completions.items = completions.items.concat(completions.getMoreItems(1));
|
liberator.threadYield();
|
||||||
completionList.setItems(completions.items);
|
completions = completionContext.allItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (completions.items.length == 0) // still not more matches
|
if (completions.items.length == 0) // still not more matches
|
||||||
@@ -895,11 +898,11 @@ function CommandLine() //{{{
|
|||||||
{
|
{
|
||||||
var compl = null;
|
var compl = null;
|
||||||
if (longest && completions.items.length > 1)
|
if (longest && completions.items.length > 1)
|
||||||
compl = completion.getLongestSubstring();
|
compl = completion.longestSubstring;
|
||||||
else if (full)
|
else if (full)
|
||||||
compl = completions.items[completionIndex][0];
|
compl = completions.items[completionIndex].text;
|
||||||
else if (completions.items.length == 1)
|
else if (completions.items.length == 1)
|
||||||
compl = completions.items[0][0];
|
compl = completions.items[0].text;
|
||||||
|
|
||||||
if (compl)
|
if (compl)
|
||||||
{
|
{
|
||||||
@@ -1236,8 +1239,9 @@ function CommandLine() //{{{
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// don't show an empty result, if we are just waiting for data to arrive
|
// don't show an empty result, if we are just waiting for data to arrive
|
||||||
if (newCompletions.incompleteResult && newCompletions.items.length == 0)
|
// FIXME: Maybe. CompletionContext
|
||||||
return;
|
//if (newCompletions.incompleteResult && newCompletions.items.length == 0)
|
||||||
|
// return;
|
||||||
|
|
||||||
completionList.setItems(newCompletions.items);
|
completionList.setItems(newCompletions.items);
|
||||||
|
|
||||||
@@ -1332,32 +1336,30 @@ function ItemList(id) //{{{
|
|||||||
// TODO: move to completions?
|
// TODO: move to completions?
|
||||||
function createDefaultRow(item, dom)
|
function createDefaultRow(item, dom)
|
||||||
{
|
{
|
||||||
if (item instanceof Array)
|
let { text: text, description: description, icon: icon } = item;
|
||||||
item = { text: item[0], description: item[1], icon: item[2] };
|
|
||||||
|
|
||||||
/* Kludge until we have completion contexts. */
|
/* Kludge until we have completion contexts. */
|
||||||
let map = completion.filterMap;
|
let map = completion.filterMap;
|
||||||
if (map)
|
if (map)
|
||||||
{
|
{
|
||||||
item.text = map[0] ? map[0](item.text) : item.text;
|
text = map[0] ? map[0](text) : text;
|
||||||
item.description = map[1] ? map[1](item.description) : item.description;
|
description = map[1] ? map[1](description) : description;
|
||||||
}
|
}
|
||||||
/* Obviously, ItemList shouldn't know or care about this. */
|
/* Obviously, ItemList shouldn't know or care about this. */
|
||||||
let filter = completion.filterString;
|
let filter = completion.filterString;
|
||||||
if (filter)
|
if (filter)
|
||||||
{
|
{
|
||||||
item.text = template.highlightFilter(item.text, filter);
|
text = template.highlightFilter(text, filter);
|
||||||
item.description = template.highlightFilter(item.description, filter);
|
description = template.highlightFilter(description, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof item.icon == "function")
|
if (typeof icon == "function")
|
||||||
item.icon = item.icon();
|
icon = icon();
|
||||||
|
|
||||||
let row =
|
let row =
|
||||||
<ul class="hl-CompItem">
|
<ul class="hl-CompItem">
|
||||||
<li class="hl-CompIcon">{item.icon ? <img src={item.icon}/> : <></>}</li>
|
<li class="hl-CompIcon">{icon ? <img src={icon}/> : <></>}</li>
|
||||||
<li class="hl-CompResult">{item.text}</li>
|
<li class="hl-CompResult">{text}</li>
|
||||||
<li class="hl-CompDesc">{item.description}</li>
|
<li class="hl-CompDesc">{description}</li>
|
||||||
</ul>;
|
</ul>;
|
||||||
|
|
||||||
if (dom)
|
if (dom)
|
||||||
|
|||||||
@@ -130,10 +130,7 @@ const util = { //{{{
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
compareIgnoreCase: function (a, b)
|
compareIgnoreCase: function (a, b) String.localeCompare(a.toLowerCase(), b.toLowerCase()),
|
||||||
{
|
|
||||||
return String.localeCompare(a.toLowerCase(), b.toLowerCase());
|
|
||||||
},
|
|
||||||
|
|
||||||
clip: function (str, length)
|
clip: function (str, length)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ const config = { //{{{
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
bang: true,
|
bang: true,
|
||||||
completer: function (filter) completion.url(filter)
|
completer: function (filter, args, bang, context) completion.url(context)
|
||||||
});
|
});
|
||||||
|
|
||||||
commands.add(["redr[aw]"],
|
commands.add(["redr[aw]"],
|
||||||
@@ -364,7 +364,7 @@ const config = { //{{{
|
|||||||
else
|
else
|
||||||
liberator.open("about:blank", liberator.NEW_WINDOW);
|
liberator.open("about:blank", liberator.NEW_WINDOW);
|
||||||
},
|
},
|
||||||
{ completer: function (filter) completion.url(filter) });
|
{ completer: function (filter, bang, args, context) completion.url(context) });
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////}}}
|
/////////////////////////////////////////////////////////////////////////////}}}
|
||||||
////////////////////// OPTIONS /////////////////////////////////////////////////
|
////////////////////// OPTIONS /////////////////////////////////////////////////
|
||||||
|
|||||||
Reference in New Issue
Block a user