decorator struct
Vladimir Bauer
9 years ago
| 24 | 24 | Width = 70 |
| 25 | 25 | ) |
| 26 | 26 | |
| 27 | // DecoratorFunc is a function that can be prepended and appended to the progress bar | |
| 28 | type DecoratorFunc func(s *Statistics) string | |
| 29 | ||
| 30 | type decoratorFuncType uint | |
| 31 | ||
| 32 | const ( | |
| 33 | decoratorAppend decoratorFuncType = iota | |
| 34 | decoratorPrepend | |
| 35 | ) | |
| 36 | ||
| 37 | type decorator struct { | |
| 38 | kind decoratorFuncType | |
| 39 | f DecoratorFunc | |
| 40 | } | |
| 41 | ||
| 27 | 42 | // Bar represents a progress bar |
| 28 | 43 | type Bar struct { |
| 29 | 44 | // total of the total for the progress bar |
| 53 | 68 | |
| 54 | 69 | redrawRequestCh chan *redrawRequest |
| 55 | 70 | |
| 56 | decoratorFuncCh chan DecoratorFunc | |
| 71 | decoratorCh chan *decorator | |
| 57 | 72 | |
| 58 | 73 | timePerItemEstimate time.Duration |
| 59 | 74 | } |
| 60 | ||
| 61 | // DecoratorFunc is a function that can be prepended and appended to the progress bar | |
| 62 | type DecoratorFunc func(s *Statistics) string | |
| 63 | 75 | |
| 64 | 76 | type Statistics struct { |
| 65 | 77 | Total, Completed int |
| 83 | 95 | Empty: Empty, |
| 84 | 96 | currentIncrCh: make(chan int), |
| 85 | 97 | redrawRequestCh: make(chan *redrawRequest), |
| 86 | decoratorFuncCh: make(chan DecoratorFunc), | |
| 98 | decoratorCh: make(chan *decorator), | |
| 87 | 99 | } |
| 88 | 100 | go b.server() |
| 89 | 101 | return b |
| 94 | 106 | } |
| 95 | 107 | |
| 96 | 108 | func (b *Bar) AppendFunc(f DecoratorFunc) *Bar { |
| 97 | b.decoratorFuncCh <- f | |
| 109 | b.decoratorCh <- &decorator{decoratorAppend, f} | |
| 98 | 110 | return b |
| 99 | 111 | } |
| 100 | 112 | |
| 116 | 128 | func (b *Bar) server() { |
| 117 | 129 | var current int |
| 118 | 130 | blockStartTime := time.Now() |
| 119 | buf := make([]byte, b.Width) | |
| 131 | buf := make([]byte, b.Width, b.Width+9) | |
| 120 | 132 | var appendFuncs []DecoratorFunc |
| 121 | // var prependFuncs []DecoratorFunc | |
| 133 | var prependFuncs []DecoratorFunc | |
| 122 | 134 | for { |
| 123 | 135 | select { |
| 124 | 136 | case i := <-b.currentIncrCh: |
| 129 | 141 | b.updateTimePerItemEstimate(i, blockStartTime) |
| 130 | 142 | current = n |
| 131 | 143 | blockStartTime = time.Now() |
| 132 | case f := <-b.decoratorFuncCh: | |
| 133 | appendFuncs = append(appendFuncs, f) | |
| 144 | case d := <-b.decoratorCh: | |
| 145 | switch d.kind { | |
| 146 | case decoratorAppend: | |
| 147 | appendFuncs = append(appendFuncs, d.f) | |
| 148 | case decoratorPrepend: | |
| 149 | prependFuncs = append(prependFuncs, d.f) | |
| 150 | } | |
| 134 | 151 | case r := <-b.redrawRequestCh: |
| 135 | 152 | r.bufch <- b.draw(buf, current, appendFuncs) |
| 136 | 153 | } |
| 138 | 155 | } |
| 139 | 156 | |
| 140 | 157 | func (b *Bar) draw(buf []byte, current int, appendFuncs []DecoratorFunc) []byte { |
| 141 | // eta := time.Duration(b.total-current) * b.timePerItemEstimate | |
| 142 | 158 | completedWidth := current * b.Width / b.total |
| 143 | 159 | |
| 144 | 160 | for i := 0; i < completedWidth; i++ { |