From a5213c3760ddcb308f2e443f3d86e82a08098718 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Fri, 17 Sep 2010 06:15:13 -0400 Subject: [PATCH] Precompute completion string matching function. --- common/content/autocommands.js | 0 common/content/bookmarks.js | 3 ++- common/content/buffer.js | 9 +++------ common/content/commandline.js | 3 ++- common/content/completion.js | 32 ++++++++++++++------------------ common/content/configbase.js | 2 +- common/content/dactyl.js | 19 ++++++++++--------- common/content/events.js | 6 +++--- common/content/io.js | 4 ++-- common/content/modules.js | 16 +++++++--------- common/content/options.js | 14 +++++++------- common/content/statusline.js | 0 common/modules/base.jsm | 18 +++++++++++++++--- common/modules/util.jsm | 5 ++--- 14 files changed, 68 insertions(+), 63 deletions(-) mode change 100755 => 100644 common/content/autocommands.js mode change 100755 => 100644 common/content/completion.js mode change 100755 => 100644 common/content/io.js mode change 100755 => 100644 common/content/statusline.js diff --git a/common/content/autocommands.js b/common/content/autocommands.js old mode 100755 new mode 100644 diff --git a/common/content/bookmarks.js b/common/content/bookmarks.js index 095b4c21..39d983cf 100644 --- a/common/content/bookmarks.js +++ b/common/content/bookmarks.js @@ -366,6 +366,7 @@ const Bookmarks = Module("bookmarks", { type: CommandOption.INT } ] + // Not privateData, since we don't treat bookmarks as private }); commands.add(["delbm[arks]"], @@ -457,7 +458,7 @@ const Bookmarks = Module("bookmarks", { for (let val in Iterator(extra || [])) { let [k, v] = val; // Need block scope here for the closure if (v) - context.filters.push(function (item) this._match(v, item[k])); + context.filters.push(function (item) this.matchString(v, item[k])); } context.completions = bookmarkcache.bookmarks; completion.urls(context, tags); diff --git a/common/content/buffer.js b/common/content/buffer.js index ed050a00..d0d495a5 100644 --- a/common/content/buffer.js +++ b/common/content/buffer.js @@ -1292,16 +1292,13 @@ const Buffer = Module("buffer", { context.title = ["Stylesheet", "Location"]; // unify split style sheets - let styles = {}; + let styles = array.toObject([s.title, []] for (s in values(buffer.alternateStyleSheets))); buffer.alternateStyleSheets.forEach(function (style) { - if (!(style.title in styles)) - styles[style.title] = []; - styles[style.title].push(style.href || "inline"); }); - context.completions = [[s, styles[s].join(", ")] for (s in styles)]; + context.completions = [[title, href.join(", ")] for ([title, href] in Iterator(styles))]; }; completion.buffer = function buffer(context) { @@ -1327,7 +1324,7 @@ const Buffer = Module("buffer", { let process = context.process[0]; context.process = [function (item, text) <> - {item.item.indicator} + {item.item.indicator} { process.call(this, item, text) } ]; diff --git a/common/content/commandline.js b/common/content/commandline.js index fc4c2075..951da1dd 100644 --- a/common/content/commandline.js +++ b/common/content/commandline.js @@ -105,7 +105,8 @@ const CommandLine = Module("commandline", { this._autocompleteTimer = Timer(200, 500, function autocompleteTell(tabPressed) { if (!events.feedingKeys && self._completions && options.get("autocomplete").values.length) { self._completions.complete(true, false); - self._completions.itemList.show(); + if (self._completions) + self._completions.itemList.show(); } }); diff --git a/common/content/completion.js b/common/content/completion.js old mode 100755 new mode 100644 index 1434b38e..03e1be23 --- a/common/content/completion.js +++ b/common/content/completion.js @@ -295,14 +295,13 @@ const CompletionContext = Class("CompletionContext", { let res = {}; for (let i in Iterator(this.keys)) { let [k, v] = i; - let _k = "_" + k; if (typeof v == "string" && /^[.[]/.test(v)) v = Function("i", "return i" + v); if (typeof v == "function") - res.__defineGetter__(k, function () _k in this ? this[_k] : (this[_k] = v(this.item))); + res.__defineGetter__(k, function () Class.replaceProperty(this, k, v(this.item))); else - res.__defineGetter__(k, function () _k in this ? this[_k] : (this[_k] = this.item[v])); - res.__defineSetter__(k, function (val) this[_k] = val); + res.__defineGetter__(k, function () Class.replaceProperty(this, k, this.item[v])); + res.__defineSetter__(k, function (val) Class.replaceProperty(this, k, val)); } return res; }, @@ -370,6 +369,15 @@ const CompletionContext = Class("CompletionContext", { let self = this; delete this._substrings; + if (this.ignoreCase) + this.matchString = this.anchored ? + function (filter, str) String.toLowerCase(str).indexOf(filter.toLowerCase()) == 0 : + function (filter, str) String.toLowerCase(str).indexOf(filter.toLowerCase()) >= 0; + else + this.matchString = this.anchored ? + function (filter, str) String.indexOf(str, filter) == 0 : + function (filter, str) String.indexOf(str, filter) >= 0; + let proto = this.proto; let filtered = this.filterFunc(items.map(function (item) ({ __proto__: proto, item: item }))); if (this.maxItems) @@ -543,19 +551,8 @@ const CompletionContext = Class("CompletionContext", { catch (e) {} }, - // FIXME - _match: function _match(filter, str) { - if (this.ignoreCase) { - filter = filter.toLowerCase(); - str = str.toLowerCase(); - } - if (this.anchored) - return str.substr(0, filter.length) == filter; - return str.indexOf(filter) > -1; - }, - match: function match(str) { - return this._match(this.filter, str); + return this.matchString(this.filter, str); }, reset: function reset() { @@ -614,8 +611,7 @@ const CompletionContext = Class("CompletionContext", { } }, { Sort: { - number: function (a, b) parseInt(b) - parseInt(a) || String.localeCompare(a, b), - + number: function (a, b) parseInt(a.text) - parseInt(b.text) || String.localeCompare(a.text, b.text), unsorted: null }, diff --git a/common/content/configbase.js b/common/content/configbase.js index 5fb75d29..a8a79847 100644 --- a/common/content/configbase.js +++ b/common/content/configbase.js @@ -166,7 +166,7 @@ const ConfigBase = Class(ModuleBase, { GradientLeft background-color: magenta; GradientRight background-color: white; - Indicator color: blue; + Indicator color: blue; width: 1.5em; text-align: center; Filter font-weight: bold; Keyword color: red; diff --git a/common/content/dactyl.js b/common/content/dactyl.js index b56548b1..00db62bf 100644 --- a/common/content/dactyl.js +++ b/common/content/dactyl.js @@ -842,7 +842,7 @@ const Dactyl = Module("dactyl", { urls = [str]; return urls.map(function (url) { - if (/^[.~]?\//.test(url)) { + if (/^(\.{0,2}|~)\//.test(url)) { try { // Try to find a matching file. let file = io.File(url); @@ -906,14 +906,7 @@ const Dactyl = Module("dactyl", { return func.apply(self || this, Array.slice(arguments, 2)); } catch (e) { - if (e instanceof FailedAssertion) { - if (e.message) - dactyl.echoerr(e.message); - else - dactyl.beep(); - } - else - dactyl.reportError(e); + dactyl.reportError(e); return undefined; } }, @@ -925,6 +918,14 @@ const Dactyl = Module("dactyl", { * @param {Object} error The error object. */ reportError: function (error) { + if (error instanceof FailedAssertion) { + if (error.message) + dactyl.echoerr(error.message); + else + dactyl.beep(); + return; + } + if (Cu.reportError) Cu.reportError(error); diff --git a/common/content/events.js b/common/content/events.js index 455bd0e0..5dd187d7 100644 --- a/common/content/events.js +++ b/common/content/events.js @@ -167,9 +167,9 @@ const Events = Module("events", { * @param {string} macro The name for the macro. */ startRecording: function (macro) { - // TODO: ignore this like Vim? - dactyl.assert(/[a-zA-Z0-9]/.test(macro), - "E354: Invalid register name: '" + macro + "'"); + // TODO: ignore this like Vim? + dactyl.assert(/[a-zA-Z0-9]/.test(macro), + "E354: Invalid register name: '" + macro + "'"); modes.isRecording = true; diff --git a/common/content/io.js b/common/content/io.js old mode 100755 new mode 100644 index ebe86d6a..1f516b11 --- a/common/content/io.js +++ b/common/content/io.js @@ -314,7 +314,7 @@ lookup: */ source: function (filename, silent) { let wasSourcing = this.sourcing; - dactyl.dump("sourcing " + filename); + defmodule.loadLog.push("sourcing " + filename); let time = Date.now(); try { var file = io.File(filename); @@ -432,7 +432,7 @@ lookup: dactyl.echoerr(message); } finally { - dactyl.dump("done sourcing " + filename + ": " + (Date.now() - time) + "ms"); + defmodule.loadLog.push("done sourcing " + filename + ": " + (Date.now() - time) + "ms"); this.sourcing = wasSourcing; } }, diff --git a/common/content/modules.js b/common/content/modules.js index 840f87c5..5f9594a4 100644 --- a/common/content/modules.js +++ b/common/content/modules.js @@ -89,8 +89,8 @@ window.addEventListener("load", function onLoad() { const loaded = set(["init"]); function init(module) { - function init(func) - function () func.call(module, dactyl, modules, window); + function init(func, mod) + function () defmodule.time(module.name || module.constructor.name, mod, func, module, dactyl, modules, window); set.add(loaded, module.constructor.name); for (let [mod, func] in Iterator(module.INIT)) { @@ -98,7 +98,7 @@ window.addEventListener("load", function onLoad() { init(func)(); else { deferredInit[mod] = deferredInit[mod] || []; - deferredInit[mod].push(init(func)); + deferredInit[mod].push(init(func, mod)); } } } @@ -121,21 +121,19 @@ window.addEventListener("load", function onLoad() { for (let dep in values(module.requires)) load(Module.constructors[dep], module.name); - dump("Load" + (isstring(prereq) ? " " + prereq + " dependency: " : ": ") + module.name); + defmodule.loadLog.push("Load" + (isstring(prereq) ? " " + prereq + " dependency: " : ": ") + module.name); if (frame && frame.filename) - dump(" from: " + frame.filename + ":" + frame.lineNumber); + defmodule.loadLog.push(" from: " + frame.filename + ":" + frame.lineNumber); delete modules[module.name]; - modules[module.name] = module(); + modules[module.name] = defmodule.time(module.name, "init", module); init(modules[module.name]); for (let [, fn] in iter(deferredInit[module.name] || [])) fn(); } catch (e) { - dump("Loading " + (module && module.name) + ": " + e); - if (e.stack) - dump(e.stack); + dump("Loading " + (module && module.name) + ": " + e + "\n" + (e.stack || "")); } return modules[module.name]; } diff --git a/common/content/options.js b/common/content/options.js index 8f28e7be..c2ae2867 100644 --- a/common/content/options.js +++ b/common/content/options.js @@ -327,7 +327,7 @@ const Option = Class("Option", { re.result = arguments.length == 2 ? result : !bang; return re; }, - unparseRegex: function (re) re.bang + re.source + (typeof re.result == "string" ? "=" + re.result : ""), + unparseRegex: function (re) re.bang + re.source + (typeof re.result == "string" ? ":" + re.result : ""), getKey: { stringlist: function (k) this.values.indexOf(k) >= 0, @@ -342,7 +342,7 @@ const Option = Class("Option", { joinValues: { charlist: function (vals) vals.join(""), stringlist: function (vals) vals.join(","), - stringmap: function (vals) [k + "=" + v for ([k, v] in Iterator(vals))].join(","), + stringmap: function (vals) [k + ":" + v for ([k, v] in Iterator(vals))].join(","), regexlist: function (vals) vals.map(Option.unparseRegex).join(","), }, @@ -351,10 +351,10 @@ const Option = Class("Option", { boolean: function (value) value == "true" || value == true ? true : false, charlist: function (value) Array.slice(value), stringlist: function (value) (value === "") ? [] : value.split(","), - stringmap: function (value) array(v.split(":") for (v in values(value.split(",")))).toObject(), + stringmap: function (value) array(util.split(v, /:/g, 2) for (v in values(value.split(",")))).toObject(), regexlist: function (value) (value === "") ? [] : value.split(",").map(Option.parseRegex), - regexmap: function (value) value.split(",").map(function (v) v.split(":")) - .map(function ([k, v]) v != null ? Option.parseRegex(k, v) : Option.parseRegex('.?', k)) + regexmap: function (value) value.split(",").map(function (v) util.split(v, /:/g, 2)) + .map(function ([k, v]) v != null ? Option.parseRegex(k, v) : Option.parseRegex(".?", k)) }, ops: { @@ -388,7 +388,7 @@ const Option = Class("Option", { stringmap: function (operator, values, scope, invert) { values = Array.concat(values); - orig = [k + "=" + v for ([k, v] in Iterator(this.values))]; + orig = [k + ":" + v for ([k, v] in Iterator(this.values))]; switch (operator) { case "+": @@ -1321,7 +1321,7 @@ const Options = Module("options", { case "regexmap": let vals = context.filter.split(","); target = vals.pop() || ""; - len = target.length - (target.indexOf("=") + 1); + len = target.length - (target.indexOf(":") + 1); break; case "charlist": len = 0; diff --git a/common/content/statusline.js b/common/content/statusline.js old mode 100755 new mode 100644 diff --git a/common/modules/base.jsm b/common/modules/base.jsm index 20b22715..4156c113 100644 --- a/common/modules/base.jsm +++ b/common/modules/base.jsm @@ -17,7 +17,7 @@ let currentModule; function defmodule(name, module, params) { module.NAME = name; module.EXPORTED_SYMBOLS = params.exports || []; - dump("defmodule " + name + "\n"); + defmodule.loadLog.push("defmodule " + name); for(let [, mod] in Iterator(params.require || [])) require(module, mod); @@ -30,10 +30,22 @@ function defmodule(name, module, params) { } currentModule = module; } +defmodule.loadLog = []; +// Object.defineProperty(defmodule.loadLog, "push", { value: function (val) { dump(val + "\n"); this[this.length] = val } }); defmodule.modules = []; +defmodule.times = {}; +defmodule.time = function (major, minor, func, self) { + let time = Date.now(); + let res = func.apply(self, Array.slice(arguments, 4)); + let delta = Date.now() - time; + defmodule.times[major] = (defmodule.times[major] || 0) + delta; + if (minor) + defmodule.times[major + ":" + minor] = (defmodule.times[major + ":" + minor] || 0) + delta; + return res; +} function endmodule() { - dump("endmodule " + currentModule.NAME + "\n"); + defmodule.loadLog.push("endmodule " + currentModule.NAME); loaded[currentModule.NAME] = 1; for(let [, mod] in Iterator(use[currentModule.NAME] || [])) require(mod, currentModule.NAME, "use"); @@ -41,7 +53,7 @@ function endmodule() { function require(obj, name, from) { try { - dump((from || "require") + ": loading " + name + " into " + obj.NAME + "\n"); + defmodule.loadLog.push((from || "require") + ": loading " + name + " into " + obj.NAME); Cu.import("resource://dactyl/" + name + ".jsm", obj); } catch (e) { diff --git a/common/modules/util.jsm b/common/modules/util.jsm index 5d854b44..9b124a29 100644 --- a/common/modules/util.jsm +++ b/common/modules/util.jsm @@ -699,12 +699,11 @@ const Util = Module("Util", { if (!re.global) re = RegExp(re.source || re, "g"); let match, start = 0, res = []; - while ((match = re.exec(str)) && --limit && match[0].length) { + while (--limit && (match = re.exec(str)) && match[0].length) { res.push(str.substring(start, match.index)); start = match.index + match[0].length; } - if (limit) - res.push(str.substring(start)); + res.push(str.substring(start)); return res; },