aboutsummaryrefslogtreecommitdiffstats
path: root/background_scripts
diff options
context:
space:
mode:
authorStephen Blott2015-05-13 14:22:57 +0100
committerStephen Blott2015-05-13 14:22:59 +0100
commit78645aa7d8c0a03bd33f619bbb39ba0a7d0c4921 (patch)
tree5fcf87cb5216f0b25a7431fe5dacefe9b5fe4288 /background_scripts
parent9fe22a3c72c64ae61c6b155efaeaa2e2125e199d (diff)
downloadvimium-78645aa7d8c0a03bd33f619bbb39ba0a7d0c4921.tar.bz2
Search completion; yet another reworking.
I'm having difficulty getting all aspects of the UX right for all combinations of modes. This is the latest attempt. The main goal is to mimic Chrome to the greatest extent possible. There will be more to come, but I think this is an improvement.
Diffstat (limited to 'background_scripts')
-rw-r--r--background_scripts/completion.coffee95
1 files changed, 44 insertions, 51 deletions
diff --git a/background_scripts/completion.coffee b/background_scripts/completion.coffee
index db151bed..d3d54521 100644
--- a/background_scripts/completion.coffee
+++ b/background_scripts/completion.coffee
@@ -403,12 +403,14 @@ class SearchEngineCompleter
handler: "keywords"
keywords: key for own key of engines
- filter: ({ queryTerms, query, engine, fetchOnlyThePrimarySuggestion }, onComplete) ->
+ 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 }
custom: true
searchUrl: searchUrl
description: description
@@ -420,8 +422,7 @@ class SearchEngineCompleter
return onComplete [] unless custom or 0 < queryTerms.length
factor = Settings.get "omniSearchWeight"
- haveCompletionEngine = CompletionSearch.haveCompletionEngine searchUrl
- haveCompletionEngine = false if factor == 0.0 and not custom
+ 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
@@ -436,47 +437,36 @@ class SearchEngineCompleter
characterCount = query.length - queryTerms.length + 1
relevancy = (if custom then 0.9 else factor) * (Math.min(characterCount, 10.0)/10.0)
- # This distinguishes two very different kinds of vomnibar baviours, the newer bahviour (true) and the
- # legacy behavior (false). We retain the latter for the default search engine, and for custom search
- # engines for which we do not have a completion engine. By "exclusive vomnibar", we mean that
- # this completer exclusively controls which suggestions may or may not be included, including filtering
- # out suggestions from other completers.
- useExclusiveVomnibar = custom and haveCompletionEngine
-
- filter = null
- if useExclusiveVomnibar
- filter = (suggestions) ->
- # We accept suggestions from this completer; and we also accept suggestions from other completers, but
- # only if their URL matches this search engine and this query (ie. only if they could have been
- # generated by this search engine previously).
- suggestions = suggestions.filter (suggestion) ->
- suggestion.type == description or
- # This is a suggestion for the same search engine.
- (suggestion.url.startsWith(engine.searchUrlPrefix) and
- # And the URL suffix (which must contain the query part) matches the current query.
- RankingUtils.matches queryTerms, suggestion.url[engine.searchUrlPrefix.length..])
-
- if fetchOnlyThePrimarySuggestion
- suggestions.filter (suggestion) -> suggestion == primarySuggestion
- else if removePrimarySuggestion
- suggestions.filter (suggestion) -> suggestion != primarySuggestion
- else
- suggestions
+ # This filter is applied to all of the suggestions from all of the completers.
+ 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).
+ suggestions.filter (suggestion) ->
+ suggestion.type == description or
+ # This is a suggestion for the same search engine.
+ (suggestion.url.startsWith(engine.searchUrlPrefix) and
+ # And the URL suffix (which must contain the query part) matches the current query.
+ RankingUtils.matches queryTerms, suggestion.url[engine.searchUrlPrefix.length..])
primarySuggestion = new Suggestion
queryTerms: queryTerms
type: description
url: Utils.createSearchUrl queryTerms, searchUrl
title: queryTerms.join " "
- relevancy: relevancy
- insertText: if useExclusiveVomnibar then query else null
- # We suppress the leading keyword for custom search engines; for example, "w query terms" becomes just
- # "query terms" in the vomnibar.
- suppressLeadingKeyword: custom
- # Toggles for the legacy behaviour.
- autoSelect: not useExclusiveVomnibar
- forceAutoSelect: not useExclusiveVomnibar
- highlightTerms: not useExclusiveVomnibar
+ relevancy: 1
+ autoSelect: custom
+ forceAutoSelect: custom
+ highlightTerms: not haveCompletionEngine
+ searchSuggestionType: "primary"
mkSuggestion = (suggestion) ->
new Suggestion
@@ -487,40 +477,43 @@ class SearchEngineCompleter
relevancy: relevancy *= 0.9
insertText: suggestion
highlightTerms: false
- searchEngineCompletionSuggestion: true
+ 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
- completions[0].relevancy = 1 if custom or (1 < queryTerms.length or /\S\s/.test query)
+ if custom or (1 < queryTerms.length or /\S\s/.test query)
+ extend completions[0],
+ relevancy: 1
+ autoSelect: custom
+ forceAutoSelect: custom
+ isPrimarySuggestion: custom
+ insertText: null
onComplete completions, args...
- # If we have cached suggestions, then we can bundle them immediately (otherwise we'll have to fetch them
- # asynchronously).
- cachedSuggestions = null
- cachedSuggestions = CompletionSearch.complete searchUrl, queryTerms if haveCompletionEngine and not fetchOnlyThePrimarySuggestion
+ cachedSuggestions =
+ if haveCompletionEngine then CompletionSearch.complete searchUrl, queryTerms else null
suggestions =
- if haveCompletionEngine and cachedSuggestions? and 0 < cachedSuggestions.length and not fetchOnlyThePrimarySuggestion
+ if cachedSuggestions? and 0 < cachedSuggestions.length
cachedSuggestions.map mkSuggestion
- else if custom or fetchOnlyThePrimarySuggestion
+ else if custom
[ primarySuggestion ]
else
[]
- if queryTerms.length == 0 or cachedSuggestions? or not haveCompletionEngine or fetchOnlyThePrimarySuggestion
- # There is no prospect of adding further completions, or further completions will not be used (eg.
- # because the vomnibar is closing and we've been asked for the primary suggestion only).
+ if queryTerms.length == 0 or cachedSuggestions? or not haveCompletionEngine
+ # There is no prospect of adding further completions.
deliverCompletions onComplete, suggestions, { filter, continuation: null }
else
- # Post initial suggestions, then deliver further completions asynchronously, as a continuation.
+ # Post the initial suggestions, then deliver further completions asynchronously, as a continuation.
deliverCompletions onComplete, suggestions,
filter: filter
continuation: (onComplete) =>
CompletionSearch.complete searchUrl, queryTerms, (suggestions = []) =>
console.log "fetched suggestions:", suggestions.length, query if SearchEngineCompleter.debug
- removePrimarySuggestion = primarySuggestion? and 0 < suggestions.length
+ removePrimarySuggestion = 0 < suggestions.length
deliverCompletions onComplete, suggestions.map mkSuggestion
# A completer which calls filter() on many completers, aggregates the results, ranks them, and returns the top