mirror of https://github.com/perkeep/perkeep.git
search: add is:image operator
Change-Id: Iba693538b4e7b3d0cf08d5e8601d3b5819000ca1
This commit is contained in:
parent
12f87787fe
commit
f27c12ee6a
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue