diff options
-rw-r--r-- | cache/query.go | 51 | ||||
-rw-r--r-- | cache/query_test.go | 8 | ||||
-rw-r--r-- | commands/ls.go | 1 |
3 files changed, 47 insertions, 13 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": diff --git a/cache/query_test.go b/cache/query_test.go index 24d80035..646a6d73 100644 --- a/cache/query_test.go +++ b/cache/query_test.go @@ -16,9 +16,13 @@ func TestQueryParse(t *testing.T) { {"status:unknown", false}, {"author:rene", true}, - // Todo: fix parsing - // {"author:\"Rene Descartes\"", true}, + {"author:\"René Descartes\"", true}, + {"label:hello", true}, + {"label:\"Good first issue\"", true}, + + {"sort:edit", true}, + {"sort:unknown", false}, } for _, test := range tests { diff --git a/commands/ls.go b/commands/ls.go index 339f1469..79124f7f 100644 --- a/commands/ls.go +++ b/commands/ls.go @@ -18,7 +18,6 @@ func runLsBug(cmd *cobra.Command, args []string) error { var query *cache.Query if len(args) >= 1 { - fmt.Println("Query", args[0]) query, err = cache.ParseQuery(args[0]) if err != nil { |