зеркало из https://github.com/mozilla/mig.git
94 строки
1.6 KiB
Go
94 строки
1.6 KiB
Go
// +build linux darwin freebsd netbsd openbsd solaris dragonfly
|
|
|
|
package pb
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// Create and start new pool with given bars
|
|
// You need call pool.Stop() after work
|
|
func StartPool(pbs ...*ProgressBar) (pool *Pool, err error) {
|
|
pool = new(Pool)
|
|
if err = pool.start(); err != nil {
|
|
return
|
|
}
|
|
pool.add(pbs...)
|
|
return
|
|
}
|
|
|
|
type Pool struct {
|
|
RefreshRate time.Duration
|
|
bars []*ProgressBar
|
|
quit chan int
|
|
finishOnce sync.Once
|
|
}
|
|
|
|
func (p *Pool) add(pbs ...*ProgressBar) {
|
|
for _, bar := range pbs {
|
|
bar.ManualUpdate = true
|
|
bar.NotPrint = true
|
|
bar.Start()
|
|
p.bars = append(p.bars, bar)
|
|
}
|
|
}
|
|
|
|
func (p *Pool) start() (err error) {
|
|
p.RefreshRate = DefaultRefreshRate
|
|
quit, err := lockEcho()
|
|
if err != nil {
|
|
return
|
|
}
|
|
p.quit = make(chan int)
|
|
go p.writer(quit)
|
|
return
|
|
}
|
|
|
|
func (p *Pool) writer(finish chan int) {
|
|
var first = true
|
|
for {
|
|
select {
|
|
case <-time.After(p.RefreshRate):
|
|
if p.print(first) {
|
|
p.print(false)
|
|
finish <- 1
|
|
return
|
|
}
|
|
first = false
|
|
case <-p.quit:
|
|
finish <- 1
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func (p *Pool) print(first bool) bool {
|
|
var out string
|
|
if !first {
|
|
out = fmt.Sprintf("\033[%dA", len(p.bars))
|
|
}
|
|
isFinished := true
|
|
for _, bar := range p.bars {
|
|
if !bar.isFinish {
|
|
isFinished = false
|
|
}
|
|
bar.Update()
|
|
out += fmt.Sprintf("\r%s\n", bar.String())
|
|
}
|
|
fmt.Print(out)
|
|
return isFinished
|
|
}
|
|
|
|
// Restore terminal state and close pool
|
|
func (p *Pool) Stop() error {
|
|
// Wait until one final refresh has passed.
|
|
time.Sleep(p.RefreshRate)
|
|
|
|
p.finishOnce.Do(func() {
|
|
close(p.quit)
|
|
})
|
|
return unlockEcho()
|
|
}
|