From f27c12ee6a6143ee0d6634368b5dfec706c5da82 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sun, 22 Dec 2013 15:11:31 -0800 Subject: [PATCH] search: add is:image operator Change-Id: Iba693538b4e7b3d0cf08d5e8601d3b5819000ca1 --- pkg/search/expr.go | 67 ++++++++++++++++++++++++++++++++--------- pkg/search/expr_test.go | 29 +++++++++++++----- 2 files changed, 73 insertions(+), 23 deletions(-) diff --git a/pkg/search/expr.go b/pkg/search/expr.go index 6e580f416..53986e42f 100644 --- a/pkg/search/expr.go +++ b/pkg/search/expr.go @@ -17,7 +17,7 @@ limitations under the License. package search import ( - "errors" + "log" "regexp" "strings" ) @@ -29,23 +29,60 @@ var tagExpr = regexp.MustCompile(`^tag:(\w+)$`) // Constraint field will always be set. The Limit and Sort may also be // set. func parseExpression(exp string) (*SearchQuery, error) { - q := func(c Constraint) (*SearchQuery, error) { - return &SearchQuery{Constraint: &c}, nil + base := &Constraint{ + Permanode: &PermanodeConstraint{ + SkipHidden: true, + }, } + sq := &SearchQuery{ + Constraint: base, + } + exp = strings.TrimSpace(exp) if exp == "" { - return q(Constraint{ - Permanode: &PermanodeConstraint{ - SkipHidden: true, - }}) + return sq, nil } - if m := tagExpr.FindStringSubmatch(exp); m != nil { - return q(Constraint{ - Permanode: &PermanodeConstraint{ - Attr: "tag", - SkipHidden: true, - Value: m[1], - }}) + + and := func(c *Constraint) { + old := sq.Constraint + sq.Constraint = &Constraint{ + Logical: &LogicalConstraint{ + Op: "and", + A: old, + B: c, + }, + } } - return nil, errors.New("unknown expression") + + words := strings.Fields(exp) + for _, word := range words { + if m := tagExpr.FindStringSubmatch(word); m != nil { + and(&Constraint{ + Permanode: &PermanodeConstraint{ + Attr: "tag", + SkipHidden: true, + Value: m[1], + }, + }) + continue + } + if word == "is:image" { + and(&Constraint{ + Permanode: &PermanodeConstraint{ + Attr: "camliContent", + ValueInSet: &Constraint{ + File: &FileConstraint{ + IsImage: true, + }, + }, + }, + }) + continue + } + log.Printf("Unknown search expression word %q", word) + // TODO: finish. better tokenization. non-operator tokens + // are text searches, etc. + } + + return sq, nil } diff --git a/pkg/search/expr_test.go b/pkg/search/expr_test.go index 7bfc4b09a..4dbc37433 100644 --- a/pkg/search/expr_test.go +++ b/pkg/search/expr_test.go @@ -45,19 +45,32 @@ var parseExprTests = []struct { in: "tag:funny", want: &SearchQuery{ Constraint: &Constraint{ - Permanode: &PermanodeConstraint{ - Attr: "tag", - Value: "funny", - SkipHidden: true, + Logical: &LogicalConstraint{ + Op: "and", + A: &Constraint{ + Permanode: &PermanodeConstraint{ + SkipHidden: true, + }, + }, + B: &Constraint{ + Permanode: &PermanodeConstraint{ + Attr: "tag", + Value: "funny", + SkipHidden: true, + }, + }, }, }, }, }, + // TODO: at least 'x' will go away eventually. - { - inList: []string{"x", "bogus:operator"}, - errContains: "unknown expression", - }, + /* + { + inList: []string{"x", "bogus:operator"}, + errContains: "unknown expression", + }, + */ } func TestParseExpression(t *testing.T) {