diff options
| author | Stephen Blott | 2015-05-13 14:22:57 +0100 |
|---|---|---|
| committer | Stephen Blott | 2015-05-13 14:22:59 +0100 |
| commit | 78645aa7d8c0a03bd33f619bbb39ba0a7d0c4921 (patch) | |
| tree | 5fcf87cb5216f0b25a7431fe5dacefe9b5fe4288 /background_scripts | |
| parent | 9fe22a3c72c64ae61c6b155efaeaa2e2125e199d (diff) | |
| download | vimium-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.coffee | 95 |
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 |
