aboutsummaryrefslogtreecommitdiffstats
path: root/background_scripts
diff options
context:
space:
mode:
authorJez Ng2012-11-10 01:29:42 -0800
committerJez Ng2012-11-10 01:29:42 -0800
commit386a3cf6c61f225f238f7b67c8b9405986467c33 (patch)
treea4232c0b3eb9bbed8f2a2678037d49c2bb2c360a /background_scripts
parent8b09b8524ff7dedf4cd2e8448522920beb9c68f5 (diff)
parent7497b56d3acba5c8750cca5b000a428d099e66b3 (diff)
downloadvimium-386a3cf6c61f225f238f7b67c8b9405986467c33.tar.bz2
Merge pull request #704 from smblott-github/relevancy
Highlight all matches in a vomnibar suggestion, not just the first.
Diffstat (limited to 'background_scripts')
-rw-r--r--background_scripts/completion.coffee45
1 files changed, 38 insertions, 7 deletions
diff --git a/background_scripts/completion.coffee b/background_scripts/completion.coffee
index e959d358..25f76c1e 100644
--- a/background_scripts/completion.coffee
+++ b/background_scripts/completion.coffee
@@ -46,12 +46,33 @@ class Suggestion
url = url.substring(url, url.length - 1) if url[url.length - 1] == "/"
url
+ # Push the ranges within `string` which match `term` onto `ranges`.
+ pushMatchingRanges: (string,term,ranges) ->
+ textPosition = 0
+ # Split `string` into a (flat) list of pairs:
+ # - for i=0,2,4,6,...
+ # - splits[i] is unmatched text
+ # - splits[i+1] is the following matched text (matching `term`)
+ # (except for the final element, for which there is no following matched text).
+ # Example:
+ # - string = "Abacab"
+ # - term = "a"
+ # - splits = [ "", "A", "b", "a", "c", "a", b" ]
+ # UM M UM M UM M UM (M=Matched, UM=Unmatched)
+ splits = string.split(RegexpCache.get(term, "(", ")"))
+ for index in [0..splits.length-2] by 2
+ unmatchedText = splits[index]
+ matchedText = splits[index+1]
+ # Add the indices spanning `matchedText` to `ranges`.
+ textPosition += unmatchedText.length
+ ranges.push([textPosition, textPosition + matchedText.length])
+ textPosition += matchedText.length
+
# Wraps each occurence of the query terms in the given string in a <span>.
highlightTerms: (string) ->
ranges = []
for term in @queryTerms
- i = string.search(RegexpCache.get(term))
- ranges.push([i, i + term.length]) if i >= 0
+ @pushMatchingRanges string, term, ranges
return string if ranges.length == 0
@@ -307,12 +328,21 @@ RegexpCache =
clear: -> @cache = {}
- get: (string) ->
+ # Get rexexp for `string` from cache, creating it if necessary.
+ # Regexp meta-characters in `string` are escaped.
+ # Regexp is wrapped in `prefix`/`suffix`, which may contain meta-characters (these are not escaped).
+ # With their default values, `prefix` and `suffix` have no effect.
+ # Example:
+ # - string="go", prefix="\b", suffix=""
+ # - this returns regexp matching "google", but not "agog" (the "go" must occur at the start of a word)
+ # TODO: `prefix` and `suffix` might be useful in richer word-relevancy scoring.
+ get: (string, prefix="", suffix="") ->
@init() unless @initialized
- @cache[string] ||= @escapeRegexp(string)
-
- # Creates a Regexp from the given string, with all special Regexp characters escaped.
- escapeRegexp: (string) -> new RegExp(string.replace(@escapeRegExp, "\\$&"), "i")
+ regexpString = string.replace(@escapeRegExp, "\\$&")
+ # Avoid cost of constructing new strings if prefix/suffix are empty (which is expected to be a common case).
+ regexpString = prefix + regexpString if prefix
+ regexpString = regexpString + suffix if suffix
+ @cache[regexpString] ||= new RegExp(regexpString, "i")
# Provides cached access to Chrome's history. As the user browses to new pages, we add those pages to this
# history cache.
@@ -382,3 +412,4 @@ root.DomainCompleter = DomainCompleter
root.TabCompleter = TabCompleter
root.HistoryCache = HistoryCache
root.RankingUtils = RankingUtils
+root.RegexpCache = RegexpCache