merge refactoring
Vladimir Bauer
7 years ago
| 395 | 395 | return table |
| 396 | 396 | } |
| 397 | 397 | |
| 398 | func (s *bState) appendAmountReceiver(d decor.Decorator) { | |
| 399 | if ar, ok := d.(decor.AmountReceiver); ok { | |
| 400 | s.amountReceivers = append(s.amountReceivers, ar) | |
| 401 | } | |
| 402 | } | |
| 403 | ||
| 404 | func (s *bState) appendShutdownListener(d decor.Decorator) { | |
| 405 | if sl, ok := d.(decor.ShutdownListener); ok { | |
| 406 | s.shutdownListeners = append(s.shutdownListeners, sl) | |
| 407 | } | |
| 408 | } | |
| 409 | ||
| 398 | 410 | func (b *Bar) refreshNowTillShutdown() { |
| 399 | 411 | for { |
| 400 | 412 | select { |
| 10 | 10 | func AppendDecorators(appenders ...decor.Decorator) BarOption { |
| 11 | 11 | return func(s *bState) { |
| 12 | 12 | for _, decorator := range appenders { |
| 13 | if ar, ok := decorator.(decor.AmountReceiver); ok { | |
| 14 | s.amountReceivers = append(s.amountReceivers, ar) | |
| 15 | } | |
| 16 | if sl, ok := decorator.(decor.ShutdownListener); ok { | |
| 17 | s.shutdownListeners = append(s.shutdownListeners, sl) | |
| 13 | s.appendAmountReceiver(decorator) | |
| 14 | s.appendShutdownListener(decorator) | |
| 15 | if md, ok := decorator.(*decor.MergeDecorator); ok { | |
| 16 | s.appendAmountReceiver(md.Decorator) | |
| 17 | s.appendShutdownListener(md.Decorator) | |
| 18 | s.aDecorators = append(s.aDecorators, md.PlaceHolders()...) | |
| 18 | 19 | } |
| 19 | 20 | s.aDecorators = append(s.aDecorators, decorator) |
| 20 | 21 | } |
| 25 | 26 | func PrependDecorators(prependers ...decor.Decorator) BarOption { |
| 26 | 27 | return func(s *bState) { |
| 27 | 28 | for _, decorator := range prependers { |
| 28 | if ar, ok := decorator.(decor.AmountReceiver); ok { | |
| 29 | s.amountReceivers = append(s.amountReceivers, ar) | |
| 30 | } | |
| 31 | if sl, ok := decorator.(decor.ShutdownListener); ok { | |
| 32 | s.shutdownListeners = append(s.shutdownListeners, sl) | |
| 29 | s.appendAmountReceiver(decorator) | |
| 30 | s.appendShutdownListener(decorator) | |
| 31 | if md, ok := decorator.(*decor.MergeDecorator); ok { | |
| 32 | s.appendAmountReceiver(md.Decorator) | |
| 33 | s.appendShutdownListener(md.Decorator) | |
| 34 | s.pDecorators = append(s.pDecorators, md.PlaceHolders()...) | |
| 33 | 35 | } |
| 34 | 36 | s.pDecorators = append(s.pDecorators, decorator) |
| 35 | 37 | } |
| 54 | 54 | // A decorator must implement this interface, in order to be used with |
| 55 | 55 | // mpb library. |
| 56 | 56 | type Decorator interface { |
| 57 | ConfigSetter | |
| 57 | 58 | Synchronizer |
| 58 | 59 | Decor(*Statistics) string |
| 59 | 60 | } |
| 60 | 61 | |
| 61 | 62 | // Synchronizer interface. |
| 62 | 63 | // All decorators implement this interface implicitly. Its Sync |
| 63 | // method exposes width sync channel, if sync is enabled. | |
| 64 | // method exposes width sync channel, if DSyncWidth bit is set. | |
| 64 | 65 | type Synchronizer interface { |
| 65 | 66 | Sync() (chan int, bool) |
| 67 | } | |
| 68 | ||
| 69 | // ConfigSetter interface | |
| 70 | type ConfigSetter interface { | |
| 71 | SetConfig(config WC) (old WC) | |
| 66 | 72 | } |
| 67 | 73 | |
| 68 | 74 | // OnCompleteMessenger interface. |
| 106 | 112 | |
| 107 | 113 | // FormatMsg formats final message according to WC.W and WC.C. |
| 108 | 114 | // Should be called by any Decorator implementation. |
| 109 | func (wc WC) FormatMsg(msg string) string { | |
| 115 | func (wc *WC) FormatMsg(msg string) string { | |
| 110 | 116 | if (wc.C & DSyncWidth) != 0 { |
| 111 | 117 | wc.wsync <- utf8.RuneCountInString(msg) |
| 112 | 118 | max := <-wc.wsync |
| 113 | if max == 0 { | |
| 114 | max = wc.W | |
| 115 | } | |
| 116 | 119 | if (wc.C & DextraSpace) != 0 { |
| 117 | 120 | max++ |
| 118 | 121 | } |
| 138 | 141 | return wc.wsync, (wc.C & DSyncWidth) != 0 |
| 139 | 142 | } |
| 140 | 143 | |
| 144 | func (wc *WC) SetConfig(conf WC) (old WC) { | |
| 145 | old = *wc | |
| 146 | *wc = conf | |
| 147 | wc.Init() | |
| 148 | return old | |
| 149 | } | |
| 150 | ||
| 141 | 151 | // OnComplete returns decorator, which wraps provided decorator, with |
| 142 | 152 | // sole purpose to display provided message on complete event. |
| 143 | 153 | // |
| 5 | 5 | "unicode/utf8" |
| 6 | 6 | ) |
| 7 | 7 | |
| 8 | func Merge(decorator Decorator, wcc ...WC) Decorator { | |
| 8 | // Merge helper func, provides a way to synchronize width of single | |
| 9 | // decorator with adjacent decorators of different bar, like so: | |
| 10 | // +--------+---------+ | |
| 11 | // | MERGE(D) | | |
| 12 | // +--------+---------+ | |
| 13 | // | D1 | D2 | | |
| 14 | // +--------+---------+ | |
| 15 | // | |
| 16 | func Merge(decorator Decorator, placeholders ...WC) Decorator { | |
| 9 | 17 | if _, ok := decorator.Sync(); !ok { |
| 10 | 18 | return decorator |
| 11 | 19 | } |
| 12 | var placeHolders []*placeHolderDecorator | |
| 13 | for _, wc := range wcc { | |
| 20 | md := &MergeDecorator{Decorator: decorator} | |
| 21 | md.wc = decorator.SetConfig(md.wc) | |
| 22 | for _, wc := range placeholders { | |
| 14 | 23 | wc.Init() |
| 15 | placeHolders = append(placeHolders, &placeHolderDecorator{ | |
| 24 | md.placeHolders = append(md.placeHolders, &placeHolderDecorator{ | |
| 16 | 25 | WC: wc, |
| 17 | 26 | wsync: make(chan int), |
| 18 | 27 | }) |
| 19 | 28 | } |
| 20 | md := &MergeDecorator{ | |
| 21 | decorator: decorator, | |
| 22 | placeHolders: placeHolders, | |
| 23 | } | |
| 24 | md.WC = decorator.SetConfig(md.WC) | |
| 25 | 29 | return md |
| 26 | 30 | } |
| 27 | 31 | |
| 28 | 32 | type MergeDecorator struct { |
| 29 | WC | |
| 30 | decorator Decorator | |
| 33 | Decorator | |
| 34 | wc WC | |
| 31 | 35 | placeHolders []*placeHolderDecorator |
| 32 | 36 | } |
| 33 | 37 | |
| 39 | 43 | return decorators |
| 40 | 44 | } |
| 41 | 45 | |
| 46 | func (md *MergeDecorator) Sync() (chan int, bool) { | |
| 47 | return md.wc.Sync() | |
| 48 | } | |
| 49 | ||
| 42 | 50 | func (d *MergeDecorator) Decor(st *Statistics) string { |
| 43 | msg := d.decorator.Decor(st) | |
| 51 | msg := d.Decorator.Decor(st) | |
| 44 | 52 | msgLen := utf8.RuneCountInString(msg) |
| 45 | 53 | pWidth := msgLen / (len(d.placeHolders) + 1) |
| 46 | 54 | mod := msgLen % (len(d.placeHolders) + 1) |
| 47 | d.wsync <- pWidth + mod | |
| 55 | d.wc.wsync <- pWidth + mod | |
| 48 | 56 | for _, ph := range d.placeHolders { |
| 49 | 57 | ph.wsync <- pWidth |
| 50 | 58 | } |
| 51 | // fmt.Fprintln(os.Stderr, "all sent") | |
| 52 | max := <-d.wsync | |
| 59 | max := <-d.wc.wsync | |
| 53 | 60 | for _, ph := range d.placeHolders { |
| 54 | 61 | max += <-ph.wsync |
| 55 | 62 | } |
| 56 | if (d.C & DextraSpace) != 0 { | |
| 63 | if (d.wc.C & DextraSpace) != 0 { | |
| 57 | 64 | max++ |
| 58 | 65 | } |
| 59 | return fmt.Sprintf(fmt.Sprintf(d.format, max), msg) | |
| 66 | return fmt.Sprintf(fmt.Sprintf(d.wc.format, max), msg) | |
| 60 | 67 | } |
| 61 | 68 | |
| 62 | 69 | type placeHolderDecorator struct { |