diff --git a/bar.go b/bar.go index 598a92b..d629e78 100644 --- a/bar.go +++ b/bar.go @@ -396,18 +396,6 @@ return table } -func (s *bState) appendAmountReceiver(d decor.Decorator) { - if ar, ok := d.(decor.AmountReceiver); ok { - s.amountReceivers = append(s.amountReceivers, ar) - } -} - -func (s *bState) appendShutdownListener(d decor.Decorator) { - if sl, ok := d.(decor.ShutdownListener); ok { - s.shutdownListeners = append(s.shutdownListeners, sl) - } -} - func (b *Bar) refreshNowTillShutdown() { for { select { diff --git a/bar_option.go b/bar_option.go index 26d72e4..7b60520 100644 --- a/bar_option.go +++ b/bar_option.go @@ -7,35 +7,47 @@ // BarOption is a function option which changes the default behavior of a bar. type BarOption func(*bState) +type merger interface { + CompoundDecorators() []decor.Decorator +} + +func (s *bState) appendAmountReceiver(d decor.Decorator) { + if ar, ok := d.(decor.AmountReceiver); ok { + s.amountReceivers = append(s.amountReceivers, ar) + } +} + +func (s *bState) appendShutdownListener(d decor.Decorator) { + if sl, ok := d.(decor.ShutdownListener); ok { + s.shutdownListeners = append(s.shutdownListeners, sl) + } +} + +func (s *bState) addDecorators(dest *[]decor.Decorator, decorators ...decor.Decorator) { + for _, decorator := range decorators { + s.appendAmountReceiver(decorator) + s.appendShutdownListener(decorator) + if m, ok := decorator.(merger); ok { + dd := m.CompoundDecorators() + s.appendAmountReceiver(dd[0]) + s.appendShutdownListener(dd[0]) + *dest = append(*dest, dd[1:]...) + } + *dest = append(*dest, decorator) + } +} + // AppendDecorators let you inject decorators to the bar's right side. -func AppendDecorators(appenders ...decor.Decorator) BarOption { - return func(s *bState) { - for _, decorator := range appenders { - s.appendAmountReceiver(decorator) - s.appendShutdownListener(decorator) - if md, ok := decorator.(*decor.MergeDecorator); ok { - s.appendAmountReceiver(md.Decorator) - s.appendShutdownListener(md.Decorator) - s.aDecorators = append(s.aDecorators, md.PlaceHolders()...) - } - s.aDecorators = append(s.aDecorators, decorator) - } +func AppendDecorators(decorators ...decor.Decorator) BarOption { + return func(s *bState) { + s.addDecorators(&s.aDecorators, decorators...) } } // PrependDecorators let you inject decorators to the bar's left side. -func PrependDecorators(prependers ...decor.Decorator) BarOption { - return func(s *bState) { - for _, decorator := range prependers { - s.appendAmountReceiver(decorator) - s.appendShutdownListener(decorator) - if md, ok := decorator.(*decor.MergeDecorator); ok { - s.appendAmountReceiver(md.Decorator) - s.appendShutdownListener(md.Decorator) - s.pDecorators = append(s.pDecorators, md.PlaceHolders()...) - } - s.pDecorators = append(s.pDecorators, decorator) - } +func PrependDecorators(decorators ...decor.Decorator) BarOption { + return func(s *bState) { + s.addDecorators(&s.pDecorators, decorators...) } } diff --git a/decor/merge.go b/decor/merge.go index 5ef20d5..b0c4a4f 100644 --- a/decor/merge.go +++ b/decor/merge.go @@ -18,7 +18,7 @@ if _, ok := decorator.Sync(); !ok || len(placeholders) == 0 { return decorator } - md := &MergeDecorator{ + md := &mergeDecorator{ Decorator: decorator, placeHolders: make([]*placeHolderDecorator, len(placeholders)), } @@ -33,25 +33,26 @@ return md } -type MergeDecorator struct { +type mergeDecorator struct { Decorator wc WC placeHolders []*placeHolderDecorator } -func (d *MergeDecorator) PlaceHolders() []Decorator { - decorators := make([]Decorator, len(d.placeHolders)) +func (d *mergeDecorator) CompoundDecorators() []Decorator { + decorators := make([]Decorator, len(d.placeHolders)+1) + decorators[0] = d.Decorator for i, ph := range d.placeHolders { - decorators[i] = ph + decorators[i+1] = ph } return decorators } -func (md *MergeDecorator) Sync() (chan int, bool) { +func (md *mergeDecorator) Sync() (chan int, bool) { return md.wc.Sync() } -func (d *MergeDecorator) Decor(st *Statistics) string { +func (d *mergeDecorator) Decor(st *Statistics) string { msg := d.Decorator.Decor(st) msgLen := utf8.RuneCountInString(msg) pWidth := msgLen / (len(d.placeHolders) + 1)