internal/frontend: split searchQueryAndMode

searchQueryAndMode is split into searchQuery and searchMode.

searchQuery now returns the raw query string, so that user can see the
query that they typed in.

For golang/go#44142

Change-Id: I696b8f65f732417c43a5290b43ba1887b0c1bc06
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/348112
Trust: Julie Qiu <julie@golang.org>
Run-TryBot: Julie Qiu <julie@golang.org>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/internal/frontend/search.go b/internal/frontend/search.go
index 6a43bba..de14a6c 100644
--- a/internal/frontend/search.go
+++ b/internal/frontend/search.go
@@ -43,7 +43,8 @@
 	}
 
 	ctx := r.Context()
-	query, searchMode := searchQueryAndMode(r)
+	query := searchQuery(r)
+	mode := searchMode(r)
 	if !utf8.ValidString(query) {
 		return &serverError{status: http.StatusBadRequest}
 	}
@@ -85,12 +86,12 @@
 		return nil
 	}
 
-	page, err := fetchSearchPage(ctx, db, query, pageParams, searchMode == searchModeSymbol)
+	page, err := fetchSearchPage(ctx, db, query, pageParams, mode == searchModeSymbol)
 	if err != nil {
 		return fmt.Errorf("fetchSearchPage(ctx, db, %q): %v", query, err)
 	}
 	page.basePage = s.newBasePage(r, fmt.Sprintf("%s - Search Results", query))
-	page.SearchMode = searchMode
+	page.SearchMode = mode
 	if s.shouldServeJSON(r) {
 		return s.serveJSONPage(w, r, page)
 	}
@@ -179,6 +180,7 @@
 	if experiment.IsActive(ctx, internal.ExperimentSearchGrouping) {
 		// When using search grouping, do pageless search: always start from the beginning.
 		offset = 0
+		query = strings.TrimLeft(query, symbolSearchFilter)
 	}
 	dbresults, err := db.Search(ctx, query, postgres.SearchOptions{
 		MaxResults:     pageParams.limit,
@@ -292,28 +294,31 @@
 	return fmt.Sprintf("/%s", requestedPath)
 }
 
-// searchQueryAndMode extracts a search query from the request. It also reports
-// whether the search performed should be in symbolSearch mode.
-// See TestSearchQuery for examples.
-func searchQueryAndMode(r *http.Request) (q, searchMode string) {
-	q = strings.TrimSpace(r.FormValue("q"))
+// searchMode reports whether the search performed should be in package or
+// symbol search mode.
+func searchMode(r *http.Request) string {
 	if !experiment.IsActive(r.Context(), internal.ExperimentSymbolSearch) {
-		return q, searchModePackage
+		return searchModePackage
 	}
+	q := searchQuery(r)
 	if strings.HasPrefix(q, symbolSearchFilter) {
-		return strings.TrimPrefix(q, symbolSearchFilter), searchModeSymbol
+		return searchModeSymbol
 	}
 	mode := strings.TrimSpace(r.FormValue("m"))
 	if mode == searchModePackage {
-		return q, searchModePackage
+		return searchModePackage
 	}
 	if mode == searchModeSymbol {
-		return q, searchModeSymbol
+		return searchModeSymbol
 	}
 	if shouldDefaultToSymbolSearch(q) {
-		return q, searchModeSymbol
+		return searchModeSymbol
 	}
-	return q, searchModePackage
+	return searchModePackage
+}
+
+func searchQuery(r *http.Request) string {
+	return strings.TrimSpace(r.FormValue("q"))
 }
 
 // shouldDefaultToSymbolSearch reports whether the symbol search mode should
diff --git a/internal/frontend/search_test.go b/internal/frontend/search_test.go
index e4d8609..83ad866 100644
--- a/internal/frontend/search_test.go
+++ b/internal/frontend/search_test.go
@@ -24,34 +24,30 @@
 
 func TestSearchQueryAndMode(t *testing.T) {
 	for _, test := range []struct {
-		name, m, q, wantQuery, wantSearchMode string
+		name, m, q, wantSearchMode string
 	}{
 		{
 			name:           "symbol: prefix in symbol mode",
 			m:              searchModeSymbol,
 			q:              "#foo",
-			wantQuery:      "foo",
 			wantSearchMode: searchModeSymbol,
 		},
 		{
 			name:           "symbol: prefix in package mode",
 			m:              searchModeSymbol,
 			q:              "#foo",
-			wantQuery:      "foo",
 			wantSearchMode: searchModeSymbol,
 		},
 		{
 			name:           "search in package mode",
 			m:              searchModePackage,
 			q:              "foo",
-			wantQuery:      "foo",
 			wantSearchMode: searchModePackage,
 		},
 		{
 			name:           "search in symbol mode",
 			m:              searchModeSymbol,
 			q:              "foo",
-			wantQuery:      "foo",
 			wantSearchMode: searchModeSymbol,
 		},
 	} {
@@ -59,10 +55,10 @@
 			u := fmt.Sprintf("/search?q=%s&m=%s", test.q, test.m)
 			r := httptest.NewRequest("GET", u, nil)
 			r = r.WithContext(experiment.NewContext(r.Context(), internal.ExperimentSymbolSearch))
-			gotQuery, gotSearchMode := searchQueryAndMode(r)
-			if gotQuery != test.wantQuery || gotSearchMode != test.wantSearchMode {
-				t.Errorf("searchQueryAndMode(%q) = %q, %q; want = %q, %q", u, gotQuery, gotSearchMode,
-					test.wantQuery, test.wantSearchMode)
+			gotSearchMode := searchMode(r)
+			if gotSearchMode != test.wantSearchMode {
+				t.Errorf("searchQueryAndMode(%q) = %q; want = %q",
+					u, gotSearchMode, test.wantSearchMode)
 			}
 		})
 	}
diff --git a/internal/frontend/server.go b/internal/frontend/server.go
index b53f554..c94edeb 100644
--- a/internal/frontend/server.go
+++ b/internal/frontend/server.go
@@ -315,7 +315,7 @@
 
 // newBasePage returns a base page for the given request and title.
 func (s *Server) newBasePage(r *http.Request, title string) basePage {
-	q, _ := searchQueryAndMode(r)
+	q := searchQuery(r)
 	return basePage{
 		HTMLTitle:          title,
 		Query:              q,