diff options
Diffstat (limited to 'cache/query.go')
-rw-r--r-- | cache/query.go | 51 |
1 files changed, 41 insertions, 10 deletions
diff --git a/cache/query.go b/cache/query.go index 8b044540..3976aede 100644 --- a/cache/query.go +++ b/cache/query.go @@ -3,6 +3,7 @@ package cache import ( "fmt" "strings" + "unicode" ) type Query struct { @@ -16,10 +17,8 @@ type Query struct { // Ex: "status:open author:descartes sort:edit-asc" // // Supported filter fields and syntax are described in docs/queries.md -// -// Todo: write a complete doc func ParseQuery(query string) (*Query, error) { - fields := strings.Fields(query) + fields := splitQuery(query) result := &Query{ OrderBy: OrderByCreation, @@ -34,24 +33,27 @@ func ParseQuery(query string) (*Query, error) { return nil, fmt.Errorf("can't parse \"%s\"", field) } - switch split[0] { + qualifierName := split[0] + qualifierQuery := removeQuote(split[1]) + + switch qualifierName { case "status": - f, err := StatusFilter(split[1]) + f, err := StatusFilter(qualifierQuery) if err != nil { return nil, err } result.Status = append(result.Status, f) case "author": - f := AuthorFilter(split[1]) + f := AuthorFilter(qualifierQuery) result.Author = append(result.Author, f) case "label": - f := LabelFilter(split[1]) + f := LabelFilter(qualifierQuery) result.Label = append(result.Label, f) case "no": - err := result.parseNoFilter(split[1]) + err := result.parseNoFilter(qualifierQuery) if err != nil { return nil, err } @@ -61,7 +63,7 @@ func ParseQuery(query string) (*Query, error) { return nil, fmt.Errorf("multiple sorting") } - err := result.parseSorting(split[1]) + err := result.parseSorting(qualifierQuery) if err != nil { return nil, err } @@ -69,13 +71,42 @@ func ParseQuery(query string) (*Query, error) { sortingDone = true default: - return nil, fmt.Errorf("unknow query field %s", split[0]) + return nil, fmt.Errorf("unknow qualifier name %s", qualifierName) } } return result, nil } +func splitQuery(query string) []string { + lastQuote := rune(0) + f := func(c rune) bool { + switch { + case c == lastQuote: + lastQuote = rune(0) + return false + case lastQuote != rune(0): + return false + case unicode.In(c, unicode.Quotation_Mark): + lastQuote = c + return false + default: + return unicode.IsSpace(c) + } + } + + return strings.FieldsFunc(query, f) +} + +func removeQuote(field string) string { + if len(field) >= 2 { + if field[0] == '"' && field[len(field)-1] == '"' { + return field[1 : len(field)-1] + } + } + return field +} + func (q *Query) parseNoFilter(query string) error { switch query { case "label": |