X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=common%2Fmodules%2Fcompletion.jsm;fp=common%2Fmodules%2Fcompletion.jsm;h=ff9c0917dade8a5403118350df32baa0b1485682;hb=9044153cb63835e39b9de8ec4ade237c03e3888a;hp=9671e95aad543f8eadf3a5f6acaaf8498bef26c0;hpb=70740024f9c028c1fd63e1a1850ab062ff956054;p=dactyl.git diff --git a/common/modules/completion.jsm b/common/modules/completion.jsm index 9671e95..ff9c091 100644 --- a/common/modules/completion.jsm +++ b/common/modules/completion.jsm @@ -4,14 +4,11 @@ // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. -"use strict"; - -try { +/* use strict */ Components.utils.import("resource://dactyl/bootstrap.jsm"); defineModule("completion", { - exports: ["CompletionContext", "Completion", "completion"], - use: ["config", "messages", "template", "util"] + exports: ["CompletionContext", "Completion", "completion"] }, this); /** @@ -212,6 +209,18 @@ var CompletionContext = Class("CompletionContext", { return this; }, + __title: Class.Memoize(function () this._title.map(function (s) + typeof s == "string" ? messages.get("completion.title." + s, s) + : s)), + + set title(val) { + delete this.__title; + return this._title = val; + }, + get title() this.__title, + + get activeContexts() this.contextList.filter(function (c) c.items.length), + // Temporary /** * @property {Object} @@ -222,28 +231,34 @@ var CompletionContext = Class("CompletionContext", { * @deprecated */ get allItems() { + let self = this; + try { - let self = this; - let allItems = this.contextList.map(function (context) context.hasItems && context.items); + let allItems = this.contextList.map(function (context) context.hasItems && context.items.length); if (this.cache.allItems && array.equals(this.cache.allItems, allItems)) return this.cache.allItemsResult; this.cache.allItems = allItems; - let minStart = Math.min.apply(Math, [context.offset for ([k, context] in Iterator(this.contexts)) if (context.hasItems && context.items.length)]); + let minStart = Math.min.apply(Math, this.activeContexts.map(function (c) c.offset)); if (minStart == Infinity) minStart = 0; - let items = this.contextList.map(function (context) { - if (!context.hasItems) - return []; - let prefix = self.value.substring(minStart, context.offset); - return context.items.map(function (item) ({ - text: prefix + item.text, - result: prefix + item.result, - __proto__: item - })); + + this.cache.allItemsResult = memoize({ + start: minStart, + + get longestSubstring() self.longestAllSubstring, + + get items() array.flatten(self.activeContexts.map(function (context) { + let prefix = self.value.substring(minStart, context.offset); + + return context.items.map(function (item) ({ + text: prefix + item.text, + result: prefix + item.result, + __proto__: item + })); + })) }); - this.cache.allItemsResult = { start: minStart, items: array.flatten(items) }; - memoize(this.cache.allItemsResult, "longestSubstring", function () self.longestAllSubstring); + return this.cache.allItemsResult; } catch (e) { @@ -253,7 +268,7 @@ var CompletionContext = Class("CompletionContext", { }, // Temporary get allSubstrings() { - let contexts = this.contextList.filter(function (c) c.hasItems && c.items.length); + let contexts = this.activeContexts; let minStart = Math.min.apply(Math, contexts.map(function (c) c.offset)); let lists = contexts.map(function (context) { let prefix = context.value.substring(minStart, context.offset); @@ -295,10 +310,12 @@ var CompletionContext = Class("CompletionContext", { this._completions = items; this.itemCache[this.key] = items; } + if (this._completions) this.hasItems = this._completions.length > 0; + if (this.updateAsync && !this.noUpdate) - this.onUpdate(); + util.trapErrors("onUpdate", this); }, get createRow() this._createRow || template.completionRow, // XXX @@ -338,11 +355,16 @@ var CompletionContext = Class("CompletionContext", { * The prototype object for items returned by {@link items}. */ get itemPrototype() { + let self = this; let res = { highlight: "" }; + function result(quote) { + yield ["context", function () self]; yield ["result", quote ? function () quote[0] + util.trapErrors(1, quote, this.text) + quote[2] : function () this.text]; + yield ["texts", function () Array.concat(this.text)]; }; + for (let i in iter(this.keys, result(this.quote))) { let [k, v] = i; if (typeof v == "string" && /^[.[]/.test(v)) @@ -350,7 +372,7 @@ var CompletionContext = Class("CompletionContext", { // reference any variables. Don't bother with eval context. v = Function("i", "return i" + v); if (typeof v == "function") - res.__defineGetter__(k, function () Class.replaceProperty(this, k, v.call(this, this.item))); + res.__defineGetter__(k, function () Class.replaceProperty(this, k, v.call(this, this.item, self))); else res.__defineGetter__(k, function () Class.replaceProperty(this, k, this.item[v])); res.__defineSetter__(k, function (val) Class.replaceProperty(this, k, val)); @@ -405,7 +427,7 @@ var CompletionContext = Class("CompletionContext", { this.noUpdate = false; }, - ignoreCase: Class.memoize(function () { + ignoreCase: Class.Memoize(function () { let mode = this.wildcase; if (mode == "match") return false; @@ -469,7 +491,7 @@ var CompletionContext = Class("CompletionContext", { this.processor = Array.slice(this.process); if (!this.anchored) this.processor[0] = function (item, text) self.process[0].call(self, item, - template.highlightFilter(item.text, self.filter)); + template.highlightFilter(item.text, self.filter, null, item.isURI)); try { // Item prototypes @@ -542,10 +564,11 @@ var CompletionContext = Class("CompletionContext", { // of the given string which also matches the current // item's text. let len = substring.length; - let i = 0, n = len; + let i = 0, n = len + 1; + let result = n && fixCase(item.result); while (n) { let m = Math.floor(n / 2); - let keep = compare(fixCase(item.text), substring.substring(0, i + m)); + let keep = compare(result, substring.substring(0, i + m)); if (!keep) len = i + m - 1; if (!keep || m == 0) @@ -589,7 +612,7 @@ var CompletionContext = Class("CompletionContext", { } this.offset += count; if (this._filter) - this._filter = this._filter.substr(advance); + this._filter = this._filter.substr(arguments[0] || 0); }, /** @@ -624,15 +647,38 @@ var CompletionContext = Class("CompletionContext", { return iter.map(util.range(start, end, step), function (i) items[i]); }, + getRow: function getRow(idx, doc) { + let cache = this.cache.rows; + if (cache) { + if (idx in this.items && !(idx in this.cache.rows)) + try { + cache[idx] = util.xmlToDom(this.createRow(this.items[idx]), + doc || this.doc); + } + catch (e) { + util.reportError(e); + cache[idx] = util.xmlToDom( +