aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Blott2015-05-06 07:40:46 +0100
committerStephen Blott2015-05-06 09:29:15 +0100
commit5752c0ead0a65fc2329515509f66e00bd6ee2f60 (patch)
tree0cc13d0e924c0daf69312036f2dc1fe28aa84494
parent372e65d7b44c3f0ad3f522bd6b8c9cfacd693186 (diff)
downloadvimium-5752c0ead0a65fc2329515509f66e00bd6ee2f60.tar.bz2
Search completion; more tweaks.
-rw-r--r--background_scripts/completion.coffee37
-rw-r--r--background_scripts/completion_engines.coffee26
-rw-r--r--lib/utils.coffee11
3 files changed, 42 insertions, 32 deletions
diff --git a/background_scripts/completion.coffee b/background_scripts/completion.coffee
index 4ae0c44b..bffb9700 100644
--- a/background_scripts/completion.coffee
+++ b/background_scripts/completion.coffee
@@ -363,23 +363,22 @@ class SearchEngineCompleter
haveDescription = description? and 0 < description.length
description ||= "#{if custom then "custom " else ""}search"
+ queryTerms = queryTerms[1..] if custom
+ query = queryTerms.join " "
+
+ if queryTerms.length == 0
+ return onComplete suggestions
+
# For custom search engines, we add an auto-selected suggestion.
if custom
- queryTerms = queryTerms[1..]
- query = queryTerms.join " "
suggestions.push new Suggestion
queryTerms: queryTerms
type: description
- url: searchUrl.replace /%s/g, Utils.createSearchQuery query.split /\s+/
- title: if haveDescription then query else "#{keyword}: #{query}"
+ url: Utils.createSearchUrl queryTerms, searchUrl
+ title: if haveDescription then query else "#{keyword}: #{query}"
relevancy: 1
- autoSelect: true
highlightTerms: false
- else
- query = queryTerms.join " "
-
- if queryTerms.length == 0
- return onComplete suggestions
+ autoSelect: true
onComplete suggestions, (existingSuggestions, onComplete) =>
suggestions = []
@@ -399,23 +398,22 @@ class SearchEngineCompleter
relavancy = 0.6 * (Math.min(characterCount, 10.0)/10.0)
if 0 < existingSuggestions.length
- existingSuggestionMinScore = existingSuggestions[existingSuggestions.length-1].relevancy
- if relavancy < existingSuggestionMinScore and MultiCompleter.maxResults <= existingSuggestions.length
+ existingSuggestionsMinScore = existingSuggestions[existingSuggestions.length-1].relevancy
+ if relavancy < existingSuggestionsMinScore and MultiCompleter.maxResults <= existingSuggestions.length
# No suggestion we propose will have a high enough relavancy to beat the existing suggestions, so bail
# immediately.
return onComplete []
- CompletionEngines.complete searchUrl, queryTerms, (searchSuggestions = []) =>
- for suggestion in searchSuggestions
+ CompletionEngines.complete searchUrl, queryTerms, (completionSuggestions = []) =>
+ for suggestion in completionSuggestions
suggestions.push new Suggestion
queryTerms: queryTerms
type: description
- url: searchUrl.replace /%s/g, Utils.createSearchQuery suggestion.split /\s+/
+ url: Utils.createSearchUrl suggestion, searchUrl
title: suggestion
- relevancy: relavancy
- insertText: if custom then "#{keyword} #{suggestion}" else suggestion
+ relevancy: relavancy *= 0.9
highlightTerms: false
- relavancy *= 0.9
+ insertText: if custom then "#{keyword} #{suggestion}" else suggestion
# We keep at least three suggestions (if possible) and at most six. We keep more than three only if
# there are enough slots. The idea is that these suggestions shouldn't wholly displace suggestions
@@ -501,7 +499,8 @@ class MultiCompleter
@filterInProgress = false
if shouldRunContinuation
continuation suggestions, (newSuggestions) =>
- onComplete @prepareSuggestions queryTerms, suggestions.concat newSuggestions
+ if 0 < newSuggestions.length
+ onComplete @prepareSuggestions queryTerms, suggestions.concat newSuggestions
else
@filter @mostRecentQuery.queryTerms, @mostRecentQuery.onComplete if @mostRecentQuery
diff --git a/background_scripts/completion_engines.coffee b/background_scripts/completion_engines.coffee
index 0177806a..1386256f 100644
--- a/background_scripts/completion_engines.coffee
+++ b/background_scripts/completion_engines.coffee
@@ -116,6 +116,9 @@ completionEngines = [
CompletionEngines =
debug: true
+ # The amount of time to wait for new completions before launching the HTTP request.
+ delay: 250
+
get: (searchUrl, url, callback) ->
xhr = new XMLHttpRequest()
xhr.open "GET", url, true
@@ -139,7 +142,7 @@ CompletionEngines =
engine = new engine()
return @engineCache.set searchUrl, engine if engine.match searchUrl
- # This is the main (actually, the only) entry point.
+ # This is the main entry point.
# - searchUrl is the search engine's URL, e.g. Settings.get("searchUrl"), or a custome search engine's URL.
# This is only used as a key for determining the relevant completion engine.
# - queryTerms are the queryTerms.
@@ -169,34 +172,41 @@ CompletionEngines =
completionCacheKey = searchUrl + junk + queryTerms.join junk
@completionCache ?= new SimpleCache 60 * 60 * 1000, 2000 # One hour, 2000 entries.
if @completionCache.has completionCacheKey
- console.log "hit", completionCacheKey if @debug
- return callback @completionCache.get completionCacheKey
+ # We add a short delay, even for a cache hit. This avoids an ugly flicker when the additional
+ # suggestions are posted. It also makes the vomnibar behave similarly regardless of whether there's a
+ # cache hit.
+ Utils.setTimeout @delay, =>
+ console.log "hit", completionCacheKey if @debug
+ callback @completionCache.get completionCacheKey
+ return
fetchSuggestions = (callback) =>
engine = @lookupEngine searchUrl
url = engine.getUrl queryTerms
- console.log "get", url if @debug
query = queryTerms.join(" ").toLowerCase()
@get searchUrl, url, (xhr = null) =>
# Parsing the response may fail if we receive an unexpected or an unexpectedly-formatted response. In
- # all cases, we fall back to the catch clause, below.
+ # all cases, we fall back to the catch clause, below. Therefore, we "fail safe" in the case of
+ # incorrect or out-of-date completion engines.
try
suggestions = engine.parse xhr
# Make sure we really do have an iterable of strings.
suggestions = (suggestion for suggestion in suggestions when "string" == typeof suggestion)
# Filter out the query itself. It's not adding anything.
suggestions = (suggestion for suggestion in suggestions when suggestion.toLowerCase() != query)
+ console.log "GET", url if @debug
catch
suggestions = []
- # We cache failures, but remove them after just ten minutes. This (it is hoped) avoids repeated
- # XMLHttpRequest failures over a short period of time.
+ # We allow failures to be cached, but remove them after just ten minutes. This (it is hoped) avoids
+ # repeated unnecessary XMLHttpRequest failures over a short period of time.
removeCompletionCacheKey = => @completionCache.set completionCacheKey, null
setTimeout removeCompletionCacheKey, 10 * 60 * 1000 # Ten minutes.
+ console.log "fail", url if @debug
callback suggestions
# We pause in case the user is still typing.
- Utils.setTimeout 200, handler = @mostRecentHandler = =>
+ Utils.setTimeout @delay, handler = @mostRecentHandler = =>
if handler != @mostRecentHandler # Bail if another completion has begun, or the user is typing.
console.log "bail", completionCacheKey if @debug
return callback []
diff --git a/lib/utils.coffee b/lib/utils.coffee
index e97872f0..354d82f6 100644
--- a/lib/utils.coffee
+++ b/lib/utils.coffee
@@ -96,11 +96,12 @@ Utils =
query = query.split(/\s+/) if typeof(query) == "string"
query.map(encodeURIComponent).join "+"
- # Creates a search URL from the given :query.
- createSearchUrl: (query) ->
- # It would be better to pull the default search engine from chrome itself. However, unfortunately chrome
- # does not provide an API for doing so.
- Settings.get("searchUrl") + @createSearchQuery query
+ # Create a search URL from the given :query (using either the provided search URL, or the default one).
+ # It would be better to pull the default search engine from chrome itself. However, chrome does not provide
+ # an API for doing so.
+ createSearchUrl: (query, searchUrl = Settings.get("searchUrl")) ->
+ searchUrl += "%s" unless 0 <= searchUrl.indexOf "%s"
+ searchUrl.replace /%s/g, @createSearchQuery query
# Converts :string into a Google search if it's not already a URL. We don't bother with escaping characters
# as Chrome will do that for us.