diff options
| -rw-r--r-- | background_scripts/completion.coffee | 97 | ||||
| -rw-r--r-- | background_scripts/main.coffee | 2 | ||||
| -rw-r--r-- | background_scripts/search_engines.coffee | 32 | ||||
| -rw-r--r-- | background_scripts/settings.coffee | 2 | ||||
| -rw-r--r-- | pages/vomnibar.coffee | 2 |
5 files changed, 82 insertions, 53 deletions
diff --git a/background_scripts/completion.coffee b/background_scripts/completion.coffee index c13d0625..cb5f64b0 100644 --- a/background_scripts/completion.coffee +++ b/background_scripts/completion.coffee @@ -322,52 +322,61 @@ class TabCompleter tabRecency.recencyScore(suggestion.tabId) class SearchEngineCompleter - refresh: -> - - filter: (queryTerms, onComplete) -> - SearchEngines.complete Settings.get("searchUrl"), queryTerms, (suggestions = []) => - characterCount = queryTerms.join("").length - completions = - for suggestion in suggestions - url = Utils.createSearchUrl suggestion.split /\s+/ - suggestion = new Suggestion queryTerms, "search", url, suggestion, @computeRelevancy, characterCount - suggestion.insertText = true - suggestion - onComplete completions - - computeRelevancy: (suggestion) -> - # We score search-engine completions by word relevancy, but weight the score increasingly as the number of - # characters in the query terms increases. The idea is that, the more the user has had to type, the less - # likely it is that one of the other suggestion types has proven useful, so the more likely it is that - # this suggestion will be useful. - # NOTE(smblott) This will require tweaking. - (Math.min(suggestion.extraRelevancyData, 12)/12) * - RankingUtils.wordRelevancy suggestion.queryTerms, suggestion.title, suggestion.title - -# A completer which will return your search engines -class CustomSearchEngineCompleter searchEngines: {} filter: (queryTerms, onComplete) -> - {url: url, description: description} = @getSearchEngineMatches queryTerms + { keyword: keyword, url: url, description: description } = @getSearchEngineMatches queryTerms + custom = url? suggestions = [] - if url - url = url.replace(/%s/g, Utils.createSearchQuery queryTerms[1..]) - if description - type = description - query = queryTerms[1..].join " " + + mkUrl = + if custom + (string) -> url.replace /%s/g, Utils.createSearchQuery string.split /\s+/ else - type = "search" - query = queryTerms[0] + ": " + queryTerms[1..].join(" ") - suggestion = new Suggestion(queryTerms, type, url, query, @computeRelevancy) - suggestion.autoSelect = true - suggestions.push(suggestion) - onComplete(suggestions) + (string) -> Utils.createSearchUrl string.split /\s+/ + + type = if description? then description else "search" + searchUrl = if custom then url else Settings.get "searchUrl" + query = queryTerms[1..].join " " + + # For custom search engines, we add an auto-selected suggestion. + if custom + title = if description? then query else queryTerms[0] + ": " + query + suggestions.push @mkSuggestion false, queryTerms, type, mkUrl(query), description, @computeRelevancy + suggestions[0].autoSelect = true + suggestions[0].relevancyScore = 1 + queryTerms = queryTerms[1..] + + # For custom search-engine queries, this adds suggestions only if we have a completer. For other queries, + # this adds suggestions for the default search engine (if we have a completer for that). + SearchEngines.complete searchUrl, queryTerms, (newSuggestions = []) => + characterCount = query.length - queryTerms.length + 1 + for suggestion in newSuggestions + suggestions.push @mkSuggestion true, queryTerms, type, mkUrl(suggestion), suggestion, @computeRelevancy, characterCount + + if custom + for suggestion in suggestions + suggestion.reinsertPrefix = "#{keyword} " if suggestion.insertText - computeRelevancy: -> 1 + onComplete suggestions + + mkSuggestion: (insertText, args...) -> + suggestion = new Suggestion args... + suggestion.insertText = insertText + suggestion + + computeRelevancy: (suggestion) -> + suggestion.relevancyScore ? + # We score search-engine completions by word relevancy, but weight the score increasingly as the number of + # characters in the query terms increases. The idea is that, the more the user has had to type, the less + # likely it is that one of the other suggestion types has proven useful, so the more likely it is that + # this suggestion will be useful. + # NOTE(smblott) This will require tweaking. + (Math.min(suggestion.extraRelevancyData, 12)/12) * + RankingUtils.wordRelevancy suggestion.queryTerms, suggestion.title, suggestion.title refresh: -> - @searchEngines = CustomSearchEngineCompleter.getSearchEngines() + @searchEngines = SearchEngineCompleter.getSearchEngines() getSearchEngineMatches: (queryTerms) -> (1 < queryTerms.length and @searchEngines[queryTerms[0]]) or {} @@ -376,23 +385,24 @@ class CustomSearchEngineCompleter # mapping in @searchEnginesMap. @searchEnginesMap: null - # Parse the custom search engines setting and cache it in CustomSearchEngineCompleter.searchEnginesMap. + # Parse the custom search engines setting and cache it in SearchEngineCompleter.searchEnginesMap. @parseSearchEngines: (searchEnginesText) -> - searchEnginesMap = CustomSearchEngineCompleter.searchEnginesMap = {} + searchEnginesMap = SearchEngineCompleter.searchEnginesMap = {} for line in searchEnginesText.split /\n/ tokens = line.trim().split /\s+/ continue if tokens.length < 2 or tokens[0].startsWith('"') or tokens[0].startsWith("#") keywords = tokens[0].split ":" continue unless keywords.length == 2 and not keywords[1] # So, like: [ "w", "" ]. searchEnginesMap[keywords[0]] = + keyword: keywords[0] url: tokens[1] description: tokens[2..].join(" ") # Fetch the search-engine map, building it if necessary. @getSearchEngines: -> - unless CustomSearchEngineCompleter.searchEnginesMap? - CustomSearchEngineCompleter.parseSearchEngines Settings.get "searchEngines" - CustomSearchEngineCompleter.searchEnginesMap + unless SearchEngineCompleter.searchEnginesMap? + SearchEngineCompleter.parseSearchEngines Settings.get "searchEngines" + SearchEngineCompleter.searchEnginesMap # A completer which calls filter() on many completers, aggregates the results, ranks them, and returns the top # 10. Queries from the vomnibar frontend script come through a multi completer. @@ -641,7 +651,6 @@ root.HistoryCompleter = HistoryCompleter root.DomainCompleter = DomainCompleter root.TabCompleter = TabCompleter root.SearchEngineCompleter = SearchEngineCompleter -root.CustomSearchEngineCompleter = CustomSearchEngineCompleter root.HistoryCache = HistoryCache root.RankingUtils = RankingUtils root.RegexpCache = RegexpCache diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee index 6f7db05c..4d2546fc 100644 --- a/background_scripts/main.coffee +++ b/background_scripts/main.coffee @@ -47,13 +47,11 @@ completionSources = history: new HistoryCompleter() domains: new DomainCompleter() tabs: new TabCompleter() - customSearchEngines: new CustomSearchEngineCompleter() searchEngines: new SearchEngineCompleter() completers = omni: new MultiCompleter([ completionSources.searchEngines, - completionSources.customSearchEngines, completionSources.bookmarks, completionSources.history, completionSources.domains]) diff --git a/background_scripts/search_engines.coffee b/background_scripts/search_engines.coffee index e96e2c76..e68cf85d 100644 --- a/background_scripts/search_engines.coffee +++ b/background_scripts/search_engines.coffee @@ -1,4 +1,9 @@ +matchesAnyRegexp = (regexps, string) -> + for re in regexps + return true if re.test string + false + # Each completer implements three functions: # # match: can this completer be used for this search URL? @@ -15,10 +20,7 @@ class Google ] name: "Google" - match: (searchUrl) -> - for re in @regexps - return true if re.test searchUrl - false + match: (searchUrl) -> matchesAnyRegexp @regexps, searchUrl getUrl: (queryTerms) -> "http://suggestqueries.google.com/complete/search?ss_protocol=legace&client=toolbar&q=#{Utils.createSearchQuery queryTerms}" @@ -31,6 +33,26 @@ class Google continue unless suggestion = suggestion.getAttribute "data" suggestion +class Youtube + constructor: -> + @regexps = [ new RegExp "https?://[a-z]+\.youtube\.com/results" ] + + name: "YouTube" + match: (searchUrl) -> matchesAnyRegexp @regexps, searchUrl + + getUrl: (queryTerms) -> + "http://suggestqueries.google.com/complete/search?client=youtube&ds=yt&q=#{Utils.createSearchQuery queryTerms}" + + # Returns a list of suggestions (strings). + parse: (xhr) -> + try + text = xhr.responseText + text = text.replace /^[^(]*\(/, "" + text = text.replace /\)[^\)]*$/, "" + suggestion[0] for suggestion in JSON.parse(text)[1] + catch + [] + # A dummy search engine which is guaranteed to match any search URL, but never produces completions. This # allows the rest of the logic to be written knowing that there will be a search engine match. class DummySearchEngine @@ -41,7 +63,7 @@ class DummySearchEngine getUrl: -> chrome.runtime.getURL "content_scripts/vimium.css" parse: -> [] -completionEngines = [ Google, DummySearchEngine ] +completionEngines = [ Google, Youtube, DummySearchEngine ] SearchEngines = cancel: (searchUrl, callback = null) -> diff --git a/background_scripts/settings.coffee b/background_scripts/settings.coffee index a73a9d5c..a4d95c81 100644 --- a/background_scripts/settings.coffee +++ b/background_scripts/settings.coffee @@ -33,7 +33,7 @@ root.Settings = Settings = root.refreshCompletionKeysAfterMappingSave() searchEngines: (value) -> - root.CustomSearchEngineCompleter.parseSearchEngines value + root.SearchEngineCompleter.parseSearchEngines value exclusionRules: (value) -> root.Exclusions.postUpdateHook value diff --git a/pages/vomnibar.coffee b/pages/vomnibar.coffee index 45a3a7db..c519ce3a 100644 --- a/pages/vomnibar.coffee +++ b/pages/vomnibar.coffee @@ -99,7 +99,7 @@ class VomnibarUI suggestion = @completions[@selection] if suggestion.insertText @previousText ?= @input.value - @input.value = suggestion.title + @input.value = (suggestion.reinsertPrefix ? "") + suggestion.title else if @previousText? @input.value = @previousText |
