diff options
| author | Stephen Blott | 2015-06-06 20:19:33 +0100 | 
|---|---|---|
| committer | Stephen Blott | 2015-06-06 20:19:33 +0100 | 
| commit | 616261ef8364cbd99765d651dfe8acd5ff55b453 (patch) | |
| tree | c7b75f7aa9a960132ba484935a4c1ed1cfb63a29 /background_scripts/completion_search.coffee | |
| parent | c20e5d44455be8ac885f0d7c42e05ec9857bd203 (diff) | |
| parent | cb900a255113b8304d8931f7c6294e20f7f9f36d (diff) | |
| download | vimium-616261ef8364cbd99765d651dfe8acd5ff55b453.tar.bz2 | |
Merge branch 'rework-completions'
Conflicts:
	background_scripts/completion.coffee
	background_scripts/completion_engines.coffee
Diffstat (limited to 'background_scripts/completion_search.coffee')
| -rw-r--r-- | background_scripts/completion_search.coffee | 78 | 
1 files changed, 55 insertions, 23 deletions
| diff --git a/background_scripts/completion_search.coffee b/background_scripts/completion_search.coffee index b26194e6..7926b45b 100644 --- a/background_scripts/completion_search.coffee +++ b/background_scripts/completion_search.coffee @@ -1,4 +1,39 @@ +# This is a wrapper class for completion engines.  It handles the case where a custom search engine includes a +# prefix query term (or terms).  For example: +# +#   http://www.google.com/search?q=javascript+%s +# +# In this case, we get better suggestions if we include the term "javascript" in queries sent to the +# completion engine.  This wrapper handles adding such prefixes to completion-engine queries and removing them +# from the resulting suggestions. +class EnginePrefixWrapper +  constructor: (@searchUrl, @engine) -> + +  getUrl: (queryTerms) -> +    # This tests whether @searchUrl contains something of the form "...=abc+def+%s...", from which we extract +    # a prefix of the form "abc def ". +    if /\=.+\+%s/.test @searchUrl +      terms = @searchUrl.replace /\+%s.*/, "" +      terms = terms.replace /.*=/, "" +      terms = terms.replace /\+/g, " " + +      queryTerms = [ terms.split(" ")..., queryTerms... ] +      prefix = "#{terms} " + +      @postprocessSuggestions = +        (suggestions) -> +          for suggestion in suggestions +            continue unless suggestion.startsWith prefix +            suggestion[prefix.length..] + +    @engine.getUrl queryTerms + +  parse: (xhr) -> +    @postprocessSuggestions @engine.parse xhr + +  postprocessSuggestions: (suggestions) -> suggestions +  CompletionSearch =    debug: false    inTransit: {} @@ -58,34 +93,30 @@ CompletionSearch =      return callback [] if 1 == queryTerms.length and Utils.isUrl query      return callback [] if Utils.hasJavascriptPrefix query -    # Cache completions.  However, completions depend upon both the searchUrl and the query terms.  So we need -    # to generate a key.  We mix in some junk generated by pwgen. A key clash might be possible, but -    # is vanishingly unlikely. -    junk = "//Zi?ei5;o//" -    completionCacheKey = searchUrl + junk + queryTerms.map((s) -> s.toLowerCase()).join junk - +    completionCacheKey = JSON.stringify [ searchUrl, queryTerms ]      if @completionCache.has completionCacheKey        console.log "hit", completionCacheKey if @debug        return callback @completionCache.get completionCacheKey      # If the user appears to be typing a continuation of the characters of the most recent query, then we can      # sometimes re-use the previous suggestions. -    if @mostRecentQuery? and @mostRecentSuggestions? -      reusePreviousSuggestions = do => -        # 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. -        # 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, @mostRecentSuggestions.length if @debug -        return callback @completionCache.set completionCacheKey, @mostRecentSuggestions +    if @mostRecentQuery? and @mostRecentSuggestions? and @mostRecentSearchUrl? +      if searchUrl == @mostRecentSearchUrl +        reusePreviousSuggestions = do => +          # 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. +          # 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, @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      # signal that we haven't found a match by returning null. @@ -98,7 +129,7 @@ CompletionSearch =          # Elide duplicate requests. First fetch the suggestions...          @inTransit[completionCacheKey] ?= new AsyncDataFetcher (callback) => -          engine = @lookupEngine searchUrl +          engine = new EnginePrefixWrapper searchUrl, @lookupEngine searchUrl            url = engine.getUrl queryTerms            @get searchUrl, url, (xhr = null) => @@ -124,6 +155,7 @@ CompletionSearch =          # ... then use the suggestions.          @inTransit[completionCacheKey].use (suggestions) => +          @mostRecentSearchUrl = searchUrl            @mostRecentQuery = query            @mostRecentSuggestions = suggestions            callback @completionCache.set completionCacheKey, suggestions | 
