diff options
| author | mike-work | 2014-05-07 23:57:56 +0100 | 
|---|---|---|
| committer | mike-work | 2014-05-29 02:42:51 +0100 | 
| commit | a18ad484f2fdc0019c15d94405c915f8bfe6d76f (patch) | |
| tree | 3a8667096504d09b85ac0cd1cf4135763c95e375 | |
| parent | 1aa7ba3a5810742d14edfb738120b70f4a0f7619 (diff) | |
| download | vimium-a18ad484f2fdc0019c15d94405c915f8bfe6d76f.tar.bz2 | |
Adding in search engines feature to fix #1009
| -rw-r--r-- | background_scripts/completion.coffee | 22 | ||||
| -rw-r--r-- | background_scripts/main.coffee | 2 | ||||
| -rw-r--r-- | background_scripts/settings.coffee | 21 | ||||
| -rw-r--r-- | pages/options.coffee | 4 | ||||
| -rw-r--r-- | pages/options.html | 27 | ||||
| -rw-r--r-- | tests/unit_tests/completion_test.coffee | 14 | ||||
| -rw-r--r-- | tests/unit_tests/settings_test.coffee | 9 | 
7 files changed, 96 insertions, 3 deletions
| diff --git a/background_scripts/completion.coffee b/background_scripts/completion.coffee index beb7003a..2868308a 100644 --- a/background_scripts/completion.coffee +++ b/background_scripts/completion.coffee @@ -248,6 +248,27 @@ class TabCompleter    computeRelevancy: (suggestion) ->      RankingUtils.wordRelevancy(suggestion.queryTerms, suggestion.url, suggestion.title) +# A completer which will return your search engines +class SearchEngineCompleter +  searchEngines: {} + +  filter: (queryTerms, onComplete) -> +    searchEngineMatch = this.getSearchEngineMatches(queryTerms[0]) +    suggestions = [] +    if searchEngineMatch +      searchEngineMatch = searchEngineMatch.replace(/%s/g, queryTerms[1..].join(" ")) +      suggestion = new Suggestion(queryTerms, "search", searchEngineMatch, queryTerms[0] + ": " + queryTerms[1..].join(" "), @computeRelevancy) +      suggestions.push(suggestion) +    onComplete(suggestions) + +  computeRelevancy: -> 1 + +  refresh: -> +    this.searchEngines = root.Settings.getSearchEngines() + +  getSearchEngineMatches: (queryTerm) -> +    this.searchEngines[queryTerm] +  # 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.  class MultiCompleter @@ -436,6 +457,7 @@ root.MultiCompleter = MultiCompleter  root.HistoryCompleter = HistoryCompleter  root.DomainCompleter = DomainCompleter  root.TabCompleter = TabCompleter +root.SearchEngineCompleter = SearchEngineCompleter  root.HistoryCache = HistoryCache  root.RankingUtils = RankingUtils  root.RegexpCache = RegexpCache diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee index b2b4669c..00b96643 100644 --- a/background_scripts/main.coffee +++ b/background_scripts/main.coffee @@ -24,9 +24,11 @@ completionSources =    history: new HistoryCompleter()    domains: new DomainCompleter()    tabs: new TabCompleter() +  seachEngines: new SearchEngineCompleter()  completers =    omni: new MultiCompleter([ +    completionSources.seachEngines,      completionSources.bookmarks,      completionSources.history,      completionSources.domains]) diff --git a/background_scripts/settings.coffee b/background_scripts/settings.coffee index c26da5a4..175f3262 100644 --- a/background_scripts/settings.coffee +++ b/background_scripts/settings.coffee @@ -32,10 +32,28 @@ root.Settings = Settings =        root.Commands.parseCustomKeyMappings value        root.refreshCompletionKeysAfterMappingSave() +    searchEngines: (value) -> +      root.Settings.parseSearchEngines value +    # postUpdateHooks convenience wrapper    performPostUpdateHook: (key, value) ->      @postUpdateHooks[key] value if @postUpdateHooks[key] +  # Here we have our functions that parse the search engines +  # this is a map that we use to store our search engines for use. +  searchEnginesMap: {} + +  # this parses the search engines settings and clears the old searchEngines and sets the new one +  parseSearchEngines: (searchEnginesText) -> +    @searchEnginesMap = {} +    # find the split pairs by first splitting by line then splitting on the first `: ` +    split_pairs = ( pair.split( /: (.+)/, 2) for pair in searchEnginesText.split( /\n/ ) when pair[0] != "#" ) +    @searchEnginesMap[a[0]] = a[1] for a in split_pairs +    @searchEnginesMap +  getSearchEngines: -> +    this.parseSearchEngines(@get("searchEngines") || "") if Object.keys(@searchEnginesMap).length == 0 +    @searchEnginesMap +    # options.coffee and options.html only handle booleans and strings; therefore all defaults must be booleans    # or strings    defaults: @@ -78,9 +96,12 @@ root.Settings = Settings =      nextPatterns: "next,more,>,\u2192,\xbb,\u226b,>>"      # default/fall back search engine      searchUrl: "http://www.google.com/search?q=" +    # put in an example search engine +    searchEngines: "w: http://www.wikipedia.org/w/index.php?title=Special:Search&search=%s"      settingsVersion: Utils.getCurrentVersion() +  # We use settingsVersion to coordinate any necessary schema changes.  if Utils.compareVersions("1.42", Settings.get("settingsVersion")) != -1    Settings.set("scrollStepSize", parseFloat Settings.get("scrollStepSize")) diff --git a/pages/options.coffee b/pages/options.coffee index 34696f68..d73d8f15 100644 --- a/pages/options.coffee +++ b/pages/options.coffee @@ -4,9 +4,9 @@ bgSettings = chrome.extension.getBackgroundPage().Settings  editableFields = [ "scrollStepSize", "excludedUrls", "linkHintCharacters", "linkHintNumbers",    "userDefinedLinkHintCss", "keyMappings", "filterLinkHints", "previousPatterns", -  "nextPatterns", "hideHud", "regexFindMode", "searchUrl"] +  "nextPatterns", "hideHud", "regexFindMode", "searchUrl", "searchEngines"] -canBeEmptyFields = ["excludedUrls", "keyMappings", "userDefinedLinkHintCss"] +canBeEmptyFields = ["excludedUrls", "keyMappings", "userDefinedLinkHintCss", "searchEngines"]  document.addEventListener "DOMContentLoaded", ->    populateOptions() diff --git a/pages/options.html b/pages/options.html index 8c7c007a..5450a774 100644 --- a/pages/options.html +++ b/pages/options.html @@ -122,6 +122,10 @@          width: 100%;          min-height: 135px;        } +      textarea#searchEngines { +        width: 100%; +        min-height: 135px; +      }        input#previousPatterns, input#nextPatterns {          width: 100%;        } @@ -330,12 +334,33 @@ unmapAll              <td verticalAlign="top">                  <div class="help">                    <div class="example"> -                    Set which search engine is used when searching from the Vomnibar (examples: "http://duckduckgo.com/?q=", "http://www.google.com/search?q="). +                    Set which search engine is used when searching from the Vomnibar (examples: "http://duckduckgo.com/?q=").                    </div>                  </div>                  <input id="searchUrl" type="text" />              </td>            </tr> +          <tr> +            <td class="caption">Search Engines</td> +            <td verticalAlign="top"> +                <div class="help"> +                  <div class="example"> +                      Allow customised search engines the format is `token: http://address.com/q?=%s` +                      <br/> +                      token must not contain a colon. +                      <br/> +                      comments are allowed and start with '#' +                      <br/> +                      all `%s` will be replaced with the query string +                      <br/> +                      for a list of default and extra search engines please see <a href="https://gist.github.com/mhauserr/1918ecd63393a9cb23c4">here</a> +                      <br/> +                      to subsequently search for something just type token follewed by your search terms +                  </div> +                </div> +                <textarea id="searchEngines"></textarea> +            </td> +          </tr>          </tbody>        </table> diff --git a/tests/unit_tests/completion_test.coffee b/tests/unit_tests/completion_test.coffee index fb267f63..43ecb49d 100644 --- a/tests/unit_tests/completion_test.coffee +++ b/tests/unit_tests/completion_test.coffee @@ -209,6 +209,20 @@ context "tab completer",      assert.arrayEqual ["tab2.com"], results.map (tab) -> tab.url      assert.arrayEqual [2], results.map (tab) -> tab.tabId +context "search engines", +  setup -> +    searchEngines = "foo: bar?q=%s\n# comment\nbaz: qux?q=%s" +    Settings.set 'searchEngines', searchEngines +    @completer = new SearchEngineCompleter() +    # note, I couldn't just call @completer.refresh() here as I couldn't set root.Settings without errors +    # workaround is below, would be good for someone that understands the testing system better than me to improve +    @completer.searchEngines = Settings.getSearchEngines() + +  should "return search engine suggestion", -> +    results = filterCompleter(@completer, ["foo", "hello"]) +    assert.arrayEqual ["bar?q=hello"], results.map (result) -> result.url +    assert.arrayEqual ["foo: hello"], results.map (result) -> result.title +  context "suggestions",    should "escape html in page titles", ->      suggestion = new Suggestion(["queryterm"], "tab", "url", "title <span>", returns(1)) diff --git a/tests/unit_tests/settings_test.coffee b/tests/unit_tests/settings_test.coffee index 25bb3628..1283497c 100644 --- a/tests/unit_tests/settings_test.coffee +++ b/tests/unit_tests/settings_test.coffee @@ -70,5 +70,14 @@ context "settings",      chrome.storage.sync.set { scrollStepSize: JSON.stringify(message) }      assert.equal message, Sync.message +  should "set search engines, retrieve them correctly and check that it has been parsed correctly", -> +    searchEngines = "foo: bar?q=%s\n# comment\nbaz: qux?q=%s" +    parsedSearchEngines = {"foo": "bar?q=%s", "baz": "qux?q=%s"} +    Settings.set 'searchEngines', searchEngines +    assert.equal(searchEngines, Settings.get('searchEngines')) +    result = Settings.getSearchEngines() +    assert.isTrue(parsedSearchEngines["foo"] == result["foo"] && +      parsedSearchEngines["baz"] == result["baz"] && Object.keys(result).length == 2) +    should "sync a key which is not a known setting (without crashing)", ->      chrome.storage.sync.set { notASetting: JSON.stringify("notAUsefullValue") } | 
