fix: using files from context in source

dev
Antonio De Lucreziis 2 years ago
parent f5af79c7d9
commit b9e71677b9

@ -56,11 +56,6 @@ func (op *Source) Configure(config map[string]any) error {
var _ cabret.ListOperation = &Source{} var _ cabret.ListOperation = &Source{}
func (op Source) ProcessList(ctx *cabret.Context, contents []cabret.Content) ([]cabret.Content, error) { func (op Source) ProcessList(ctx *cabret.Context, contents []cabret.Content) ([]cabret.Content, error) {
files, err := cabret.FindFiles()
if err != nil {
return nil, err
}
matches := []cabret.MatchResult{} matches := []cabret.MatchResult{}
for _, rawPattern := range op.Patterns { for _, rawPattern := range op.Patterns {
@ -69,10 +64,10 @@ func (op Source) ProcessList(ctx *cabret.Context, contents []cabret.Content) ([]
return nil, err return nil, err
} }
for _, f := range files { for _, file := range ctx.Files {
if ok, captures, _ := pattern.Match(f); ok { if ok, captures, _ := pattern.Match(file); ok {
matches = append(matches, cabret.MatchResult{ matches = append(matches, cabret.MatchResult{
File: f, File: file,
Captures: captures, Captures: captures,
}) })
} }

@ -16,6 +16,11 @@ type PathPart interface {
regex() string regex() string
} }
var _ PathPart = PathLiteral{}
var _ PathPart = PathShortPattern{}
var _ PathPart = PathLongPattern{}
var _ PathPart = PathString{}
type PathLiteral struct { type PathLiteral struct {
LongAny bool `parser:" @'**'"` LongAny bool `parser:" @'**'"`
ShortAny bool `parser:"| @'*' "` ShortAny bool `parser:"| @'*' "`
@ -25,7 +30,7 @@ type PathLiteral struct {
func (p PathLiteral) regex() string { func (p PathLiteral) regex() string {
switch { switch {
case p.Slash: case p.Slash:
return "/" return regexp.QuoteMeta("/")
case p.ShortAny: case p.ShortAny:
return "([^/]+?)" return "([^/]+?)"
case p.LongAny: case p.LongAny:
@ -52,7 +57,7 @@ func (p PathLongPattern) regex() string {
} }
type PathString struct { type PathString struct {
Value string `parser:"@Ident"` Value string `parser:"@(Ident|Rune)+"`
} }
func (p PathString) regex() string { func (p PathString) regex() string {
@ -63,18 +68,44 @@ type Pattern struct {
Parts []PathPart `parser:"@@+"` Parts []PathPart `parser:"@@+"`
} }
func (pp Pattern) regex() string { var parser = participle.MustBuild[Pattern](
sb := &strings.Builder{} participle.Union[PathPart](
&PathLiteral{},
&PathLongPattern{},
&PathShortPattern{},
&PathString{},
),
participle.Lexer(
lexer.MustSimple([]lexer.SimpleRule{
{Name: "Slash", Pattern: `/`},
{Name: "LongAny", Pattern: `\*\*`},
{Name: "ShortAny", Pattern: `\*`},
{Name: "PatternLongOpen", Pattern: `{{`},
{Name: "PatternLongClose", Pattern: `}}`},
{Name: "PatternShortOpen", Pattern: `{`},
{Name: "PatternShortClose", Pattern: `}`},
{Name: "Ident", Pattern: `[a-zA-Z][a-zA-Z0-9\_]*`},
{Name: "Rune", Pattern: `[^/{}]+`},
}),
),
)
for _, p := range pp.Parts { func ParsePattern(path string) (*Pattern, error) {
sb.WriteString(p.regex()) return parser.ParseString("", path)
} }
return sb.String() func MustParsePattern(path string) *Pattern {
p, err := ParsePattern(path)
if err != nil {
panic(err)
}
return p
} }
func (pp Pattern) Match(s string) (bool, map[string]string, error) { // Match takes a path "s" and matches it against this pattern and returns whether it matched and in that case a map containing all captures for this pattern. This will throw an error if it can't compile the internal regex (should never happen).
r, err := regexp.Compile("^" + pp.regex() + "$") func (p Pattern) Match(s string) (bool, map[string]string, error) {
r, err := regexp.Compile("^" + p.regex() + "$")
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
@ -96,26 +127,15 @@ func (pp Pattern) Match(s string) (bool, map[string]string, error) {
return true, ctx, nil return true, ctx, nil
} }
var parser = participle.MustBuild[Pattern]( func (p Pattern) regex() string {
participle.Union[PathPart]( sb := &strings.Builder{}
&PathLiteral{},
&PathLongPattern{}, for _, part := range p.Parts {
&PathShortPattern{}, sb.WriteString(part.regex())
&PathString{}, }
),
participle.Lexer( return sb.String()
lexer.MustSimple([]lexer.SimpleRule{ }
{Name: "Slash", Pattern: `/`},
{Name: "LongAny", Pattern: `\*\*`},
{Name: "ShortAny", Pattern: `\*`},
{Name: "PatternLongOpen", Pattern: `{{`},
{Name: "PatternLongClose", Pattern: `}}`},
{Name: "PatternShortOpen", Pattern: `{`},
{Name: "PatternShortClose", Pattern: `}`},
{Name: "Ident", Pattern: `[^/{}]+`},
}),
),
)
func RenderTemplate(tmpl string, ctx map[string]string) string { func RenderTemplate(tmpl string, ctx map[string]string) string {
s := tmpl s := tmpl
@ -124,16 +144,3 @@ func RenderTemplate(tmpl string, ctx map[string]string) string {
} }
return s return s
} }
func ParsePattern(path string) (*Pattern, error) {
return parser.ParseString("", path)
}
func MustParsePattern(path string) *Pattern {
p, err := ParsePattern(path)
if err != nil {
panic(err)
}
return p
}

@ -2,6 +2,7 @@ package path_test
import ( import (
"testing" "testing"
"unicode"
"github.com/aziis98/cabret/path" "github.com/aziis98/cabret/path"
"gotest.tools/assert" "gotest.tools/assert"
@ -170,3 +171,37 @@ func TestMultipleGroups(t *testing.T) {
}) })
}) })
} }
func FuzzMatch(f *testing.F) {
f.Add(`{a}.txt`)
f.Add(`{a}/{b}.txt`)
f.Add(`src/{{a}}/index.html`)
f.Add(`/a/{b}/c-{d}.go`)
path.MustParsePattern(`{a}.txt`)
path.MustParsePattern(`{a}/{b}.txt`)
path.MustParsePattern(`src/{{a}}/index.html`)
path.MustParsePattern(`/a/{b}/c-{d}.go`)
f.Fuzz(func(t *testing.T, pattern string) {
goodPattern := make([]rune, 0, len(pattern))
// filter in only ascii runes
for _, c := range pattern {
if c <= unicode.MaxASCII {
goodPattern = append(goodPattern, c)
}
}
pattern = string(goodPattern)
p, err := path.ParsePattern(pattern)
if err != nil {
return
}
if _, _, err := p.Match(""); err != nil {
t.Errorf(`invalid regexp generated by pattern %q`, pattern)
}
})
}

Loading…
Cancel
Save