mirror of
https://gitea.com/jolheiser/sip
synced 2024-11-22 19:51:58 +01:00
Add qualifier module (#10)
Add qualify module Signed-off-by: jolheiser <john.olheiser@gmail.com> Co-authored-by: jolheiser <john.olheiser@gmail.com> Reviewed-on: https://gitea.com/jolheiser/sip/pulls/10
This commit is contained in:
parent
222dcf402b
commit
4490cc9888
83
modules/qualify/qualify.go
Normal file
83
modules/qualify/qualify.go
Normal file
@ -0,0 +1,83 @@
|
||||
package qualify
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Query map[string]Filter
|
||||
|
||||
type Filter []string
|
||||
|
||||
func (q Query) Query() string {
|
||||
if query, ok := q["query"]; ok {
|
||||
return strings.Join(query, " ")
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (f Filter) Last() string {
|
||||
return f[len(f)-1]
|
||||
}
|
||||
|
||||
func Parse(text string, qualifiers ...string) Query {
|
||||
queries := make(map[string]Filter)
|
||||
|
||||
for _, field := range fields(text) {
|
||||
var key, value string
|
||||
if k, v, ok := qualified(field, qualifiers...); ok {
|
||||
key = k
|
||||
value = trim(v)
|
||||
} else {
|
||||
key = "query"
|
||||
value = trim(field)
|
||||
}
|
||||
|
||||
if queries[key] == nil {
|
||||
queries[key] = make([]string, 0)
|
||||
}
|
||||
queries[key] = append(queries[key], value)
|
||||
}
|
||||
|
||||
return queries
|
||||
}
|
||||
|
||||
func qualified(text string, qualifiers ...string) (string, string, bool) {
|
||||
if len(qualifiers) == 0 && strings.Contains(text, ":") {
|
||||
kv := strings.SplitN(text, ":", 2)
|
||||
return kv[0], kv[1], true
|
||||
}
|
||||
|
||||
for _, qualifier := range qualifiers {
|
||||
if strings.HasPrefix(text, qualifier+":") {
|
||||
return text[:len(qualifier)], text[len(qualifier)+1:], true
|
||||
}
|
||||
}
|
||||
return "", "", false
|
||||
}
|
||||
|
||||
func fields(text string) []string {
|
||||
var f []string
|
||||
|
||||
var quotes bool
|
||||
var last int
|
||||
for idx, char := range text {
|
||||
if char == '"' {
|
||||
quotes = !quotes
|
||||
continue
|
||||
}
|
||||
|
||||
if char == ' ' {
|
||||
if quotes {
|
||||
continue
|
||||
}
|
||||
f = append(f, text[last:idx])
|
||||
last = idx + 1
|
||||
}
|
||||
}
|
||||
f = append(f, strings.TrimSpace(text[last:]))
|
||||
return f
|
||||
}
|
||||
|
||||
func trim(text string) string {
|
||||
return strings.TrimPrefix(strings.TrimSuffix(strings.TrimSpace(text), `"`), `"`)
|
||||
}
|
49
modules/qualify/qualify_test.go
Normal file
49
modules/qualify/qualify_test.go
Normal file
@ -0,0 +1,49 @@
|
||||
package qualify
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
tt := []struct {
|
||||
Query string
|
||||
Result string
|
||||
Qualifiers []string
|
||||
}{
|
||||
{"test", "query->test", nil},
|
||||
{`"test"`, "query->test", nil},
|
||||
{"author:jolheiser", "author->jolheiser", nil},
|
||||
{`"this is a test" author:"jolheiser"`, "query->this is a test,author->jolheiser", nil},
|
||||
{`"this is" "a test" query`, "query->this is|a test|query", nil},
|
||||
{`label:"a bug" label:"a" label:"bug"`, "label->a bug|a|bug", nil},
|
||||
{`author:"jolheiser""`, `author->jolheiser"`, nil},
|
||||
{`author:""jolheiser""`, `author->"jolheiser"`, nil},
|
||||
{"test:testing", "query->test:testing", []string{"label"}},
|
||||
}
|
||||
|
||||
for idx, tc := range tt {
|
||||
t.Run(strconv.Itoa(idx+1), func(t *testing.T) {
|
||||
parsed := result(Parse(tc.Query, tc.Qualifiers...))
|
||||
if parsed != tc.Result {
|
||||
t.Logf("\nwant: %s\n got: %s", tc.Result, parsed)
|
||||
t.Fail()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func result(parsed Query) string {
|
||||
res := make([]string, 0, len(parsed))
|
||||
for key, values := range parsed {
|
||||
res = append(res, fmt.Sprintf("%s->%s", key, strings.Join(values, "|")))
|
||||
}
|
||||
return strings.Join(res, ",")
|
||||
}
|
@ -2,6 +2,7 @@ package sdk
|
||||
|
||||
import (
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"gitea.com/jolheiser/sip/modules/qualify"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -87,34 +88,34 @@ func (f *IssueFilter) Match(issue *gitea.Issue) bool {
|
||||
|
||||
func NewIssueFilter(query string) *IssueFilter {
|
||||
filter := &IssueFilter{}
|
||||
for _, q := range strings.Split(query, " ") {
|
||||
kv := strings.Split(q, ":")
|
||||
if len(kv) == 2 {
|
||||
kv[0] = strings.ToLower(kv[0])
|
||||
kv[1] = strings.ToLower(kv[1])
|
||||
switch kv[0] {
|
||||
case "is":
|
||||
switch kv[1] {
|
||||
case "open", "opened":
|
||||
filter.State = Open
|
||||
case "close", "closed":
|
||||
filter.State = Closed
|
||||
case "merge", "merged":
|
||||
filter.State = Merged
|
||||
default:
|
||||
filter.State = None
|
||||
}
|
||||
case "author":
|
||||
filter.Author = kv[1]
|
||||
case "label":
|
||||
filter.Labels = append(filter.Labels, kv[1])
|
||||
case "milestone":
|
||||
filter.Milestone = kv[1]
|
||||
}
|
||||
continue
|
||||
filters := qualify.Parse(query, "is", "author", "label", "milestone")
|
||||
|
||||
if state, ok := filters["is"]; ok {
|
||||
switch state.Last() {
|
||||
case "open", "opened":
|
||||
filter.State = Open
|
||||
case "close", "closed":
|
||||
filter.State = Closed
|
||||
case "merge", "merged":
|
||||
filter.State = Merged
|
||||
default:
|
||||
filter.State = None
|
||||
}
|
||||
filter.Query += " " + q
|
||||
}
|
||||
filter.Query = strings.TrimSpace(filter.Query)
|
||||
|
||||
if author, ok := filters["author"]; ok {
|
||||
filter.Author = author.Last()
|
||||
}
|
||||
|
||||
if label, ok := filters["label"]; ok {
|
||||
filter.Labels = append(filter.Labels, label...)
|
||||
}
|
||||
|
||||
if milestone, ok := filters["milestone"]; ok {
|
||||
filter.Milestone = milestone.Last()
|
||||
}
|
||||
|
||||
filter.Query = filters.Query()
|
||||
|
||||
return filter
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ func TestIssueFilter(t *testing.T) {
|
||||
|
||||
{"is:closed milestone:0.1.0", &IssueFilter{State: Closed, Milestone: "0.1.0"}},
|
||||
{"milestone:v1.0.0 keyword", &IssueFilter{Query: "keyword", Milestone: "v1.0.0"}},
|
||||
{`label:"a bug" keyword`, &IssueFilter{Query: "keyword", Labels: []string{"a bug"}}},
|
||||
}
|
||||
|
||||
for idx, tc := range tt {
|
||||
|
Loading…
Reference in New Issue
Block a user