Skip to content

Commit

Permalink
ref(filtering): redesign filter creation (#156)
Browse files Browse the repository at this point in the history
  • Loading branch information
plastikfan committed Sep 4, 2024
1 parent d1cbc53 commit b2f14d0
Show file tree
Hide file tree
Showing 12 changed files with 301 additions and 274 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
"unconvert",
"unlambda",
"unparam",
"vals",
"varcheck",
"verr",
"watchv",
Expand Down
4 changes: 4 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ tasks:
cmds:
- go test ./core

tf-filter:
cmds:
- go test ./internal/filtering

tf-hiber:
cmds:
- go test ./internal/feat/hiber
Expand Down
21 changes: 11 additions & 10 deletions internal/feat/filter/schemes.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,14 @@ func newScheme(o *pref.Options) scheme {
}
}

if o.Filter.IsCustomFilteringActive() {
return &customScheme{
common: c,
}
// If none of the other schemes active, then according to
// FilterOptions.IsFilteringActive, the only other possibility
// is that the client has defined a custom filter, so we don't
// need to check again.
//
return &customScheme{
common: c,
}

return nil
}

type common struct {
Expand All @@ -68,7 +69,7 @@ type nativeScheme struct {
}

func (f *nativeScheme) create() error {
filter, err := filtering.NewNodeFilter(f.o.Filter.Node, &f.o.Filter)
filter, err := filtering.New(f.o.Filter.Node, &f.o.Filter)
if err != nil {
return err
}
Expand All @@ -94,7 +95,7 @@ type childScheme struct {
}

func (f *childScheme) create() error {
filter, err := filtering.NewChildFilter(f.o.Filter.Child)
filter, err := filtering.NewChild(f.o.Filter.Child)

if err != nil {
return err
Expand Down Expand Up @@ -140,7 +141,7 @@ type samplerScheme struct {
}

func (f *samplerScheme) create() error {
filter, err := filtering.NewSampleFilter(f.o.Filter.Sample, &f.o.Sampling)
filter, err := filtering.NewSample(f.o.Filter.Sample, &f.o.Sampling)

if err != nil {
return err
Expand All @@ -163,7 +164,7 @@ func (f *samplerScheme) create() error {
})
}

return nil
return filter.Validate()
}

func (f *samplerScheme) init(pi *types.PluginInit, crate *measure.Crate) {
Expand Down
2 changes: 2 additions & 0 deletions internal/feat/hiber/hibernate-defs.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/snivilised/traverse/cycle"
"github.com/snivilised/traverse/enums"
"github.com/snivilised/traverse/internal/override"
"github.com/snivilised/traverse/pref"
)

const (
Expand Down Expand Up @@ -47,6 +48,7 @@ type (

common struct {
ho *core.HibernateOptions
fo *pref.FilterOptions
triggers triggers
controls *cycle.Controls
}
Expand Down
1 change: 1 addition & 0 deletions internal/feat/hiber/hibernate-plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func IfActive(o *pref.Options, mediator types.Mediator) types.Plugin {
profile: &simple{
common: common{
ho: &o.Hibernate,
fo: &o.Filter,
},
},
}
Expand Down
4 changes: 2 additions & 2 deletions internal/feat/hiber/hibernate-simple-profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func (p *simple) init(controls *cycle.Controls) error {
p.controls = controls

if p.common.ho.WakeAt != nil {
filter, err := filtering.NewNodeFilter(p.common.ho.WakeAt, nil)
filter, err := filtering.New(p.common.ho.WakeAt, p.common.fo)
if err != nil {
return err
}
Expand All @@ -40,7 +40,7 @@ func (p *simple) init(controls *cycle.Controls) error {
}

if p.common.ho.SleepAt != nil {
filter, err := filtering.NewNodeFilter(p.common.ho.SleepAt, nil)
filter, err := filtering.New(p.common.ho.SleepAt, p.common.fo)
if err != nil {
return err
}
Expand Down
157 changes: 157 additions & 0 deletions internal/filtering/builders.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package filtering

import (
"strings"

"github.com/snivilised/traverse/core"
"github.com/snivilised/traverse/enums"
"github.com/snivilised/traverse/internal/third/lo"
"github.com/snivilised/traverse/locale"
"github.com/snivilised/traverse/pref"
)

func buildNativeNodeFilter(definition *core.FilterDef) (core.TraverseFilter, error) {
var (
filter core.TraverseFilter
ifNotApplicable = applicable(definition.IfNotApplicable)
err error
)

switch definition.Type {
case enums.FilterTypeExtendedGlob:
filter, err = createExtendedGlobFilter(definition, ifNotApplicable)

case enums.FilterTypeRegex:
filter = createRegexFilter(definition, ifNotApplicable)

case enums.FilterTypeGlob:
filter = createGlobFilter(definition, ifNotApplicable)

case enums.FilterTypeCustom, enums.FilterTypePoly:
return nil, nil

case enums.FilterTypeUndefined:
return nil, locale.ErrFilterMissingType
}

if err != nil {
return nil, err
}

return filter, filter.Validate()
}

func applicable(ifNotApplicable enums.TriStateBool) bool {
switch ifNotApplicable {
case enums.TriStateBoolTrue:
return true

case enums.TriStateBoolFalse:
return false

case enums.TriStateBoolUndefined:
}

return true
}

func buildPolyNodeFilter(definition *core.FilterDef,
fo *pref.FilterOptions,
nativeFn filterNativeFunc,
customFn filterUsingOptionsFunc,
) (core.TraverseFilter, error) {
if definition.Type != enums.FilterTypePoly {
return nil, nil
}
polyDef := fo.Node.Poly

// enforce the correct filter scopes
//
polyDef.File.Scope.Set(enums.ScopeFile)
polyDef.File.Scope.Clear(enums.ScopeFolder)

polyDef.Folder.Scope.Set(enums.ScopeFolder)
polyDef.Folder.Scope.Clear(enums.ScopeFile)

file, err := buildConstituent(&polyDef.File, fo, nativeFn, customFn)

if err != nil {
return nil, err
}

folder, err := buildConstituent(&polyDef.Folder, fo, nativeFn, customFn)

if err != nil {
return nil, err
}

filter := &Poly{
File: file,
Folder: folder,
}

return filter, nil
}

func buildConstituent(definition *core.FilterDef,
fo *pref.FilterOptions,
nativeFn filterNativeFunc,
customFn filterUsingOptionsFunc,
) (core.TraverseFilter, error) {
filter, err := OrFuncE(
func() (core.TraverseFilter, error) {
return customFn(definition, fo)
},
func() (core.TraverseFilter, error) {
return nativeFn(definition)
},
)

if err != nil {
return nil, err
}

if err := filter.Validate(); err != nil {
return nil, err
}

return filter, err
}

func getCustomFilter(_ *core.FilterDef,
fo *pref.FilterOptions,
) (core.TraverseFilter, error) {
return fo.Custom, nil
}

func splitExtendedGlobPattern(pattern string) (segments, suffixes []string, err error) {
if !strings.Contains(pattern, "|") {
return []string{}, []string{},
locale.NewInvalidExtGlobFilterMissingSeparatorError(pattern)
}

segments = strings.Split(pattern, "|")
suffixes = strings.Split(segments[1], ",")

suffixes = lo.Reject(suffixes, func(item string, _ int) bool {
return item == ""
})

return segments, suffixes, nil
}

const (
exclusionDelim = "/"
)

func splitGlob(baseGlob string) (base, exclusion string) {
base = strings.ToLower(baseGlob)

if strings.Contains(base, exclusionDelim) {
constituents := strings.Split(base, exclusionDelim)
base = constituents[0]
exclusion = constituents[1]
}

return base, exclusion
}
78 changes: 78 additions & 0 deletions internal/filtering/child.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,87 @@
package filtering

import (
"slices"
"strings"

"github.com/snivilised/traverse/core"
"github.com/snivilised/traverse/enums"
"github.com/snivilised/traverse/internal/third/lo"
"github.com/snivilised/traverse/locale"
)

func NewChild(def *core.ChildFilterDef) (core.ChildTraverseFilter, error) {
var (
filter core.ChildTraverseFilter
)

if def == nil {
return nil, locale.ErrFilterIsNil
}

switch def.Type {
case enums.FilterTypeExtendedGlob:
var (
err error
segments, suffixes []string
)

if segments, suffixes, err = splitExtendedGlobPattern(def.Pattern); err != nil {
return nil, locale.NewInvalidIncaseFilterDefError(def.Pattern)
}

base, exclusion := splitGlob(segments[0])

filter = &ChildExtendedGlobFilter{
Child: Child{
Name: def.Description,
Pattern: def.Pattern,
Negate: def.Negate,
},
baseGlob: base,
suffixes: lo.Map(suffixes, func(s string, _ int) string {
return strings.ToLower(strings.TrimPrefix(strings.TrimSpace(s), "."))
}),
anyExtension: slices.Contains(suffixes, "*"),
exclusion: exclusion,
}

case enums.FilterTypeRegex:
filter = &ChildRegex{
Child: Child{
Name: def.Description,
Pattern: def.Pattern,
Negate: def.Negate,
},
}

case enums.FilterTypeGlob:
filter = &ChildGlob{
Child: Child{
Name: def.Description,
Pattern: def.Pattern,
Negate: def.Negate,
},
}

case enums.FilterTypeCustom:
return nil, locale.ErrFilterCustomNotSupported

case enums.FilterTypeUndefined:
return nil, locale.ErrFilterUndefined

case enums.FilterTypePoly:
}

if filter != nil {
if err := filter.Validate(); err != nil {
return nil, err
}
}

return filter, nil
}

// ChildFilter ================================================================

// Child filter used when subscription is FoldersWithFiles
Expand Down
Loading

0 comments on commit b2f14d0

Please sign in to comment.