Codebase list golang-github-vbauerster-mpb / b67d71d
sync width Vladimir Bauer 9 years ago
3 changed file(s) with 85 addition(s) and 23 deletion(s). Raw diff Collapse all Expand all
249249 ch := make(chan state, 1)
250250 b.stateReqCh <- ch
251251 return <-ch
252 }
253
254 func (b *Bar) bytes(termWidth int) []byte {
255 s := b.getState()
256 return draw(&s, termWidth)
257252 }
258253
259254 func (b *Bar) server(ctx context.Context, wg *sync.WaitGroup, id int, total int64, width int, format string) {
356351 }
357352 }
358353
359 func draw(s *state, termWidth int) []byte {
354 func (b *Bar) bytes(termWidth int, ws *widthSync) []byte {
355 s := b.getState()
356 return draw(&s, termWidth, ws)
357 }
358
359 func draw(s *state, termWidth int, ws *widthSync) []byte {
360360 if termWidth <= 0 {
361361 termWidth = s.width
362362 }
366366 // render append functions to the right of the bar
367367 var appendBlock []byte
368368 for _, f := range s.appendFuncs {
369 appendBlock = append(appendBlock, []byte(f(stat))...)
369 appendBlock = append(appendBlock, []byte(f(stat, nil, nil))...)
370370 }
371371
372372 // render prepend functions to the left of the bar
373373 var prependBlock []byte
374 for _, f := range s.prependFuncs {
375 prependBlock = append(prependBlock, []byte(f(stat))...)
374 for i, f := range s.prependFuncs {
375 prependBlock = append(prependBlock, []byte(f(stat, ws.listen[i], ws.result[i]))...)
376376 }
377377
378378 prependCount := utf8.RuneCount(prependBlock)
1515 )
1616
1717 // DecoratorFunc is a function that can be prepended and appended to the progress bar
18 type DecoratorFunc func(s *Statistics) string
18 type DecoratorFunc func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string
1919
2020 type decorator struct {
2121 kind decoratorFuncType
2424
2525 func (b *Bar) PrependName(name string, padding int) *Bar {
2626 layout := "%" + strconv.Itoa(padding) + "s"
27 b.PrependFunc(func(s *Statistics) string {
27 b.PrependFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string {
2828 return fmt.Sprintf(layout, name)
2929 })
3030 return b
3232
3333 func (b *Bar) PrependCounters(unit Units, padding int) *Bar {
3434 layout := "%" + strconv.Itoa(padding) + "s"
35 b.PrependFunc(func(s *Statistics) string {
35 b.PrependFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string {
3636 current := Format(s.Current).To(unit)
3737 total := Format(s.Total).To(unit)
3838 str := fmt.Sprintf("%s / %s", current, total)
4343
4444 func (b *Bar) PrependETA(padding int) *Bar {
4545 layout := "ETA%" + strconv.Itoa(padding) + "s"
46 b.PrependFunc(func(s *Statistics) string {
46 b.PrependFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string {
4747 return fmt.Sprintf(layout, time.Duration(s.Eta().Seconds())*time.Second)
4848 })
4949 return b
5151
5252 func (b *Bar) AppendETA(padding int) *Bar {
5353 layout := "ETA %" + strconv.Itoa(padding) + "s"
54 b.AppendFunc(func(s *Statistics) string {
54 b.AppendFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string {
5555 return fmt.Sprintf(layout, time.Duration(s.Eta().Seconds())*time.Second)
5656 })
5757 return b
5959
6060 func (b *Bar) PrependElapsed(padding int) *Bar {
6161 layout := "%" + strconv.Itoa(padding) + "s"
62 b.PrependFunc(func(s *Statistics) string {
62 b.PrependFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string {
6363 return fmt.Sprintf(layout, time.Duration(s.TimeElapsed.Seconds())*time.Second)
6464 })
6565 return b
6666 }
6767
6868 func (b *Bar) AppendElapsed() *Bar {
69 b.AppendFunc(func(s *Statistics) string {
69 b.AppendFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string {
7070 return fmt.Sprint(time.Duration(s.TimeElapsed.Seconds()) * time.Second)
7171 })
7272 return b
7373 }
7474
7575 func (b *Bar) AppendPercentage() *Bar {
76 b.AppendFunc(func(s *Statistics) string {
76 b.AppendFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string {
7777 completed := percentage(s.Total, s.Current, 100)
7878 return fmt.Sprintf("%3d %%", completed)
7979 })
8282
8383 func (b *Bar) PrependPercentage(padding int) *Bar {
8484 layout := "%" + strconv.Itoa(padding) + "d %%"
85 b.PrependFunc(func(s *Statistics) string {
85 b.PrependFunc(func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string {
8686 completed := percentage(s.Total, s.Current, 100)
8787 return fmt.Sprintf(layout, completed)
8888 })
176176 if isClosed(p.done) {
177177 panic(ErrCallAfterStop)
178178 }
179 respCh := make(chan int)
179 respCh := make(chan int, 1)
180180 p.barCountReqCh <- respCh
181181 return <-respCh
182182 }
198198 return
199199 }
200200 close(p.operationCh)
201 }
202
203 type widthSync struct {
204 listen []chan int
205 result []chan int
201206 }
202207
203208 // server monitors underlying channels and renders any progress bars
218223 }
219224 wg.Done()
220225 }
226 var numPrependers int
227 // var numAppenders int
221228 for {
222229 select {
223230 case w := <-p.outChangeReqCh:
243250 }
244251 op.result <- ok
245252 }
253 if len(bars) > 0 {
254 numPrependers = len(bars[0].GetPrependers())
255 // numAppenders = len(bars[0].GetAppenders())
256 }
246257 case respCh := <-p.barCountReqCh:
247258 respCh <- len(bars)
248259 case beforeRender = <-p.brCh:
255266
256267 if beforeRender != nil {
257268 beforeRender(bars)
269 }
270
271 prepWidthSync := &widthSync{
272 listen: make([]chan int, numPrependers),
273 result: make([]chan int, numPrependers),
274 }
275 for i := 0; i < numPrependers; i++ {
276 prepWidthSync.listen[i] = make(chan int, numBars)
277 prepWidthSync.result[i] = make(chan int, numBars)
278 }
279 stopWidthListen := make(chan struct{})
280 for i, listenCh := range prepWidthSync.listen {
281 go func(listenCh <-chan int, resultCh chan<- int) {
282 widths := make([]int, 0, numBars)
283 loop:
284 for {
285 select {
286 case w := <-listenCh:
287 widths = append(widths, w)
288 if len(widths) == numBars {
289 break loop
290 }
291 case <-stopWidthListen:
292 return
293 }
294 }
295 result := max(widths)
296 for i := 0; i < numBars; i++ {
297 resultCh <- result
298 }
299 // close(resultCh)
300 }(listenCh, prepWidthSync.result[i])
258301 }
259302
260303 width, _, _ := cwriter.GetTermSize()
264307 for i := 0; i < numBars; i++ {
265308 go func() {
266309 defer recoverIfPanic()
267 drawer(ibars, ibbCh)
310 drawer(ibars, ibbCh, prepWidthSync)
268311 }()
269312 }
270313 go func() {
271314 wg.Wait()
272315 close(ibbCh)
316 close(stopWidthListen)
317 for _, ch := range prepWidthSync.result {
318 close(ch)
319 }
320 for _, ch := range prepWidthSync.listen {
321 close(ch)
322 }
273323 }()
274324
275325 m := make(map[int][]byte, len(bars))
276 for r := range ibbCh {
277 m[r.index] = r.buf
326 for ibb := range ibbCh {
327 m[ibb.index] = ibb.buf
278328 }
279329 for i := 0; i < len(bars); i++ {
280330 cw.Write(m[i])
296346
297347 func drawer(ibars <-chan indexedBar, ibbCh chan<- indexedBarBuffer) {
298348 for b := range ibars {
299 buf := b.bar.bytes(b.termWidth)
349 buf := b.bar.bytes(b.termWidth, ws)
300350 buf = append(buf, '\n')
301351 ibbCh <- indexedBarBuffer{b.index, buf}
302352 }
323373 return false
324374 }
325375 }
376
377 func max(slice []int) int {
378 max := slice[0]
379
380 for i := 1; i < len(slice); i++ {
381 if slice[i] > max {
382 max = slice[i]
383 }
384 }
385
386 return max
387 }