aboutsummaryrefslogtreecommitdiffstats
path: root/background_scripts/completion.coffee
diff options
context:
space:
mode:
Diffstat (limited to 'background_scripts/completion.coffee')
-rw-r--r--background_scripts/completion.coffee57
1 files changed, 41 insertions, 16 deletions
diff --git a/background_scripts/completion.coffee b/background_scripts/completion.coffee
index 91fb85e1..5fc98b88 100644
--- a/background_scripts/completion.coffee
+++ b/background_scripts/completion.coffee
@@ -22,18 +22,18 @@ class Suggestion
@title = ""
# Extra data which will be available to the relevancy function.
@relevancyData = null
- # If @autoSelect is truthy, then this suggestion is automatically pre-selected in the vomnibar. There may
- # be at most one such suggestion.
+ # If @autoSelect is truthy, then this suggestion is automatically pre-selected in the vomnibar. This only
+ # affects the suggestion in slot 0 in the vomnibar.
@autoSelect = false
- # If truthy (and @autoSelect is truthy too), then this suggestion is always pre-selected when the query
- # changes. There may be at most one such suggestion.
- @forceAutoSelect = false
- # If @highlightTerms is true, then we highlight matched terms in the title and URL.
+ # If @highlightTerms is true, then we highlight matched terms in the title and URL. Otherwise we don't.
@highlightTerms = true
- # If @insertText is a string, then the indicated text is inserted into the vomnibar input when the
- # suggestion is selected.
+ # @insertText is text to insert into the vomnibar input when the suggestion is selected.
@insertText = null
+ # Other options set by individual completers include:
+ # - tabId (TabCompleter)
+ # - isSearchSuggestion, customSearchMode (SearchEngineCompleter)
+
extend this, @options
computeRelevancy: ->
@@ -230,13 +230,16 @@ class BookmarkCompleter
RankingUtils.wordRelevancy(suggestion.queryTerms, suggestion.url, suggestion.title)
class HistoryCompleter
- filter: ({ queryTerms }, onComplete) ->
+ filter: ({ queryTerms, seenTabToOpenCompletionList }, onComplete) ->
@currentSearch = { queryTerms: @queryTerms, onComplete: @onComplete }
results = []
HistoryCache.use (history) =>
results =
if queryTerms.length > 0
history.filter (entry) -> RankingUtils.matches(queryTerms, entry.url, entry.title)
+ else if seenTabToOpenCompletionList
+ # <Tab> opens the completion list, even without a query.
+ history
else
[]
onComplete results.map (entry) =>
@@ -251,6 +254,8 @@ class HistoryCompleter
computeRelevancy: (suggestion) ->
historyEntry = suggestion.relevancyData
recencyScore = RankingUtils.recencyScore(historyEntry.lastVisitTime)
+ # If there are no query terms, then relevancy is based on recency alone.
+ return recencyScore if suggestion.queryTerms.length == 0
wordRelevancy = RankingUtils.wordRelevancy(suggestion.queryTerms, suggestion.url, suggestion.title)
# Average out the word score and the recency. Recency has the ability to pull the score up, but not down.
(wordRelevancy + Math.max recencyScore, wordRelevancy) / 2
@@ -397,9 +402,10 @@ class SearchEngineCompleter
# This looks up the custom search engine and, if one is found, notes it and removes its keyword from the
# query terms.
- triageRequest: (request) ->
+ preprocessRequest: (request) ->
@searchEngines.use (engines) =>
{ queryTerms, query } = request
+ request.searchEngines = engines
keyword = queryTerms[0]
# Note. For a keyword "w", we match "w search terms" and "w ", but not "w" on its own.
if keyword and engines[keyword] and (1 < queryTerms.length or /\s$/.test query)
@@ -468,7 +474,7 @@ class SearchEngineCompleter
# We only accept suggestions:
# - from this completer, or
# - 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).
+ # 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.
@@ -483,8 +489,8 @@ class SearchEngineCompleter
title: queryTerms.join " "
relevancy: 1
autoSelect: custom
- forceAutoSelect: custom
highlightTerms: not haveCompletionEngine
+ isSearchSuggestion: true
mkSuggestion = (suggestion) =>
new Suggestion
@@ -542,6 +548,22 @@ class SearchEngineCompleter
Suggestion.boostRelevancyScore 0.5,
relevancyData * RankingUtils.wordRelevancy queryTerms, title, title
+ postProcessSuggestions: (request, suggestions) ->
+ return unless request.searchEngines
+ engines = (engine for _, engine of request.searchEngines)
+ engines.sort (a,b) -> b.searchUrl.length - a.searchUrl.length
+ engines.push keyword: null, description: "search", searchUrl: Settings.get "searchUrl"
+ for suggestion in suggestions
+ unless suggestion.isSearchSuggestion or suggestion.insertText
+ for engine in engines
+ if suggestion.insertText = Utils.extractQuery engine.searchUrl, suggestion.url
+ # suggestion.customSearchMode informs the vomnibar that, if the users edits the text from this
+ # suggestion, then custom search-engine mode should be activated.
+ suggestion.customSearchMode = engine.keyword
+ suggestion.title = suggestion.insertText
+ suggestion.type = engine.description ? "custom search"
+ break
+
# 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.
class MultiCompleter
@@ -559,7 +581,7 @@ class MultiCompleter
# Provide each completer with an opportunity to see (and possibly alter) the request before it is
# launched.
- completer.triageRequest? request for completer in @completers
+ completer.preprocessRequest? request for completer in @completers
RegexpCache.clear()
{ queryTerms } = request
@@ -585,7 +607,7 @@ class MultiCompleter
# Post results, unless there are none and we will be running a continuation. This avoids
# collapsing the vomnibar briefly before expanding it again, which looks ugly.
unless suggestions.length == 0 and shouldRunContinuations
- suggestions = @prepareSuggestions queryTerms, suggestions
+ suggestions = @prepareSuggestions request, queryTerms, suggestions
onComplete
results: suggestions
mayCacheResults: continuations.length == 0
@@ -602,7 +624,7 @@ class MultiCompleter
jobs.onReady =>
suggestions = filter suggestions for filter in filters
- suggestions = @prepareSuggestions queryTerms, suggestions
+ suggestions = @prepareSuggestions request, queryTerms, suggestions
# We post these results even if a new query has started. The vomnibar will not display them
# (because they're arriving too late), but it will cache them.
onComplete
@@ -614,7 +636,7 @@ class MultiCompleter
if @mostRecentQuery
@filter @mostRecentQuery...
- prepareSuggestions: (queryTerms, suggestions) ->
+ prepareSuggestions: (request, queryTerms, suggestions) ->
# Compute suggestion relevancies and sort.
suggestion.computeRelevancy queryTerms for suggestion in suggestions
suggestions.sort (a, b) -> b.relevancy - a.relevancy
@@ -629,6 +651,9 @@ class MultiCompleter
break if count++ == @maxResults
seenUrls[url] = suggestion
+ # Give each completer the opportunity to tweak the suggestions.
+ completer.postProcessSuggestions? request, suggestions for completer in @completers
+
# Generate HTML for the remaining suggestions and return them.
suggestion.generateHtml() for suggestion in suggestions
suggestions