aboutsummaryrefslogtreecommitdiffstats
path: root/background_scripts
diff options
context:
space:
mode:
Diffstat (limited to 'background_scripts')
-rw-r--r--background_scripts/completion.coffee65
-rw-r--r--background_scripts/completion_search.coffee14
2 files changed, 32 insertions, 47 deletions
diff --git a/background_scripts/completion.coffee b/background_scripts/completion.coffee
index ebf56dde..68edad99 100644
--- a/background_scripts/completion.coffee
+++ b/background_scripts/completion.coffee
@@ -10,7 +10,7 @@
# - refresh(): (optional) refreshes the completer's data source (e.g. refetches the list of bookmarks).
# - cancel(): (optional) cancels any pending, cancelable action.
class Suggestion
- showRelevancy: false # Set this to true to render relevancy when debugging the ranking scores.
+ showRelevancy: true # Set this to true to render relevancy when debugging the ranking scores.
constructor: (@options) ->
# Required options.
@@ -397,20 +397,19 @@ class SearchEngineCompleter
callback engines
# Let the front-end vomnibar know the search-engine keywords. It needs to know them so that, when the
- # query goes from "w" to "w ", the vomnibar synchronously launches the next filter() request (all of which avoids
- # an ugly delay).
+ # query goes from "w" to "w ", the vomnibar can synchronously launch the next filter() request (which
+ # avoids an ugly delay/flicker).
port.postMessage
handler: "keywords"
keywords: key for own key of engines
filter: (request, onComplete) ->
{ queryTerms, query, engine } = request
- [ primarySuggestion, removePrimarySuggestion ] = [ null, false ]
{ custom, searchUrl, description } =
if engine
{ keyword, searchUrl, description } = engine
- extend request, { searchUrl, suppressLeadingKeyword: keyword }
+ extend request, { searchUrl, customSearchMode: true }
custom: true
searchUrl: searchUrl
description: description
@@ -421,35 +420,32 @@ class SearchEngineCompleter
return onComplete [] unless custom or 0 < queryTerms.length
- factor = Math.max 0, Math.min 1, Settings.get "omniSearchWeight"
+ factor = Math.max 0.0, Math.min 1.0, Settings.get "omniSearchWeight"
haveCompletionEngine = (0.0 < factor or custom) and CompletionSearch.haveCompletionEngine searchUrl
# Relevancy:
# - Relevancy does not depend upon the actual suggestion (so, it does not depend upon word
# relevancy, say). We assume that the completion engine has already factored that in. Also,
- # completion engines often handle spelling mistakes, in which case we wouldn't find the query terms
- # in the suggestion anyway.
+ # completion engines sometimes handle spelling mistakes, in which case we wouldn't find the query
+ # terms in the suggestion anyway.
# - Scores are weighted such that they retain the order provided by the completion engine.
# - The relavancy is higher if the query term is longer. The idea is that search suggestions are more
# likely to be relevant if, after typing some number of characters, the user hasn't yet found
# a useful suggestion from another completer.
#
characterCount = query.length - queryTerms.length + 1
- relevancy = (if custom then 0.9 else factor) * (Math.min(characterCount, 12.0)/12.0)
+ relevancy = (if custom then 0.5 else factor) * 12.0 / Math.max 12.0, characterCount
+ console.log factor, relevancy
- # This filter is applied to all of the suggestions from all of the completers.
+ # This filter is applied to all of the suggestions from all of the completers, after they have been
+ # aggregated by the MultiCompleter.
filter = (suggestions) ->
return suggestions unless custom and haveCompletionEngine
- # The primary suggestion was just a guess. If we've managed fetch actual completions (asynchronously),
- # then we now remove it.
- if removePrimarySuggestion
- suggestions = suggestions.filter (suggestion) -> suggestion != primarySuggestion
-
# We only accept suggestions:
# - from this completer, or
- # - from other completers, but then only if their URL matches this search engine and this query
- # (that is only if their URL could have been generated by this search engine).
+ # - from other completers, but then only if their URL matches this search engine and matches this
+ # query (that is only if their URL could have been generated by this search engine).
suggestions.filter (suggestion) ->
suggestion.type == description or
# This is a suggestion for the same search engine.
@@ -466,7 +462,6 @@ class SearchEngineCompleter
autoSelect: custom
forceAutoSelect: custom
highlightTerms: not haveCompletionEngine
- searchSuggestionType: "primary"
mkSuggestion = (suggestion) ->
new Suggestion
@@ -477,43 +472,27 @@ class SearchEngineCompleter
relevancy: relevancy *= 0.9
insertText: suggestion
highlightTerms: false
- searchSuggestionType: "completion"
-
- deliverCompletions = (onComplete, completions, args...) ->
- # Make the first suggestion float to the top of the vomnibar (except if we would be competing with the
- # domain completer, which also assigns a relevancy of 1).
- if 0 < completions.length
- if custom # or (1 < queryTerms.length or /\S\s/.test query)
- extend completions[0],
- relevancy: 1
- autoSelect: custom
- forceAutoSelect: custom
- insertText: null
- onComplete completions, args...
cachedSuggestions =
if haveCompletionEngine then CompletionSearch.complete searchUrl, queryTerms else null
- suggestions =
- if cachedSuggestions? and 0 < cachedSuggestions.length
- cachedSuggestions.map mkSuggestion
- else if custom
- [ primarySuggestion ]
- else
- []
+ suggestions = []
+ suggestions.push primarySuggestion if custom
+ suggestions.push cachedSuggestions.map(mkSuggestion)... if custom and cachedSuggestions?
if queryTerms.length == 0 or cachedSuggestions? or not haveCompletionEngine
# There is no prospect of adding further completions.
- deliverCompletions onComplete, suggestions, { filter, continuation: null }
+ suggestions.push cachedSuggestions.map(mkSuggestion)... if cachedSuggestions?
+ onComplete suggestions, { filter, continuation: null }
else
- # Post the initial suggestions, then deliver further completions asynchronously, as a continuation.
- deliverCompletions onComplete, suggestions,
+ # Post the initial suggestions, but then deliver any further completions asynchronously, as a
+ # continuation.
+ onComplete suggestions,
filter: filter
continuation: (onComplete) =>
CompletionSearch.complete searchUrl, queryTerms, (suggestions = []) =>
console.log "fetched suggestions:", suggestions.length, query if SearchEngineCompleter.debug
- removePrimarySuggestion = 0 < suggestions.length
- deliverCompletions onComplete, suggestions.map mkSuggestion
+ onComplete suggestions.map mkSuggestion
# A completer which calls filter() on many completers, aggregates the results, ranks them, and returns the top
# 10. All queries from the vomnibar come through a multi completer.
diff --git a/background_scripts/completion_search.coffee b/background_scripts/completion_search.coffee
index a9521a3d..c6824594 100644
--- a/background_scripts/completion_search.coffee
+++ b/background_scripts/completion_search.coffee
@@ -1,6 +1,6 @@
CompletionSearch =
- debug: false
+ debug: true
inTransit: {}
completionCache: new SimpleCache 2 * 60 * 60 * 1000, 5000 # Two hours, 5000 entries.
engineCache:new SimpleCache 1000 * 60 * 60 * 1000 # 1000 hours.
@@ -75,13 +75,16 @@ CompletionSearch =
# Verify that the previous query is a prefix of the current query.
return false unless 0 == query.indexOf @mostRecentQuery.toLowerCase()
# Verify that every previous suggestion contains the text of the new query.
- for suggestion in (@mostRecentSuggestions.map (s) -> s.toLowerCase())
+ # Note: @mostRecentSuggestions may also be empty, in which case we drop though. The effect is that
+ # previous queries with no suggestions suppress subsequent no-hope HTTP requests as the user continues
+ # to type.
+ for suggestion in @mostRecentSuggestions
return false unless 0 <= suggestion.indexOf query
# Ok. Re-use the suggestion.
true
if reusePreviousSuggestions
- console.log "reuse previous query:", @mostRecentQuery if @debug
+ console.log "reuse previous query:", @mostRecentQuery, @mostRecentSuggestions.length if @debug
return callback @completionCache.set completionCacheKey, @mostRecentSuggestions
# That's all of the caches we can try. Bail if the caller is only requesting synchronous results. We
@@ -104,8 +107,11 @@ CompletionSearch =
# incorrect or out-of-date completion engines.
try
suggestions = engine.parse xhr
+ # Make all suggestions lower case. It looks odd when suggestions from one completion engine are
+ # upper case, and those from another are lower case.
+ suggestions = (suggestion.toLowerCase() for suggestion in suggestions)
# Filter out the query itself. It's not adding anything.
- suggestions = (suggestion for suggestion in suggestions when suggestion.toLowerCase() != query)
+ suggestions = (suggestion for suggestion in suggestions when suggestion != query)
console.log "GET", url if @debug
catch
suggestions = []