2020-07-04 21:00:11 +00:00
|
|
|
package progress
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"github.com/logrusorgru/aurora"
|
|
|
|
"github.com/vbauerster/mpb/v5"
|
|
|
|
"github.com/vbauerster/mpb/v5/cwriter"
|
|
|
|
"github.com/vbauerster/mpb/v5/decor"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"regexp"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Progress struct {
|
|
|
|
progress *mpb.Progress
|
2020-07-08 21:13:53 +00:00
|
|
|
progress_stdout *mpb.Progress
|
2020-07-05 21:38:58 +00:00
|
|
|
bar *mpb.Bar
|
2020-07-07 20:39:43 +00:00
|
|
|
total int64
|
|
|
|
initialTotal int64
|
2020-07-04 21:00:11 +00:00
|
|
|
captureData *captureData
|
|
|
|
termWidth int
|
2020-07-08 21:13:05 +00:00
|
|
|
mutex *sync.Mutex
|
2020-07-04 21:00:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewProgress(group *sync.WaitGroup) *Progress {
|
|
|
|
w := cwriter.New(os.Stdout)
|
|
|
|
tw, err := w.GetWidth()
|
|
|
|
if err != nil {
|
|
|
|
panic("Couldn't determine available terminal width.")
|
|
|
|
}
|
|
|
|
|
|
|
|
p := &Progress{
|
|
|
|
progress: mpb.New(
|
|
|
|
mpb.WithWaitGroup(group),
|
|
|
|
mpb.WithOutput(os.Stderr),
|
|
|
|
mpb.PopCompletedMode(),
|
|
|
|
),
|
2020-07-08 21:13:53 +00:00
|
|
|
|
|
|
|
progress_stdout: mpb.New(
|
|
|
|
mpb.WithWaitGroup(group),
|
|
|
|
mpb.WithOutput(os.Stdout),
|
|
|
|
//mpb.PopCompletedMode(),
|
|
|
|
),
|
|
|
|
|
2020-07-04 21:00:11 +00:00
|
|
|
termWidth: tw,
|
2020-07-08 21:13:05 +00:00
|
|
|
mutex: &sync.Mutex{},
|
2020-07-04 21:00:11 +00:00
|
|
|
}
|
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
2020-07-05 21:38:58 +00:00
|
|
|
func (p *Progress) SetupProgressBar(name string, total int64) *mpb.Bar {
|
2020-07-05 15:22:21 +00:00
|
|
|
barname := "[" + aurora.Green(name).String() + "]"
|
2020-07-05 21:38:58 +00:00
|
|
|
bar := p.progress.AddBar(
|
2020-07-04 21:00:11 +00:00
|
|
|
total,
|
|
|
|
mpb.BarNoPop(),
|
2020-07-05 18:11:53 +00:00
|
|
|
mpb.BarRemoveOnComplete(),
|
2020-07-04 21:00:11 +00:00
|
|
|
mpb.PrependDecorators(
|
2020-07-05 15:22:21 +00:00
|
|
|
decor.Name(barname),
|
2020-07-04 21:00:11 +00:00
|
|
|
decor.CountersNoUnit(aurora.Blue(" %d/%d").String()),
|
|
|
|
decor.NewPercentage(aurora.Bold("%d").String(), decor.WCSyncSpace),
|
|
|
|
),
|
|
|
|
mpb.AppendDecorators(
|
2020-07-05 20:46:34 +00:00
|
|
|
decor.AverageSpeed(0, aurora.Yellow("%.2f req/s ").String()),
|
2020-07-04 21:00:11 +00:00
|
|
|
decor.OnComplete(
|
2020-07-05 20:46:34 +00:00
|
|
|
decor.AverageETA(decor.ET_STYLE_GO), aurora.Bold("done!").String(),
|
2020-07-04 21:00:11 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
)
|
2020-07-05 21:38:58 +00:00
|
|
|
|
|
|
|
p.bar = bar
|
2020-07-07 20:39:43 +00:00
|
|
|
p.total = total
|
|
|
|
p.initialTotal = total
|
2020-07-05 21:38:58 +00:00
|
|
|
return bar
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Progress) Update() {
|
|
|
|
p.bar.Increment()
|
2020-07-04 21:00:11 +00:00
|
|
|
}
|
|
|
|
|
2020-07-07 20:39:43 +00:00
|
|
|
func (p *Progress) Abort(remaining int64) {
|
|
|
|
p.total -= remaining
|
|
|
|
p.bar.SetTotal(p.total, false)
|
2020-07-05 22:09:58 +00:00
|
|
|
}
|
|
|
|
|
2020-07-04 21:00:11 +00:00
|
|
|
func (p *Progress) Wait() {
|
2020-07-07 20:39:43 +00:00
|
|
|
if p.initialTotal != p.total {
|
|
|
|
p.bar.SetTotal(p.total, true)
|
|
|
|
}
|
|
|
|
|
2020-07-04 21:00:11 +00:00
|
|
|
p.progress.Wait()
|
2020-07-08 21:13:53 +00:00
|
|
|
p.progress_stdout.Wait()
|
2020-07-04 21:00:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
func (p *Progress) StartStdCapture() {
|
2020-07-08 21:13:05 +00:00
|
|
|
p.mutex.Lock()
|
2020-07-04 21:00:11 +00:00
|
|
|
p.captureData = startStdCapture()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Progress) StopStdCaptureAndShow() {
|
|
|
|
stopStdCapture(p.captureData)
|
2020-07-08 21:13:53 +00:00
|
|
|
|
|
|
|
// stdout
|
|
|
|
for _, captured := range p.captureData.DataStdOut {
|
|
|
|
var r = regexp.MustCompile("(.{" + strconv.Itoa(p.termWidth) + "})")
|
|
|
|
multiline := r.ReplaceAllString(captured, "$1\n")
|
|
|
|
arr := strings.Split(multiline, "\n")
|
|
|
|
|
|
|
|
for _, msg := range arr {
|
|
|
|
p.progress_stdout.Add(0, makeLogBar(msg)).SetTotal(0, true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// stderr
|
|
|
|
for _, captured := range p.captureData.DataStdErr {
|
2020-07-04 21:00:11 +00:00
|
|
|
var r = regexp.MustCompile("(.{" + strconv.Itoa(p.termWidth) + "})")
|
|
|
|
multiline := r.ReplaceAllString(captured, "$1\n")
|
|
|
|
arr := strings.Split(multiline, "\n")
|
|
|
|
|
|
|
|
for _, msg := range arr {
|
|
|
|
p.progress.Add(0, makeLogBar(msg)).SetTotal(0, true)
|
|
|
|
}
|
|
|
|
}
|
2020-07-08 21:13:53 +00:00
|
|
|
|
2020-07-08 21:13:05 +00:00
|
|
|
p.mutex.Unlock()
|
2020-07-04 21:00:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func makeLogBar(msg string) mpb.BarFiller {
|
|
|
|
return mpb.BarFillerFunc(func(w io.Writer, _ int, st decor.Statistics) {
|
|
|
|
fmt.Fprintf(w, msg)
|
|
|
|
})
|
|
|
|
}
|