| 0 | 0 |
package mpb
|
| 1 | 1 |
|
| 2 | 2 |
import (
|
|
3 |
"fmt"
|
| 3 | 4 |
"io"
|
| 4 | 5 |
"math"
|
|
6 |
"os"
|
| 5 | 7 |
"sync"
|
| 6 | 8 |
"time"
|
| 7 | 9 |
"unicode/utf8"
|
|
| 20 | 22 |
|
| 21 | 23 |
// Bar represents a progress Bar
|
| 22 | 24 |
type Bar struct {
|
| 23 | |
stateReqCh chan state
|
| 24 | |
incrCh chan incrReq
|
| 25 | |
dCommandCh chan *dCommandData
|
|
25 |
stateReqCh chan state
|
|
26 |
incrCh chan incrReq
|
|
27 |
// dCommandCh chan *dCommandData
|
| 26 | 28 |
flushedCh chan struct{}
|
| 27 | 29 |
removeReqCh chan struct{}
|
| 28 | 30 |
completedCh chan struct{}
|
|
| 83 | 85 |
|
| 84 | 86 |
func newBar(id int, total int64, wg *sync.WaitGroup, conf *userConf) *Bar {
|
| 85 | 87 |
b := &Bar{
|
| 86 | |
width: conf.width,
|
| 87 | |
stateReqCh: make(chan state),
|
| 88 | |
incrCh: make(chan incrReq),
|
| 89 | |
dCommandCh: make(chan *dCommandData),
|
|
88 |
width: conf.width,
|
|
89 |
stateReqCh: make(chan state),
|
|
90 |
incrCh: make(chan incrReq),
|
|
91 |
// dCommandCh: make(chan *dCommandData),
|
| 90 | 92 |
flushedCh: make(chan struct{}),
|
| 91 | 93 |
removeReqCh: make(chan struct{}),
|
| 92 | 94 |
completedCh: make(chan struct{}),
|
|
| 113 | 115 |
|
| 114 | 116 |
// SetWidth overrides width of individual bar
|
| 115 | 117 |
func (b *Bar) SetWidth(n int) *Bar {
|
| 116 | |
if n < 2 || isClosed(b.done) {
|
|
118 |
if n < 2 {
|
| 117 | 119 |
return b
|
| 118 | 120 |
}
|
| 119 | |
s := <-b.stateReqCh
|
| 120 | |
s.width = n
|
| 121 | |
b.stateReqCh <- s
|
|
121 |
b.updateState(func(s *state) {
|
|
122 |
s.width = n
|
|
123 |
})
|
| 122 | 124 |
return b
|
| 123 | 125 |
}
|
| 124 | 126 |
|
| 125 | 127 |
// TrimLeftSpace removes space befor LeftEnd charater
|
| 126 | 128 |
func (b *Bar) TrimLeftSpace() *Bar {
|
| 127 | |
if isClosed(b.done) {
|
| 128 | |
return b
|
| 129 | |
}
|
| 130 | |
// b.trimLeftCh <- true
|
| 131 | |
s := <-b.stateReqCh
|
| 132 | |
s.trimLeftSpace = true
|
| 133 | |
b.stateReqCh <- s
|
|
129 |
b.updateState(func(s *state) {
|
|
130 |
s.trimLeftSpace = true
|
|
131 |
})
|
| 134 | 132 |
return b
|
| 135 | 133 |
}
|
| 136 | 134 |
|
| 137 | 135 |
// TrimRightSpace removes space after RightEnd charater
|
| 138 | 136 |
func (b *Bar) TrimRightSpace() *Bar {
|
| 139 | |
if isClosed(b.done) {
|
| 140 | |
return b
|
| 141 | |
}
|
| 142 | |
// b.trimRightCh <- true
|
| 143 | |
s := <-b.stateReqCh
|
| 144 | |
s.trimRightSpace = true
|
| 145 | |
b.stateReqCh <- s
|
|
137 |
b.updateState(func(s *state) {
|
|
138 |
s.trimRightSpace = true
|
|
139 |
})
|
| 146 | 140 |
return b
|
| 147 | 141 |
}
|
| 148 | 142 |
|
| 149 | 143 |
// Format overrides format of individual bar
|
| 150 | 144 |
func (b *Bar) Format(format string) *Bar {
|
| 151 | |
if utf8.RuneCountInString(format) != numFmtRunes || isClosed(b.done) {
|
|
145 |
if utf8.RuneCountInString(format) != numFmtRunes {
|
| 152 | 146 |
return b
|
| 153 | 147 |
}
|
| 154 | |
s := <-b.stateReqCh
|
| 155 | |
s.updateFormat(format)
|
| 156 | |
b.stateReqCh <- s
|
|
148 |
b.updateState(func(s *state) {
|
|
149 |
s.updateFormat(format)
|
|
150 |
})
|
| 157 | 151 |
return b
|
| 158 | 152 |
}
|
| 159 | 153 |
|
|
| 161 | 155 |
// Defaults to 0.25
|
| 162 | 156 |
// Normally you shouldn't touch this
|
| 163 | 157 |
func (b *Bar) SetEtaAlpha(a float64) *Bar {
|
| 164 | |
if isClosed(b.done) {
|
| 165 | |
return b
|
| 166 | |
}
|
| 167 | |
s := <-b.stateReqCh
|
| 168 | |
s.etaAlpha = a
|
| 169 | |
b.stateReqCh <- s
|
| 170 | |
return b
|
|
158 |
b.updateState(func(s *state) {
|
|
159 |
s.etaAlpha = a
|
|
160 |
})
|
|
161 |
return b
|
|
162 |
}
|
|
163 |
|
|
164 |
// PrependFunc prepends DecoratorFunc
|
|
165 |
func (b *Bar) PrependFunc(f DecoratorFunc) *Bar {
|
|
166 |
b.updateState(func(s *state) {
|
|
167 |
s.prependFuncs = append(s.prependFuncs, f)
|
|
168 |
})
|
|
169 |
return b
|
|
170 |
}
|
|
171 |
|
|
172 |
// AppendFunc appends DecoratorFunc
|
|
173 |
func (b *Bar) AppendFunc(f DecoratorFunc) *Bar {
|
|
174 |
b.updateState(func(s *state) {
|
|
175 |
s.appendFuncs = append(s.appendFuncs, f)
|
|
176 |
})
|
|
177 |
return b
|
|
178 |
}
|
|
179 |
|
|
180 |
// RemoveAllPrependers removes all prepend functions
|
|
181 |
func (b *Bar) RemoveAllPrependers() {
|
|
182 |
b.updateState(func(s *state) {
|
|
183 |
s.prependFuncs = nil
|
|
184 |
})
|
|
185 |
}
|
|
186 |
|
|
187 |
// RemoveAllAppenders removes all append functions
|
|
188 |
func (b *Bar) RemoveAllAppenders() {
|
|
189 |
b.updateState(func(s *state) {
|
|
190 |
s.appendFuncs = nil
|
|
191 |
})
|
| 171 | 192 |
}
|
| 172 | 193 |
|
| 173 | 194 |
// ProxyReader wrapper for io operations, like io.Copy
|
|
| 228 | 249 |
// Can be used as condition in for loop
|
| 229 | 250 |
func (b *Bar) InProgress() bool {
|
| 230 | 251 |
return !isClosed(b.done)
|
| 231 | |
}
|
| 232 | |
|
| 233 | |
// PrependFunc prepends DecoratorFunc
|
| 234 | |
func (b *Bar) PrependFunc(f DecoratorFunc) *Bar {
|
| 235 | |
if isClosed(b.done) {
|
| 236 | |
return b
|
| 237 | |
}
|
| 238 | |
b.dCommandCh <- &dCommandData{dPrepend, f}
|
| 239 | |
return b
|
| 240 | |
}
|
| 241 | |
|
| 242 | |
// RemoveAllPrependers removes all prepend functions
|
| 243 | |
func (b *Bar) RemoveAllPrependers() {
|
| 244 | |
if isClosed(b.done) {
|
| 245 | |
return
|
| 246 | |
}
|
| 247 | |
b.dCommandCh <- &dCommandData{dPrependZero, nil}
|
| 248 | |
}
|
| 249 | |
|
| 250 | |
// AppendFunc appends DecoratorFunc
|
| 251 | |
func (b *Bar) AppendFunc(f DecoratorFunc) *Bar {
|
| 252 | |
if isClosed(b.done) {
|
| 253 | |
return b
|
| 254 | |
}
|
| 255 | |
b.dCommandCh <- &dCommandData{dAppend, f}
|
| 256 | |
return b
|
| 257 | |
}
|
| 258 | |
|
| 259 | |
// RemoveAllAppenders removes all append functions
|
| 260 | |
func (b *Bar) RemoveAllAppenders() {
|
| 261 | |
if isClosed(b.done) {
|
| 262 | |
return
|
| 263 | |
}
|
| 264 | |
b.dCommandCh <- &dCommandData{dAppendZero, nil}
|
| 265 | 252 |
}
|
| 266 | 253 |
|
| 267 | 254 |
// Completed signals to the bar, that process has been completed.
|
|
| 275 | 262 |
}
|
| 276 | 263 |
}
|
| 277 | 264 |
|
|
265 |
func (b *Bar) flushed() {
|
|
266 |
select {
|
|
267 |
case b.flushedCh <- struct{}{}:
|
|
268 |
case <-b.done:
|
|
269 |
fmt.Fprintf(os.Stderr, "flushedCh abort: %d\n", b.state.id)
|
|
270 |
return
|
|
271 |
}
|
|
272 |
}
|
|
273 |
|
|
274 |
func (b *Bar) remove() {
|
|
275 |
select {
|
|
276 |
case b.removeReqCh <- struct{}{}:
|
|
277 |
case <-b.done:
|
|
278 |
return
|
|
279 |
}
|
|
280 |
}
|
|
281 |
|
| 278 | 282 |
func (b *Bar) getState() state {
|
| 279 | 283 |
select {
|
| 280 | 284 |
case s := <-b.stateReqCh:
|
|
| 284 | 288 |
}
|
| 285 | 289 |
}
|
| 286 | 290 |
|
|
291 |
func (b *Bar) updateState(cb func(s *state)) {
|
|
292 |
s := b.getState()
|
|
293 |
cb(&s)
|
|
294 |
select {
|
|
295 |
case b.stateReqCh <- s:
|
|
296 |
case <-b.done:
|
|
297 |
return
|
|
298 |
}
|
|
299 |
}
|
|
300 |
|
| 287 | 301 |
func (b *Bar) server(wg *sync.WaitGroup, s state) {
|
| 288 | 302 |
var incrStartTime time.Time
|
| 289 | 303 |
|
| 290 | 304 |
defer func() {
|
| 291 | 305 |
b.state = s
|
| 292 | 306 |
wg.Done()
|
| 293 | |
// fmt.Printf("Exited bar %d\n", s.id)
|
| 294 | 307 |
close(b.done)
|
|
308 |
fmt.Fprintf(os.Stderr, "Exited bar %d\n", s.id)
|
| 295 | 309 |
}()
|
| 296 | 310 |
|
| 297 | 311 |
for {
|
|
| 317 | 331 |
s.current = n
|
| 318 | 332 |
s.refill = r.refill
|
| 319 | 333 |
incrStartTime = time.Now()
|
| 320 | |
case data := <-b.dCommandCh:
|
| 321 | |
switch data.action {
|
| 322 | |
case dAppend:
|
| 323 | |
s.appendFuncs = append(s.appendFuncs, data.f)
|
| 324 | |
case dAppendZero:
|
| 325 | |
s.appendFuncs = nil
|
| 326 | |
case dPrepend:
|
| 327 | |
s.prependFuncs = append(s.prependFuncs, data.f)
|
| 328 | |
case dPrependZero:
|
| 329 | |
s.prependFuncs = nil
|
| 330 | |
}
|
| 331 | 334 |
case <-b.flushedCh:
|
| 332 | 335 |
if s.completed {
|
|
336 |
fmt.Fprintln(os.Stderr, "completed")
|
| 333 | 337 |
return
|
| 334 | 338 |
}
|
| 335 | 339 |
case <-b.completedCh:
|
|
| 340 | 344 |
case <-b.cancel:
|
| 341 | 345 |
return
|
| 342 | 346 |
}
|
| 343 | |
}
|
| 344 | |
}
|
| 345 | |
|
| 346 | |
func (b *Bar) flushed() {
|
| 347 | |
select {
|
| 348 | |
case b.flushedCh <- struct{}{}:
|
| 349 | |
case <-b.done:
|
| 350 | |
return
|
| 351 | |
}
|
| 352 | |
}
|
| 353 | |
|
| 354 | |
func (b *Bar) remove() {
|
| 355 | |
select {
|
| 356 | |
case b.removeReqCh <- struct{}{}:
|
| 357 | |
case <-b.done:
|
| 358 | |
return
|
| 359 | 347 |
}
|
| 360 | 348 |
}
|
| 361 | 349 |
|