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

More completion stuff. And move vimperator.png to chrome://liberator2/content/ -- long story.

This commit is contained in:
Kris Maglione
2008-11-24 10:10:49 +00:00
parent b2a87273f8
commit 9b14f6e331
14 changed files with 376 additions and 330 deletions

View File

@@ -39,26 +39,26 @@ function CompletionContext(editor, name, offset)
if (editor instanceof arguments.callee)
{
let self = this;
let parent = editor;
name = parent.name + "/" + name;
this.contexts = parent.contexts;
if (name in this.contexts)
{
let self = this.contexts[name];
self = this.contexts[name];
self.offset = parent.offset + (offset || 0);
return self;
}
this.contexts[name] = this;
this.top = parent.top;
this.anchored = parent.anchored;
this.parent = parent;
this.editor = parent.editor;
this.offset = parent.offset + (offset || 0);
this.__defineGetter__("contextList", function () this.top.contextList);
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__("value", function () this.top.value);
["editor", "filterFunc", "keys", "title", "top"].forEach(function (key)
self[key] = parent[key]);
["contextList", "onUpdate", "selectionTypes", "tabPressed", "updateAsync", "value"].forEach(function (key) {
self.__defineGetter__(key, function () this.top[key]);
self.__defineSetter__(key, function (val) this.top[key] = val);
});
this.incomplete = false;
}
else
@@ -67,6 +67,9 @@ function CompletionContext(editor, name, offset)
this._value = editor;
else
this.editor = editor;
this.filterFunc = completion.filter;
this.title = ["Completions"];
this.keys = [0, 1];
this.top = this;
this.offset = offset || 0;
this.tabPressed = false;
@@ -78,56 +81,139 @@ function CompletionContext(editor, name, offset)
}
this.name = name || "";
this.cache = {};
this._items = []; // FIXME
this.process = [];
this._completions = []; // FIXME
}
CompletionContext.prototype = {
// Temporary
get allItems()
{
let self = this;
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;
}));
}
}
let items = this.contextList.map(function (context) {
let prefix = self.value.substring(minStart, context.offset);
if (!context.hasItems)
return [];
return context.items;
});
return { start: minStart, items: util.Array.flatten(items) }
},
get caret() (this.editor ? this.editor.selection.getRangeAt(0).startOffset : this.value.length) - this.offset,
get completions() this._completions || [],
set completions(items)
{
delete this.cache.filtered;
delete this.cache.filter;
this.hasItems = items.length > 0;
this._completions = items;
let self = this;
if (this.updateAsync)
liberator.callInMainThread(function () { self.onUpdate.call(self) });
},
get createRow() this._createRow || template.completionRow, // XXX
set createRow(createRow) this._createRow = createRow,
get filter() this.value.substr(this.offset, this.caret),
get regenerate() this._generate && (!this.completions || this.cache.key != this.key || this.cache.offset != this.offset),
set regenerate(val) { if (val) delete this.cache.offset },
get items() this._items,
set items(items)
get generate() !this._generate ? null : function ()
{
this.hasItems = items.length > 0;
this._items = items;
if (this.updateAsync)
liberator.callInMainThread(function () { this.onUpdate.call(this) });
this._completions = this._generate.call(this);
this.cache.offset = this.offset;
this.cache.key = this.key;
return this._completions;
},
set generate(arg)
{
let self = this;
this.hasItems = true;
this._generate = arg;
if (this.background && this.regenerate)
{
let lock = {};
this.cache.backgroundLock = lock;
this.incomplete = true;
liberator.callFunctionInThread(null, function () {
let items = self.generate();
if (self.backgroundLock != lock)
return;
self.incomplete = false;
self.completions = items;
});
}
},
get title() this._title || ["Completions"], // XXX
set title(val) this._title = val,
get filter() this._filter || this.value.substr(this.offset, this.caret),
set filter(val) this._filter = val,
get format() ({
keys: this.keys,
process: this.process
}),
set format(format)
{
this.keys = format.keys;
this.process = format.process;
},
get items()
{
if (!this.hasItems)
return [];
if (this.cache.filtered && this.cache.filter == this.filter)
return this.cache.filtered;
let items = this.completions;
if (this.regenerate)
items = this.generate();
this.cache.filter = this.filter;
if (items == null)
return items;
let self = this;
let text = function (item) item[self.keys[0]];
if (self.quote)
text = function (item) self.quote(item[self.keys[0]]);
this.cache.filtered = this.filterFunc(items.map(function (item) ({ text: text(item), item: item })),
this.filter, this.anchored);
return this.cache.filtered;
},
get process() // FIXME
{
let process = this._process;
process = [process[0] || template.icon, process[1] || function (item, k) k];
let first = process[0];
let filter = this.filter;
if (!this.anchored)
process[0] = function (item, text) first(item, template.highlightFilter(item.text, filter));
return process;
},
set process(process)
{
this._process = process;
},
advance: function advance(count)
{
this.offset += count;
},
getItems: function (start, end)
{
let self = this;
let items = this.items;
if (!items)
return [];
let reverse = start > end;
start = Math.max(0, start || 0);
end = Math.min(items.length, end ? end : items.length);
return util.map(util.range(start, end, reverse), function (i) items[i]);
},
fork: function fork(name, offset, completer, self)
{
let context = new CompletionContext(this, name, offset);
@@ -273,8 +359,6 @@ function Completion() //{{{
if (!(objects instanceof Array))
objects = [objects];
completion.filterMap = [null, function highlight(v) template.highlight(v, true)];
let [obj, key] = objects;
let cache = this.context.cache.objects || {};
this.context.cache.objects = cache;
@@ -307,30 +391,27 @@ function Completion() //{{{
return cache[key] = compl;
}
this.filter = function filter(compl, key, last, offset)
this.filter = function filter(context, compl, name, anchored, key, last, offset)
{
context.title = [name];
context.anchored = anchored;
context.filter = key;
context.process = [null, function highlight(item, v) template.highlight(v, true)];
if (last != undefined) // Escaping the key (without adding quotes), so it matches the escaped completions.
key = util.escapeString(key.substr(offset), "");
let res = buildLongestStartingSubstring(compl, key);
if (res.length == 0)
{
substrings = [];
res = buildLongestCommonSubstring(compl, key);
}
if (last != undefined) // Prepend the quote delimiter to the substrings list, so it's not stripped on <Tab>
substrings = substrings.map(function (s) last + s);
let res;
if (last != undefined) // We're looking for a quoted string, so, strip whatever prefix we have and quote the rest
{
res.forEach(function strEscape(a) a[0] = util.escapeString(a[0].substr(offset), last));
}
res = compl.map(function (a) [util.escapeString(a[0].substr(offset), last), a[1]]);
else // We're not looking for a quoted string, so filter out anything that's not a valid identifier
{
res = res.filter(function isIdent(a) /^[\w$][\w\d$]*$/.test(a[0]));
}
return res;
res = compl.filter(function isIdent(a) /^[\w$][\w\d$]*$/.test(a[0]));
if (!anchored)
res = res.filter(function ([k]) util.compareIgnoreCase(k.substr(0, key.length), key));
context.completions = res;
}
this.eval = function eval(arg, key, tmp)
@@ -505,7 +586,6 @@ function Completion() //{{{
{
if (e.message != "Invalid JS")
liberator.reportError(e);
// liberator.dump(util.escapeString(string) + ": " + e + "\n" + e.stack);
lastIdx = 0;
return;
}
@@ -572,9 +652,15 @@ function Completion() //{{{
{
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), key + (string || ""), last, key.length);
obj[3] = compl || this.objectKeys(obj);
this.context.fork(obj[1], top[OFFSET], this.filter, this,
obj[3], obj[1], true, key + (string || ""), last, key.length);
}
for (let [,obj] in Iterator(objects))
{
obj[1] += " (substrings)";
this.context.fork(obj[1], top[OFFSET], this.filter, this,
obj[3], obj[1], false, key + (string || ""), last, key.length);
}
}
@@ -723,8 +809,9 @@ function Completion() //{{{
for (let [,item] in Iterator(list))
{
var complist = item[0] instanceof Array ? item[0]
: [item[0]];
// FIXME: Temporary kludge
let text = item.item ? item.item[0] || item.text : item[0];
var complist = text instanceof Array ? text : [text];
for (let [,compitem] in Iterator(complist))
{
let str = !ignorecase ? compitem : String(compitem).toLowerCase();
@@ -732,15 +819,14 @@ function Completion() //{{{
if (str.indexOf(filter) == -1)
continue;
filtered.push([compitem, item[1], favicon ? item[2] : null]);
item.text = compitem;
filtered.push(item);
if (longest)
buildSubstrings(str, filter);
break;
}
}
if (options.get("wildoptions").has("sort"))
filtered = filtered.sort(function (a, b) util.compareIgnoreCase(a[0], b[0]));;
return filtered;
}
@@ -755,14 +841,15 @@ function Completion() //{{{
for (let [,item] in Iterator(list))
{
var complist = item[0] instanceof Array ? item[0]
: [item[0]];
let text = item.item ? item.item[0] || item.text : item[0];
var complist = text instanceof Array ? text : [text];
for (let [,compitem] in Iterator(complist))
{
if (compitem.indexOf(filter) != 0)
if (compitem.substr(0, filter.length) != filter)
continue;
filtered.push([compitem, item[1], favicon ? item[2] : null]);
item.text = compitem;
filtered.push(item);
if (longest)
{
@@ -780,8 +867,6 @@ function Completion() //{{{
break;
}
}
if (options.get("wildoptions").has("sort"))
filtered = filtered.sort(function (a, b) util.compareIgnoreCase(a[0], b[0]));;
return filtered;
}
@@ -808,17 +893,23 @@ function Completion() //{{{
// returns the longest common substring
// used for the 'longest' setting for wildmode
get longestSubstring () substrings.reduce(function (a, b) a.length > b.length ? a : b, ""),
get longestSubstring() substrings.reduce(function (a, b) a.length > b.length ? a : b, ""),
get substrings() substrings.slice(),
runCompleter: function (name, filter)
{
let context = new CompletionContext(filter);
context.__defineGetter__("background", function () false);
context.__defineSetter__("background", function () false);
this[name](context);
return context.items.map(function (i) i.item);
},
// generic filter function, also builds substrings needed
// for :set wildmode=list:longest, if necessary
filter: function filter(array, filter, matchFromBeginning, favicon)
{
if (!filter)
return [[a[0], a[1], favicon ? a[2] : null] for each (a in array)];
let result;
if (matchFromBeginning)
result = buildLongestStartingSubstring(array, filter, favicon);
@@ -827,16 +918,6 @@ function Completion() //{{{
return result;
},
cached: function cached(key, filter, generate, method)
{
if (!filter && cacheFilter[key] || filter.indexOf(cacheFilter[key]) != 0)
cacheResults[key] = generate(filter);
cacheFilter[key] = filter;
if (cacheResults[key].length)
return cacheResults[key] = this[method].apply(this, [cacheResults[key], filter].concat(Array.slice(arguments, 4)));
return [];
},
// cancel any ongoing search
cancel: function cancel()
{
@@ -928,10 +1009,7 @@ function Completion() //{{{
itemsStr = itemsStr.toLowerCase();
}
if (filter.split(/\s+/).every(function strIndex(str) itemsStr.indexOf(str) > -1))
return true;
return false;
return filter.split(/\s+/).every(function strIndex(str) itemsStr.indexOf(str) > -1);
},
////////////////////////////////////////////////////////////////////////////////
@@ -944,16 +1022,14 @@ function Completion() //{{{
{
return {
start: 0,
get items() {
return bookmarks.get(filter).map(function (bmark) {
items: bookmarks.get(filter).map(function (bmark) {
// temporary, until we have moved all completions to objects
bmark[0] = bmark.url;
bmark[1] = bmark.title;
bmark.text = bmark.url;
return bmark;
});
},
})
};
},
@@ -1017,22 +1093,18 @@ function Completion() //{{{
let schemes = [];
let rtp = options["runtimepath"].split(",");
rtp.forEach(function (path) {
// FIXME: Now! Very, very broken.
schemes = schemes.concat([[c[0].replace(/\.vimp$/, ""), ""]
let schemes = rtp.map(function (path) // FIXME: Now! Very, very broken.
[[c[0].replace(/\.vimp$/, ""), ""]
for each (c in completion.file(path + "/colors/", true)[1])]);
});
return [0, completion.filter(schemes, filter)];
return [0, completion.filter(util.Array.flatten(schemes), filter)];
},
command: function command(context)
{
context.title = ["Command"];
if (!context.filter)
context.items = [[c.name, c.description] for (c in commands)];
else
context.items = this.filter([[c.longNames, c.description] for (c in commands)], context.filter, true);
context.anchored = true;
context.completions = [[c.longNames, c.description] for (c in commands)];
},
dialog: function dialog(filter) [0, this.filter(config.dialogs, filter)],
@@ -1040,7 +1112,7 @@ function Completion() //{{{
directory: function directory(context, tail)
{
this.file(context, tail);
context.items = context.items.filter(function (i) i[1] == "Directory");
context.completions = context.completions.filter(function (i) i[1] == "Directory");
},
environment: function environment(filter)
@@ -1050,10 +1122,7 @@ function Completion() //{{{
lines.pop();
let vars = lines.map(function (line) {
let matches = line.match(/([^=]+)=(.+)/) || [];
return [matches[1], matches[2]];
});
let vars = lines.map(function (line) (line.match(/([^=]+)=(.+)/) || []).slice(1));
return [0, this.filter(vars, filter)];
},
@@ -1075,7 +1144,6 @@ function Completion() //{{{
let [count, cmd, special, args] = commands.parseCommand(context.filter);
let [, prefix, junk] = context.filter.match(/^(:*\d*)\w*(.?)/) || [];
context.advance(prefix.length)
context.items = []; // XXX
if (!junk)
return this.command(context);
@@ -1090,7 +1158,6 @@ function Completion() //{{{
args = command.parseArgs(cmdContext.filter, argContext);
if (args)
{
// XXX, XXX, XXX
if (!args.completeOpt && command.completer)
{
cmdContext.advance(args.completeStart);
@@ -1101,12 +1168,12 @@ function Completion() //{{{
{
cmdContext.advance(compObject.start);
cmdContext.title = ["Completions"];
cmdContext.items = compObject.items;
cmdContext.filterFunc = function (k) k;
cmdContext.completions = compObject.items;
}
}
cmdContext.updateAsync = true;
context.updateAsync = true;
}
//liberator.dump([[v.name, v.offset, v.items.length, v.hasItems] for each (v in context.contexts)]);
}
},
@@ -1117,65 +1184,53 @@ function Completion() //{{{
let [dir] = context.filter.match(/^(?:.*[\/\\])?/);
// dir == "" is expanded inside readDirectory to the current dir
let generate = function generate()
context.title = ["Path", "Type"];
if (tail)
context.advance(dir.length);
context.anchored = true;
context.key = dir;
context.generate = function generate()
{
let files = [], mapped = [];
context.cache.dir = dir;
try
{
dir = dir.replace("\\ ", " ", "g");
files = io.readDirectory(dir, true);
let files = io.readDirectory(dir, true);
if (options["wildignore"])
{
let wigRegexp = RegExp("(^" + options["wildignore"].replace(",", "|", "g") + ")$");
files = files.filter(function (f) f.isDirectory() || !wigRegexp.test(f.leafName))
}
mapped = files.map(
return files.map(
function (file) [(tail ? file.leafName : dir + file.leafName).replace(" ", "\\ ", "g"),
file.isDirectory() ? "Directory" : "File"]
);
}
catch (e) {}
return mapped;
return [];
};
context.title = ["Path", "Type"];
if (tail)
context.advance(dir.length);
context.items = this.cached("file-" + dir, context.filter, generate, "filter", true);
},
help: function help(filter)
help: function help(context)
{
let res = [];
for (let [, file] in Iterator(config.helpFiles))
context.title = ["Help"];
context.background = true;
context.generate = function ()
{
try
{
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "chrome://liberator/locale/" + file, false);
xmlhttp.send(null);
}
catch (e)
{
liberator.log("Error opening chrome://liberator/locale/" + file, 1);
continue;
}
let doc = xmlhttp.responseXML;
res.push(Array.map(doc.getElementsByClassName("tag"),
function (elem) [elem.textContent, file]));
let res = config.helpFiles.map(function (file) {
let resp = util.httpGet("chrome://liberator/locale/" + file);
if (!resp)
return [];
let doc = resp.responseXML;
return Array.map(doc.getElementsByClassName("tag"),
function (elem) [elem.textContent, file]);
});
return util.Array.flatten(res);
}
return [0, this.filter(util.Array.flatten(res), filter)];
},
highlightGroup: function highlightGroup(filter) commands.get("highlight").completer(filter), // XXX
get javascriptCompleter() javascript,
javascript: function _javascript(context)
@@ -1200,17 +1255,25 @@ function Completion() //{{{
{
let [, keyword, space, args] = context.filter.match(/^\s*(\S*)(\s*)(.*)$/);
let keywords = bookmarks.getKeywords();
let engines = this.filter(keywords.concat(bookmarks.getSearchEngines()), context.filter, false, true);
let engines = bookmarks.getSearchEngines();
context.title = ["Search Keywords"];
context.items = engines;
context.completions = keywords.concat(engines);
context.anchored = true;
// TODO: Simplify.
for (let [,item] in Iterator(keywords))
{
let name = item.keyword;
if (space && keyword == name && item.url.indexOf("%s") > -1)
context.fork(name, name.length + space.length, function (context) {
if (!space)
return;
context.fork("suggest", keyword.length + space.length, this.searchEngineSuggest, this,
keyword, true);
let item = keywords.filter(function (k) k.keyword == keyword)[0];
if (item && item.url.indexOf("%s") > -1)
context.fork("keyword/" + keyword, keyword.length + space.length, function (context) {
context.title = [keyword + " Quick Search"];
context.background = true;
context.anchored = true;
context.generate = function () {
let [begin, end] = item.url.split("%s");
let history = modules.history.service;
let query = history.getNewQuery();
@@ -1221,86 +1284,56 @@ function Completion() //{{{
opts.resultType = opts.RESULTS_AS_URI;
opts.queryType = opts.QUERY_TYPE_HISTORY;
context.title = [keyword + " Quick Search"];
function setItems()
{
context.items = completion.filter(context.cache.items, args, false, true);
}
if (context.cache.items)
setItems();
else
{
context.incomplete = true;
liberator.callFunctionInThread(null, function () {
let results = history.executeQuery(query, opts);
let root = results.root;
root.containerOpen = true;
context.cache.items = util.map(util.range(0, root.childCount), function (i) {
let child = root.getChild(i);
let rest = child.uri.length - end.length;
let query = child.uri.substring(begin.length, rest);
if (child.uri.substr(rest) == end && query.indexOf("&") == -1)
return [decodeURIComponent(query.replace("+", "%20")),
child.title,
child.icon];
}).filter(function (k) k);
root.containerOpen = false;
context.incomplete = false;
setItems();
});
}
});
}
let results = history.executeQuery(query, opts);
let root = results.root;
root.containerOpen = true;
let result = util.map(util.range(0, root.childCount), function (i) {
let child = root.getChild(i);
let rest = child.uri.length - end.length;
let query = child.uri.substring(begin.length, rest);
if (child.uri.substr(rest) == end && query.indexOf("&") == -1)
return [decodeURIComponent(query.replace("+", "%20")),
child.title,
child.icon];
}).filter(function (k) k);
root.containerOpen = false;
return result;
};
});
},
// XXX: Move to bookmarks.js?
searchEngineSuggest: function searchEngineSuggest(context, engineAliases)
searchEngineSuggest: function searchEngineSuggest(context, engineAliases, kludge)
{
if (!filter)
return [0, []];
if (!context.filter)
return;
let engineList = (engineAliases || options["suggestengines"] || "google").split(",");
let responseType = "application/x-suggestions+json";
let ss = Components.classes["@mozilla.org/browser/search-service;1"]
.getService(Components.interfaces.nsIBrowserSearchService);
let matches = query.match(RegExp("^\s*(" + name + "\\s+)(.*)$")) || [];
if (matches[1])
context.advance(matches[1].length);
query = context.filter;
let engineList = (engineAliases || options["suggestengines"] || "google").split(",");
let completions = [];
engineList.forEach(function (name) {
let engine = ss.getEngineByAlias(name);
if (engine && engine.supportsResponseType(responseType))
var queryURI = engine.getSubmission(query, responseType).uri.asciiSpec;
else
if (!engine)
return;
let xhr = new XMLHttpRequest();
xhr.open("GET", queryURI, false);
xhr.send(null);
let json = Components.classes["@mozilla.org/dom/json;1"]
.createInstance(Components.interfaces.nsIJSON);
let results = json.decode(xhr.responseText)[1];
if (!results)
let [, word] = /^\s*(\S+)/.exec(context.filter) || [];
if (!kludge && word == name) // FIXME: Check for matching keywords
return;
let ctxt = context.fork(name, 0);
let ctxt = context.fork(engine.name, (matches[1] || "").length);
ctxt.title = [engine.name + " Suggestions"];
// make sure we receive strings, otherwise a man-in-the-middle attack
// could return objects which toString() method could be called to
// execute untrusted code
ctxt.items = [[item, ""] for ([k, item] in results) if (typeof item == "string")];
ctxt.title = [engine.description + " Suggestions"];
ctxt.regenerate = true;
ctxt.background = true;
ctxt.generate = function () bookmarks.getSuggestions(name, this.filter);
});
},
shellCommand: function shellCommand(filter)
shellCommand: function shellCommand(context)
{
let generate = function generate()
context.title = ["Shell Command", "Path"];
context.generate = function ()
{
liberator.dump("generate");
const environmentService = Components.classes["@mozilla.org/process/environment;1"]
.getService(Components.interfaces.nsIEnvironment);
@@ -1312,17 +1345,13 @@ function Completion() //{{{
let dir = io.getFile(dirName);
if (dir.exists() && dir.isDirectory())
{
io.readDirectory(dir).forEach(function (file) {
if (file.isFile() && file.isExecutable())
commands.push([file.leafName, dir.path]);
});
commands.push([[file.leafName, dir.path] for ([i, file] in Iterator(io.readDirectory(dir)))
if (file.isFile() && file.isExecutable())]);
}
}
return commands;
return util.Array.flatten(commands);
}
return [0, this.cached("shell-command", filter, generate, "filter")];
},
sidebar: function sidebar(filter)
@@ -1341,14 +1370,14 @@ function Completion() //{{{
// unify split style sheets
completions.forEach(function (stylesheet) {
for (let i = 0; i < completions.length; i++)
{
if (stylesheet[0] == completions[i][0] && stylesheet[1] != completions[i][1])
completions = completions.filter(function (completion) {
if (stylesheet[0] == completion[0] && stylesheet[1] != completion[1])
{
stylesheet[1] += ", " + completions[i][1];
completions.splice(i, 1);
stylesheet[1] += ", " + completion[1];
return false;
}
}
return true;
});
});
return [0, this.filter(completions, filter)];
@@ -1374,14 +1403,8 @@ function Completion() //{{{
b: function b(context)
{
context.title = ["Bookmark", "Title"];
context.createRow = function createRow(context, item, class)
{
// FIXME
if (class)
return template.completionRow(context, item, class);
return template.bookmarkItem(item);
}
context.items = bookmarks.get(context.filter)
context.format = bookmarks.format;
context.completions = bookmarks.get(context.filter)
},
l: function l(context)
{
@@ -1389,15 +1412,16 @@ function Completion() //{{{
return
context.title = ["Smart Completions"];
context.incomplete = true;
context.hasItems = context.items.length > 0; // XXX
context.hasItems = context.completions.length > 0; // XXX
context.filterFunc = function (items) items;
let timer = new util.Timer(50, 100, function (result) {
context.items = [
[result.getValueAt(i), result.getCommentAt(i), result.getImageAt(i)]
context.completions = [
{ 0: result.getValueAt(i), 1: result.getCommentAt(i), icon: 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));
context.completions.forEach(function ([item]) buildSubstrings(item, filter));
});
completionService.stopSearch();
completionService.startSearch(context.filter, "", context.result, {
@@ -1408,9 +1432,9 @@ function Completion() //{{{
timer.flush();
}
});
}
};
// Will, and should, throw an error if !(c in opts)
Array.forEach(complete || options["complete"],
function (c) context.fork(c, 0, opts[c], completion));
},
@@ -1432,11 +1456,10 @@ function Completion() //{{{
userMapping: function userMapping(context, args, modes)
{
liberator.dump(args);
if (args.completeArg == 0)
{
let maps = [[m.names[0], ""] for (m in mappings.getUserIterator(modes))];
context.items = this.filter(maps, args.arguments[0]);
context.completions = this.filter(maps, args.arguments[0]);
}
}
// }}}