diff --git a/content/bindings.xml b/content/bindings.xml index 6d9ecb2b..d9653c5e 100644 --- a/content/bindings.xml +++ b/content/bindings.xml @@ -21,6 +21,117 @@ + + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + diff --git a/content/bookmarks.js b/content/bookmarks.js index 7c2daf51..493e9431 100644 --- a/content/bookmarks.js +++ b/content/bookmarks.js @@ -235,7 +235,7 @@ function Bookmarks() //{{{ "string", "google", { completer: function completer(context) completion.search(context, true), - validator: function validator(value) completion.runCompleter("search", "", true).some(function ([s]) s == value) + validator: options.validateCompleter }); options.add(["preload"], diff --git a/content/completion.js b/content/completion.js index 684edbce..205edb7d 100644 --- a/content/completion.js +++ b/content/completion.js @@ -464,6 +464,14 @@ CompletionContext.prototype = { context.incomplete = false; } }, + + wait: function wait(interruptable, timeout) + { + let end = Date.now() + timeout; + while (this.incomplete && (!timeout || Date.now() > end)) + liberator.threadYield(true, interruptable); + return this.incomplete; + } } function Completion() //{{{ @@ -1015,8 +1023,7 @@ function Completion() //{{{ let res = context.fork.apply(context, ["run", 0, this, name].concat(Array.slice(arguments, 2))); if (res) // FIXME return { items: res.map(function (i) ({ item: i })) }; - while (context.incomplete) - liberator.threadYield(true, true); + context.wait(true); return context.allItems; }, diff --git a/content/options.js b/content/options.js index 6b672ab0..be173f52 100644 --- a/content/options.js +++ b/content/options.js @@ -944,10 +944,12 @@ function Options() //{{{ // TODO: Run this by default? validateCompleter: function (values) { - let self = this; - let completions = completion.runCompleter(function (context) self.completer(context), ""); + let context = CompletionContext(""); + let res = this.completer(context); + if (!res) + res = context.allItems.map(function (item) [item.text]); return Array.concat(values).every( - function (value) completions.some(function (item) item[0] == value)); + function (value) res.some(function (item) item[0] == value)); }, get store() storage.options, diff --git a/content/ui.js b/content/ui.js index 302be48a..79b42057 100644 --- a/content/ui.js +++ b/content/ui.js @@ -106,6 +106,7 @@ function CommandLine() //{{{ var wildIndex = 0; // keep track how often we press in a row var startHints = false; // whether we're waiting to start hints mode + var lastSubstring = ""; var statusTimer = new util.Timer(5, 100, function statusTell() { if (completionIndex >= completions.items.length) @@ -324,6 +325,9 @@ function CommandLine() //{{{ // highlight= won't work here. let start = commandWidget.selectionStart; let substring = completionContext.longestAllSubstring.substr(start - completionContext.allItems.start); + if (substring.length < 2 && substring != lastSubstring.substr(Math.max(0, lastSubstring.length - substring.length))) + return; + lastSubstring = substring; let node = {substring} editor.insertNode(util.xmlToDom(node, document), editor.rootElement, 1); commandWidget.selectionStart = commandWidget.selectionEnd = start;