aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Blott2015-05-02 16:29:42 +0100
committerStephen Blott2015-05-02 17:24:48 +0100
commit8329f3cbe95e6a39e500aa15e54c6c44fad9cb7e (patch)
tree31367cd8d6d35eb7efec537a9e8a4fb2b2d85237
parent6073d820ff25f824b575a797f160b3204e0e9863 (diff)
downloadvimium-8329f3cbe95e6a39e500aa15e54c6c44fad9cb7e.tar.bz2
Search completion; refactor, add Youtube.
Major refactoring. Unified tratment of custom search engines and general searches.
-rw-r--r--background_scripts/completion.coffee97
-rw-r--r--background_scripts/main.coffee2
-rw-r--r--background_scripts/search_engines.coffee32
-rw-r--r--background_scripts/settings.coffee2
-rw-r--r--pages/vomnibar.coffee2
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