diff --git a/decor/counters.go b/decor/counters.go index 34d3a0a..f41b679 100644 --- a/decor/counters.go +++ b/decor/counters.go @@ -47,12 +47,11 @@ for _, widthConf := range wcc { wc = widthConf } - wc.Init() if pairFmt == "" { pairFmt = "%d / %d" } d := &countersDecorator{ - WC: wc, + WC: wc.Init(), unit: unit, pairFmt: pairFmt, } @@ -61,16 +60,11 @@ type countersDecorator struct { WC - unit int - pairFmt string - completeMsg *string + unit int + pairFmt string } func (d *countersDecorator) Decor(st *Statistics) string { - if st.Completed && d.completeMsg != nil { - return d.FormatMsg(*d.completeMsg) - } - var res string switch d.unit { case UnitKiB: @@ -83,7 +77,3 @@ return d.FormatMsg(res) } - -func (d *countersDecorator) OnCompleteMessage(msg string) { - d.completeMsg = &msg -} diff --git a/decor/decorator.go b/decor/decorator.go index 12a03be..5190b35 100644 --- a/decor/decorator.go +++ b/decor/decorator.go @@ -52,10 +52,11 @@ } // Decorator interface. -// A decorator must implement this interface, in order to be used with -// mpb library. +// Implementors should embed WC type, that way only single method +// Decor(*Statistics) needs to be implemented, the rest will be handled +// by WC type. type Decorator interface { - ConfigSetter + Configurator Synchronizer Decor(*Statistics) string } @@ -67,20 +68,14 @@ Sync() (chan int, bool) } -// ConfigSetter interface. -type ConfigSetter interface { - SetConfig(config WC) (old WC) -} - -// OnCompleteMessenger interface. -// Decorators implementing this interface suppose to return provided -// string on complete event. -type OnCompleteMessenger interface { - OnCompleteMessage(string) +// Configurator interface. +type Configurator interface { + GetConf() WC + SetConf(*WC) } // AmountReceiver interface. -// EWMA based decorators must implement this one. +// EWMA based decorators need to implement this one. type AmountReceiver interface { NextAmount(int64, ...time.Duration) } @@ -136,7 +131,7 @@ } // Init initializes width related config. -func (wc *WC) Init() { +func (wc *WC) Init() WC { wc.dynFormat = "%%" if (wc.C & DidentRight) != 0 { wc.dynFormat += "-" @@ -144,8 +139,11 @@ wc.dynFormat += "%ds" wc.staticFormat = fmt.Sprintf(wc.dynFormat, wc.W) if (wc.C & DSyncWidth) != 0 { + // it's deliberate choice to override wsync on each Init() call, + // this way globals like WCSyncSpace can be reused wc.wsync = make(chan int) } + return *wc } // Sync is implementation of Synchronizer interface. @@ -153,23 +151,12 @@ return wc.wsync, (wc.C & DSyncWidth) != 0 } -// SetConfig sets new conf and returns old one. -func (wc *WC) SetConfig(conf WC) (old WC) { - conf.Init() - old = *wc - *wc = conf - return old +// GetConf is implementation of Configurator interface. +func (wc *WC) GetConf() WC { + return *wc } -// OnComplete returns decorator, which wraps provided decorator, with -// sole purpose to display provided message on complete event. -// -// `decorator` Decorator to wrap -// -// `message` message to display on complete event -func OnComplete(decorator Decorator, message string) Decorator { - if d, ok := decorator.(OnCompleteMessenger); ok { - d.OnCompleteMessage(message) - } - return decorator +// SetConf is implementation of Configurator interface. +func (wc *WC) SetConf(conf *WC) { + *wc = conf.Init() } diff --git a/decor/elapsed.go b/decor/elapsed.go index b4ca601..ac28731 100644 --- a/decor/elapsed.go +++ b/decor/elapsed.go @@ -25,9 +25,8 @@ for _, widthConf := range wcc { wc = widthConf } - wc.Init() d := &elapsedDecorator{ - WC: wc, + WC: wc.Init(), startTime: startTime, producer: chooseTimeProducer(style), } @@ -36,24 +35,14 @@ type elapsedDecorator struct { WC - startTime time.Time - producer func(time.Duration) string - msg string - completeMsg *string + startTime time.Time + producer func(time.Duration) string + msg string } func (d *elapsedDecorator) Decor(st *Statistics) string { - if st.Completed { - if d.completeMsg != nil { - return d.FormatMsg(*d.completeMsg) - } - return d.FormatMsg(d.msg) + if !st.Completed { + d.msg = d.producer(time.Since(d.startTime)) } - - d.msg = d.producer(time.Since(d.startTime)) return d.FormatMsg(d.msg) } - -func (d *elapsedDecorator) OnCompleteMessage(msg string) { - d.completeMsg = &msg -} diff --git a/decor/eta.go b/decor/eta.go index a85af6b..818cded 100644 --- a/decor/eta.go +++ b/decor/eta.go @@ -50,9 +50,8 @@ for _, widthConf := range wcc { wc = widthConf } - wc.Init() d := &movingAverageETA{ - WC: wc, + WC: wc.Init(), average: average, normalizer: normalizer, producer: chooseTimeProducer(style), @@ -62,17 +61,12 @@ type movingAverageETA struct { WC - average ewma.MovingAverage - normalizer TimeNormalizer - producer func(time.Duration) string - completeMsg *string + average ewma.MovingAverage + normalizer TimeNormalizer + producer func(time.Duration) string } func (d *movingAverageETA) Decor(st *Statistics) string { - if st.Completed && d.completeMsg != nil { - return d.FormatMsg(*d.completeMsg) - } - v := math.Round(d.average.Value()) remaining := time.Duration((st.Total - st.Current) * int64(v)) if d.normalizer != nil { @@ -91,10 +85,6 @@ return } d.average.Add(durPerItem) -} - -func (d *movingAverageETA) OnCompleteMessage(msg string) { - d.completeMsg = &msg } // AverageETA decorator. It's wrapper of NewAverageETA. @@ -120,9 +110,8 @@ for _, widthConf := range wcc { wc = widthConf } - wc.Init() d := &averageETA{ - WC: wc, + WC: wc.Init(), startTime: startTime, normalizer: normalizer, producer: chooseTimeProducer(style), @@ -132,17 +121,12 @@ type averageETA struct { WC - startTime time.Time - normalizer TimeNormalizer - producer func(time.Duration) string - completeMsg *string + startTime time.Time + normalizer TimeNormalizer + producer func(time.Duration) string } func (d *averageETA) Decor(st *Statistics) string { - if st.Completed && d.completeMsg != nil { - return d.FormatMsg(*d.completeMsg) - } - var remaining time.Duration if st.Current != 0 { durPerItem := float64(time.Since(d.startTime)) / float64(st.Current) @@ -153,10 +137,6 @@ } } return d.FormatMsg(d.producer(remaining)) -} - -func (d *averageETA) OnCompleteMessage(msg string) { - d.completeMsg = &msg } func (d *averageETA) AverageAdjust(startTime time.Time) { diff --git a/decor/merge.go b/decor/merge.go index 06abf91..b0ed244 100644 --- a/decor/merge.go +++ b/decor/merge.go @@ -20,13 +20,13 @@ } md := &mergeDecorator{ Decorator: decorator, + wc: decorator.GetConf(), placeHolders: make([]*placeHolderDecorator, len(placeholders)), } - md.wc = decorator.SetConfig(md.wc) + decorator.SetConf(&WC{}) for i, wc := range placeholders { - wc.Init() md.placeHolders[i] = &placeHolderDecorator{ - WC: wc, + WC: wc.Init(), wsync: make(chan int), } } diff --git a/decor/name.go b/decor/name.go index fde1b3b..2d5865f 100644 --- a/decor/name.go +++ b/decor/name.go @@ -10,9 +10,8 @@ for _, widthConf := range wcc { wc = widthConf } - wc.Init() d := &nameDecorator{ - WC: wc, + WC: wc.Init(), msg: name, } return d @@ -20,17 +19,9 @@ type nameDecorator struct { WC - msg string - complete *string + msg string } func (d *nameDecorator) Decor(st *Statistics) string { - if st.Completed && d.complete != nil { - return d.FormatMsg(*d.complete) - } return d.FormatMsg(d.msg) } - -func (d *nameDecorator) OnCompleteMessage(msg string) { - d.complete = &msg -} diff --git a/decor/on_complete.go b/decor/on_complete.go new file mode 100644 index 0000000..1c88684 --- /dev/null +++ b/decor/on_complete.go @@ -0,0 +1,29 @@ +package decor + +// OnComplete returns decorator, which wraps provided decorator, with +// sole purpose to display provided message on complete event. +// +// `decorator` Decorator to wrap +// +// `message` message to display on complete event +func OnComplete(decorator Decorator, message string) Decorator { + d := &onCompleteWrapper{ + Decorator: decorator, + wc: decorator.GetConf(), + msg: message, + } + return d +} + +type onCompleteWrapper struct { + Decorator + wc WC + msg string +} + +func (d *onCompleteWrapper) Decor(st *Statistics) string { + if st.Completed { + return d.wc.FormatMsg(d.msg) + } + return d.Decorator.Decor(st) +} diff --git a/decor/percentage.go b/decor/percentage.go index 0acd44e..abf343a 100644 --- a/decor/percentage.go +++ b/decor/percentage.go @@ -51,12 +51,11 @@ for _, widthConf := range wcc { wc = widthConf } - wc.Init() if fmt == "" { fmt = "% d" } d := &percentageDecorator{ - WC: wc, + WC: wc.Init(), fmt: fmt, } return d @@ -64,18 +63,10 @@ type percentageDecorator struct { WC - fmt string - completeMsg *string + fmt string } func (d *percentageDecorator) Decor(st *Statistics) string { - if st.Completed && d.completeMsg != nil { - return d.FormatMsg(*d.completeMsg) - } p := internal.Percentage(st.Total, st.Current, 100) return d.FormatMsg(fmt.Sprintf(d.fmt, percentageType(p))) } - -func (d *percentageDecorator) OnCompleteMessage(msg string) { - d.completeMsg = &msg -} diff --git a/decor/speed.go b/decor/speed.go index c22e5df..df400c1 100644 --- a/decor/speed.go +++ b/decor/speed.go @@ -59,9 +59,8 @@ if format == "" { format = "%.0f" } - wc.Init() d := &movingAverageSpeed{ - WC: wc, + WC: wc.Init(), average: average, producer: chooseSpeedProducer(unit, format), } @@ -70,26 +69,19 @@ type movingAverageSpeed struct { WC - producer func(float64) string - average ewma.MovingAverage - msg string - completeMsg *string + producer func(float64) string + average ewma.MovingAverage + msg string } func (d *movingAverageSpeed) Decor(st *Statistics) string { - if st.Completed { - if d.completeMsg != nil { - return d.FormatMsg(*d.completeMsg) + if !st.Completed { + var speed float64 + if v := math.Round(d.average.Value()); v != 0 { + speed = 1 / time.Duration(v).Seconds() } - return d.FormatMsg(d.msg) + d.msg = d.producer(speed) } - - var speed float64 - if v := math.Round(d.average.Value()); v != 0 { - speed = 1 / time.Duration(v).Seconds() - } - - d.msg = d.producer(speed) return d.FormatMsg(d.msg) } @@ -103,10 +95,6 @@ return } d.average.Add(durPerByte) -} - -func (d *movingAverageSpeed) OnCompleteMessage(msg string) { - d.completeMsg = &msg } // AverageSpeed decorator with dynamic unit measure adjustment. It's @@ -141,9 +129,8 @@ if format == "" { format = "%.0f" } - wc.Init() d := &averageSpeed{ - WC: wc, + WC: wc.Init(), startTime: startTime, producer: chooseSpeedProducer(unit, format), } @@ -152,28 +139,18 @@ type averageSpeed struct { WC - startTime time.Time - producer func(float64) string - msg string - completeMsg *string + startTime time.Time + producer func(float64) string + msg string } func (d *averageSpeed) Decor(st *Statistics) string { - if st.Completed { - if d.completeMsg != nil { - return d.FormatMsg(*d.completeMsg) - } - return d.FormatMsg(d.msg) + if !st.Completed { + speed := float64(st.Current) / time.Since(d.startTime).Seconds() + d.msg = d.producer(speed) } - speed := float64(st.Current) / time.Since(d.startTime).Seconds() - d.msg = d.producer(speed) - return d.FormatMsg(d.msg) -} - -func (d *averageSpeed) OnCompleteMessage(msg string) { - d.completeMsg = &msg } func (d *averageSpeed) AverageAdjust(startTime time.Time) { diff --git a/decor/spinner.go b/decor/spinner.go index b184b5a..24f5531 100644 --- a/decor/spinner.go +++ b/decor/spinner.go @@ -12,12 +12,11 @@ for _, widthConf := range wcc { wc = widthConf } - wc.Init() if len(frames) == 0 { frames = defaultSpinnerStyle } d := &spinnerDecorator{ - WC: wc, + WC: wc.Init(), frames: frames, } return d @@ -25,20 +24,12 @@ type spinnerDecorator struct { WC - frames []string - count uint - complete *string + frames []string + count uint } func (d *spinnerDecorator) Decor(st *Statistics) string { - if st.Completed && d.complete != nil { - return d.FormatMsg(*d.complete) - } frame := d.frames[d.count%uint(len(d.frames))] d.count++ return d.FormatMsg(frame) } - -func (d *spinnerDecorator) OnCompleteMessage(msg string) { - d.complete = &msg -}