diff --git a/context.go b/context.go index 7b33e4c..6df6eda 100644 --- a/context.go +++ b/context.go @@ -26,23 +26,21 @@ import ( "os" "runtime" "sync" - - "github.com/bmatcuk/doublestar" ) type context struct { gs *goldsmith plug Plugin - filters []string + filters []Filter input, output chan *file } func (ctx *context) chain() { defer close(ctx.output) - var filters []string + var err error + var filters []Filter if initializer, ok := ctx.plug.(Initializer); ok { - var err error filters, err = initializer.Initialize(ctx) if err != nil { ctx.gs.fault(ctx.plug.Name(), nil, err) @@ -60,21 +58,17 @@ func (ctx *context) chain() { defer wg.Done() for f := range ctx.input { accept := processor != nil - matcher := func(patterns []string) { - if accept && len(patterns) > 0 { - accept = false - for _, pattern := range patterns { - if match, _ := doublestar.PathMatch(pattern, f.Path()); match { - accept = true - break - } - } + for _, filter := range append(ctx.filters, filters...) { + if accept, err = filter.Accept(ctx, f); err != nil { + ctx.gs.fault(filter.Name(), f, err) + return + } + + if !accept { + break } } - matcher(filters) - matcher(ctx.filters) - if accept { if _, err := f.Seek(0, os.SEEK_SET); err != nil { ctx.gs.fault("core", f, err) diff --git a/core.go b/core.go index 19fa694..da58257 100644 --- a/core.go +++ b/core.go @@ -33,18 +33,15 @@ type goldsmith struct { contexts []*context refs map[string]bool complete bool + filters []Filter errors []error errorMtx sync.Mutex } -func (gs *goldsmith) pushContext(plug Plugin, filters []string) *context { - ctx := &context{ - gs: gs, - plug: plug, - filters: filters, - output: make(chan *file), - } +func (gs *goldsmith) pushContext(plug Plugin) *context { + ctx := &context{gs: gs, plug: plug, output: make(chan *file)} + ctx.filters = append(ctx.filters, gs.filters...) if len(gs.contexts) > 0 { ctx.input = gs.contexts[len(gs.contexts)-1].output @@ -102,12 +99,35 @@ func (gs *goldsmith) fault(name string, f *file, err error) { // Goldsmith Implementation // -func (gs *goldsmith) Chain(p Plugin, filters ...string) Goldsmith { +func (gs *goldsmith) Chain(p Plugin) Goldsmith { if gs.complete { panic("attempted reuse of goldsmith instance") } - gs.pushContext(p, filters) + gs.pushContext(p) + return gs +} + +func (gs *goldsmith) FilterPush(f Filter) Goldsmith { + if gs.complete { + panic("attempted reuse of goldsmith instance") + } + + gs.filters = append(gs.filters, f) + return gs +} + +func (gs *goldsmith) FilterPop() Goldsmith { + if gs.complete { + panic("attempted reuse of goldsmith instance") + } + + count := len(gs.filters) + if count == 0 { + panic("attempted to pop empty filter stack") + } + + gs.filters = gs.filters[:count-1] return gs } diff --git a/goldsmith.go b/goldsmith.go index b071e1f..fdbfd9b 100644 --- a/goldsmith.go +++ b/goldsmith.go @@ -32,13 +32,15 @@ import ( ) type Goldsmith interface { - Chain(p Plugin, filters ...string) Goldsmith + Chain(p Plugin) Goldsmith + FilterPush(f Filter) Goldsmith + FilterPop() Goldsmith End(dstDir string) []error } -func Begin(srcDir string, filters ...string) Goldsmith { +func Begin(srcDir string) Goldsmith { gs := &goldsmith{srcDir: srcDir, refs: make(map[string]bool)} - gs.Chain(new(loader), filters...) + gs.Chain(new(loader)) return gs } @@ -113,7 +115,7 @@ func (e Error) Error() string { } type Initializer interface { - Initialize(ctx Context) ([]string, error) + Initialize(ctx Context) ([]Filter, error) } type Processor interface { @@ -124,6 +126,15 @@ type Finalizer interface { Finalize(ctx Context) error } -type Plugin interface { +type Component interface { Name() string } + +type Filter interface { + Component + Accept(ctx Context, f File) (bool, error) +} + +type Plugin interface { + Component +} diff --git a/loader.go b/loader.go index f077e03..41bc9e5 100644 --- a/loader.go +++ b/loader.go @@ -30,7 +30,7 @@ func (*loader) Name() string { return "loader" } -func (*loader) Initialize(ctx Context) ([]string, error) { +func (*loader) Initialize(ctx Context) ([]Filter, error) { infos := make(chan fileInfo) go scanDir(ctx.SrcDir(), infos)