Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1717)

Unified Diff: chrome/browser/history/query_parser.cc

Issue 9316129: Don't strip punctuation inside quotes in history search queries. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: New patch based on chat with mrossetti. Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/history/query_parser.cc
diff --git a/chrome/browser/history/query_parser.cc b/chrome/browser/history/query_parser.cc
index 782c708010cf2b9b8ef0ed7216f6740a95c8b4aa..c1a628e24e5562508ada86d22387788a4768658e 100644
--- a/chrome/browser/history/query_parser.cc
+++ b/chrome/browser/history/query_parser.cc
@@ -11,6 +11,7 @@
#include "base/i18n/case_conversion.h"
#include "base/logging.h"
#include "base/stl_util.h"
+#include "base/string_util.h"
namespace {
@@ -46,7 +47,7 @@ void CoalesceMatchesFrom(size_t index, Snippet::MatchPositions* matches) {
// Sorts the match positions in |matches| by their first index, then coalesces
// any match positions that intersect each other.
-void CoalseAndSortMatchPositions(Snippet::MatchPositions* matches) {
+void CoalesceAndSortMatchPositions(Snippet::MatchPositions* matches) {
std::sort(matches->begin(), matches->end(), &CompareMatchPosition);
// WARNING: we don't use iterator here as CoalesceMatchesFrom may remove
// from matches.
@@ -64,6 +65,17 @@ bool IsQueryQuote(wchar_t ch) {
ch == 0x201e; // double low-9 quotation mark
}
+// Returns true if the character is considered non-breaking when it appears in
+// the middle of a word. This can be used to prevent an URL-like query from
+// being broken into multiple words.
+bool IsNonBreakingSymbol(wchar_t ch) {
+ return ch == '.' ||
+ ch == '-' ||
+ ch == '_' ||
+ ch == '/' ||
+ ch == '~';
+}
+
} // namespace
// Inheritance structure:
@@ -89,6 +101,7 @@ class QueryNodeWord : public QueryNode {
const std::vector<QueryWord>& words,
Snippet::MatchPositions* match_positions) const OVERRIDE;
virtual void AppendWords(std::vector<string16>* words) const OVERRIDE;
+ virtual void Append(const string16& word);
sky 2012/02/08 23:31:28 This isn't part of QueryNode, so move it some wher
Patrick Dubroy 2012/02/09 14:47:00 Whoops, yeah. Done.
private:
string16 word_;
@@ -141,6 +154,10 @@ void QueryNodeWord::AppendWords(std::vector<string16>* words) const {
words->push_back(word_);
}
+void QueryNodeWord::Append(const string16& str) {
+ word_ += str;
+}
+
// A QueryNodeList has a collection of QueryNodes which are deleted in the end.
class QueryNodeList : public QueryNode {
public:
@@ -347,7 +364,7 @@ bool QueryParser::DoesQueryMatch(const string16& text,
// completely punt here.
match_positions->clear();
} else {
- CoalseAndSortMatchPositions(&matches);
+ CoalesceAndSortMatchPositions(&matches);
match_positions->swap(matches);
}
return true;
@@ -365,27 +382,42 @@ bool QueryParser::ParseQueryImpl(const string16& query, QueryNodeList* root) {
query_stack.push_back(root);
bool in_quotes = false; // whether we're currently in a quoted phrase
+ QueryNodeWord* current_word = NULL;
while (iter.Advance()) {
// Just found a span between 'prev' (inclusive) and 'pos' (exclusive). It
- // is not necessarily a word, but could also be a sequence of punctuation
- // or whitespace.
- if (iter.IsWord()) {
- QueryNodeWord* word_node = new QueryNodeWord(iter.GetString());
- if (in_quotes)
- word_node->set_literal(true);
- query_stack.back()->AddChild(word_node);
- } else { // Punctuation.
- if (IsQueryQuote(query[iter.prev()])) {
- if (!in_quotes) {
- QueryNodeList* quotes_node = new QueryNodePhrase;
- query_stack.back()->AddChild(quotes_node);
- query_stack.push_back(quotes_node);
- in_quotes = true;
- } else {
- query_stack.pop_back(); // Stop adding to the quoted phrase.
- in_quotes = false;
- }
+ // is not necessarily a word, it could also be a punctuation or whitespace
+ // character. Punctuation is preserved inside quotes, and otherwise removed
+ // except if it is a non-breaking character in the middle of a word.
+
+ wchar_t last_char = query[iter.prev()];
+ if (IsQueryQuote(last_char)) {
+ if (!in_quotes) {
+ QueryNodeList* quotes_node = new QueryNodePhrase;
+ query_stack.back()->AddChild(quotes_node);
+ query_stack.push_back(quotes_node);
+ in_quotes = true;
+ } else {
+ query_stack.pop_back(); // Stop adding to the quoted phrase.
+ in_quotes = false;
+ }
+ current_word = NULL;
+ } else if (iter.IsWord() || (in_quotes && !IsWhitespace(last_char))) {
+ // Append to the current word if the new token is a word or a non-
+ // whitespace character inside quotes.
+ if (current_word) {
+ current_word->Append(iter.GetString());
+ } else {
+ current_word = new QueryNodeWord(iter.GetString());
+ current_word->set_literal(in_quotes);
+ query_stack.back()->AddChild(current_word);
}
+ } else if (current_word != NULL) {
+ // Allow non-breaking symbols inside a word.
+ // Any other punctuation or whitespace character ends the current word.
+ if (IsNonBreakingSymbol(last_char))
+ current_word->Append(iter.GetString());
+ else
+ current_word = NULL;
}
}
« no previous file with comments | « no previous file | chrome/browser/history/query_parser_unittest.cc » ('j') | chrome/browser/history/query_parser_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698