fix(deps): update module github.com/schollz/progressbar/v3 to v3.17.0 (#14720)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
pull/14721/head
renovate[bot] 7 months ago committed by GitHub
parent e6cf42396f
commit 4419d0f33e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      go.mod
  2. 11
      go.sum
  3. 334
      vendor/github.com/schollz/progressbar/v3/progressbar.go
  4. 4
      vendor/modules.txt

@ -137,7 +137,7 @@ require (
github.com/prometheus/alertmanager v0.27.0
github.com/prometheus/common/sigv4 v0.1.0
github.com/richardartoul/molecule v1.0.0
github.com/schollz/progressbar/v3 v3.14.6
github.com/schollz/progressbar/v3 v3.17.0
github.com/shirou/gopsutil/v4 v4.24.10
github.com/thanos-io/objstore v0.0.0-20241015070247-5f04b8b0b52a
github.com/twmb/franz-go v1.17.1

@ -442,6 +442,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM=
github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY=
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs=
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
@ -1303,7 +1305,6 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
github.com/kardianos/service v1.0.0/go.mod h1:8CzDhVuCuugtsHyZoTvsOBuvonN/UDBvl0kH+BUxvbo=
github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
@ -1408,6 +1409,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mdlayher/apcupsd v0.0.0-20200608131503-2bf01da7bf1b/go.mod h1:WYK/Z/aXq9cbMFIL5ihcA4sX/r/3/WCas/Qvs/2fXcA=
@ -1710,8 +1713,8 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.29 h1:BkTk4gynLjguayxrYxZoMZjBnAOh7ntQvUkOFmkMqPU=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.29/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
github.com/schollz/progressbar/v3 v3.14.6 h1:GyjwcWBAf+GFDMLziwerKvpuS7ZF+mNTAXIB2aspiZs=
github.com/schollz/progressbar/v3 v3.14.6/go.mod h1:Nrzpuw3Nl0srLY0VlTvC4V6RL50pcEymjy6qyJAaLa0=
github.com/schollz/progressbar/v3 v3.17.0 h1:Fv+vG6O6jnJwdjCelvfyYO7sF2jaUGQVmdH4CxcZdsQ=
github.com/schollz/progressbar/v3 v3.17.0/go.mod h1:5H4fLgifX+KeQCsEJnZTOepgZLe1jFF1lpPXb68IJTA=
github.com/sean-/conswriter v0.0.0-20180208195008-f5ae3917a627/go.mod h1:7zjs06qF79/FKAJpBvFx3P8Ww4UTIMAe+lpNXDHziac=
github.com/sean-/pager v0.0.0-20180208200047-666be9bf53b5/go.mod h1:BeybITEsBEg6qbIiqJ6/Bqeq25bCLbL7YFmpaFfJDuM=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
@ -2324,7 +2327,6 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
@ -2335,7 +2337,6 @@ golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

@ -45,17 +45,20 @@ type state struct {
isAltSaucerHead bool
lastShown time.Time
startTime time.Time
startTime time.Time // time when the progress bar start working
counterTime time.Time
counterNumSinceLast int64
counterLastTenRates []float64
spinnerIdx int // the index of spinner
maxLineWidth int
currentBytes float64
finished bool
exit bool // Progress bar exit halfway
details []string // details to show,only used when detail row is set to more than 0
rendered string
}
@ -80,6 +83,9 @@ type config struct {
showIterationsPerSecond bool
showIterationsCount bool
// whether the progress bar should show the total bytes (e.g. 23/24 or 23/-, vs. just 23).
showTotalBytes bool
// whether the progress bar should show elapsed time.
// always enabled if predictTime is true.
elapsedTime bool
@ -103,6 +109,11 @@ type config struct {
// spinnerTypeOptionUsed remembers if the spinnerType was changed manually
spinnerTypeOptionUsed bool
// spinnerChangeInterval the change interval of spinner
// if set this attribute to 0, the spinner only change when renderProgressBar was called
// for example, each time when Add() was called,which will call renderProgressBar function
spinnerChangeInterval time.Duration
// spinner represents the spinner as a slice of string
spinner []string
@ -123,6 +134,9 @@ type config struct {
// showDescriptionAtLineEnd specifies whether description should be written at line end instead of line start
showDescriptionAtLineEnd bool
// specifies how many rows of details to show,default value is 0 and no details will be shown
maxDetailRow int
stdBuffer bytes.Buffer
}
@ -134,7 +148,45 @@ type Theme struct {
SaucerPadding string
BarStart string
BarEnd string
}
// BarStartFilled is used after the Bar starts filling, if set. Otherwise, it defaults to BarStart.
BarStartFilled string
// BarEndFilled is used once the Bar finishes, if set. Otherwise, it defaults to BarEnd.
BarEndFilled string
}
var (
// ThemeDefault is given by default (if not changed with OptionSetTheme), and it looks like "|████ |".
ThemeDefault = Theme{Saucer: "█", SaucerPadding: " ", BarStart: "|", BarEnd: "|"}
// ThemeASCII is a predefined Theme that uses ASCII symbols. It looks like "[===>...]".
// Configure it with OptionSetTheme(ThemeASCII).
ThemeASCII = Theme{
Saucer: "=",
SaucerHead: ">",
SaucerPadding: ".",
BarStart: "[",
BarEnd: "]",
}
// ThemeUnicode is a predefined Theme that uses Unicode characters, displaying a graphic bar.
// It looks like "" (rendering will depend on font being used).
// It requires special symbols usually found in "nerd fonts" [2], or in Fira Code [1], and other sources.
// Configure it with OptionSetTheme(ThemeUnicode).
//
// [1] https://github.com/tonsky/FiraCode
// [2] https://www.nerdfonts.com/
ThemeUnicode = Theme{
Saucer: "\uEE04", //
SaucerHead: "\uEE04", //
SaucerPadding: "\uEE01", //
BarStart: "\uEE00", //
BarStartFilled: "\uEE03", //
BarEnd: "\uEE02", //
BarEndFilled: "\uEE05", //
}
)
// Option is the type all options need to adhere to
type Option func(p *ProgressBar)
@ -146,6 +198,18 @@ func OptionSetWidth(s int) Option {
}
}
// OptionSetSpinnerChangeInterval sets the spinner change interval
// the spinner will change according to this value.
// By default, this value is 100 * time.Millisecond
// If you don't want to let this progressbar update by specified time interval
// you can set this value to zero, then the spinner will change each time rendered,
// such as when Add() or Describe() was called
func OptionSetSpinnerChangeInterval(interval time.Duration) Option {
return func(p *ProgressBar) {
p.config.spinnerChangeInterval = interval
}
}
// OptionSpinnerType sets the type of spinner used for indeterminate bars
func OptionSpinnerType(spinnerType int) Option {
return func(p *ProgressBar) {
@ -162,7 +226,8 @@ func OptionSpinnerCustom(spinner []string) Option {
}
}
// OptionSetTheme sets the elements the bar is constructed of
// OptionSetTheme sets the elements the bar is constructed with.
// There are two pre-defined themes you can use: ThemeASCII and ThemeUnicode.
func OptionSetTheme(t Theme) Option {
return func(p *ProgressBar) {
p.config.theme = t
@ -240,13 +305,20 @@ func OptionShowIts() Option {
}
}
// OptionShowElapsedOnFinish will keep the display of elapsed time on finish
// OptionShowElapsedTimeOnFinish will keep the display of elapsed time on finish.
func OptionShowElapsedTimeOnFinish() Option {
return func(p *ProgressBar) {
p.config.showElapsedTimeOnFinish = true
}
}
// OptionShowTotalBytes will keep the display of total bytes.
func OptionShowTotalBytes(flag bool) Option {
return func(p *ProgressBar) {
p.config.showTotalBytes = flag
}
}
// OptionSetItsString sets what's displayed for iterations a second. The default is "it" which would display: "it/s"
func OptionSetItsString(iterationString string) Option {
return func(p *ProgressBar) {
@ -262,7 +334,7 @@ func OptionThrottle(duration time.Duration) Option {
}
}
// OptionClearOnFinish will clear the bar once its finished
// OptionClearOnFinish will clear the bar once its finished.
func OptionClearOnFinish() Option {
return func(p *ProgressBar) {
p.config.clearOnFinish = true
@ -308,7 +380,13 @@ func OptionShowDescriptionAtLineEnd() Option {
}
}
var defaultTheme = Theme{Saucer: "█", SaucerPadding: " ", BarStart: "|", BarEnd: "|"}
// OptionSetMaxDetailRow sets the max row of details
// the row count should be less than the terminal height, otherwise it will not give you the output you want
func OptionSetMaxDetailRow(row int) Option {
return func(p *ProgressBar) {
p.config.maxDetailRow = row
}
}
// NewOptions constructs a new instance of ProgressBar, with any options you specify
func NewOptions(max int, options ...Option) *ProgressBar {
@ -318,18 +396,24 @@ func NewOptions(max int, options ...Option) *ProgressBar {
// NewOptions64 constructs a new instance of ProgressBar, with any options you specify
func NewOptions64(max int64, options ...Option) *ProgressBar {
b := ProgressBar{
state: getBasicState(),
state: state{
startTime: time.Time{},
lastShown: time.Time{},
counterTime: time.Time{},
},
config: config{
writer: os.Stdout,
theme: defaultTheme,
iterationString: "it",
width: 40,
max: max,
throttleDuration: 0 * time.Nanosecond,
elapsedTime: max == -1,
predictTime: true,
spinnerType: 9,
invisible: false,
writer: os.Stdout,
theme: ThemeDefault,
iterationString: "it",
width: 40,
max: max,
throttleDuration: 0 * time.Nanosecond,
elapsedTime: max == -1,
predictTime: true,
spinnerType: 9,
invisible: false,
spinnerChangeInterval: 100 * time.Millisecond,
showTotalBytes: true,
},
}
@ -341,11 +425,13 @@ func NewOptions64(max int64, options ...Option) *ProgressBar {
panic("invalid spinner type, must be between 0 and 75")
}
if b.config.maxDetailRow < 0 {
panic("invalid max detail row, must be greater than 0")
}
// ignoreLength if max bytes not known
if b.config.max == -1 {
b.config.ignoreLength = true
b.config.max = int64(b.config.width)
b.config.predictTime = false
b.lengthUnknown()
}
b.config.maxHumanized, b.config.maxHumanizedSuffix = humanizeBytes(float64(b.config.max),
@ -355,6 +441,27 @@ func NewOptions64(max int64, options ...Option) *ProgressBar {
b.RenderBlank()
}
// if the render time interval attribute is set
if b.config.spinnerChangeInterval != 0 && !b.config.invisible && b.config.ignoreLength {
go func() {
ticker := time.NewTicker(b.config.spinnerChangeInterval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
if b.IsFinished() {
return
}
if b.IsStarted() {
b.lock.Lock()
b.render()
b.lock.Unlock()
}
}
}
}()
}
return &b
}
@ -386,6 +493,7 @@ func DefaultBytes(maxBytes int64, description ...string) *ProgressBar {
OptionSetDescription(desc),
OptionSetWriter(os.Stderr),
OptionShowBytes(true),
OptionShowTotalBytes(true),
OptionSetWidth(10),
OptionThrottle(65*time.Millisecond),
OptionShowCount(),
@ -412,6 +520,7 @@ func DefaultBytesSilent(maxBytes int64, description ...string) *ProgressBar {
OptionSetDescription(desc),
OptionSetWriter(io.Discard),
OptionShowBytes(true),
OptionShowTotalBytes(true),
OptionSetWidth(10),
OptionThrottle(65*time.Millisecond),
OptionShowCount(),
@ -432,6 +541,7 @@ func Default(max int64, description ...string) *ProgressBar {
OptionSetDescription(desc),
OptionSetWriter(os.Stderr),
OptionSetWidth(10),
OptionShowTotalBytes(true),
OptionThrottle(65*time.Millisecond),
OptionShowCount(),
OptionShowIts(),
@ -458,6 +568,7 @@ func DefaultSilent(max int64, description ...string) *ProgressBar {
OptionSetDescription(desc),
OptionSetWriter(io.Discard),
OptionSetWidth(10),
OptionShowTotalBytes(true),
OptionThrottle(65*time.Millisecond),
OptionShowCount(),
OptionShowIts(),
@ -486,6 +597,24 @@ func (p *ProgressBar) RenderBlank() error {
return p.render()
}
// StartWithoutRender will start the progress bar without rendering it
// this method is created for the use case where you want to start the progress
// but don't want to render it immediately.
// If you want to start the progress and render it immediately, use RenderBlank instead,
// or maybe you can use Add to start it automatically, but it will make the time calculation less precise.
func (p *ProgressBar) StartWithoutRender() {
p.lock.Lock()
defer p.lock.Unlock()
if p.IsStarted() {
return
}
p.state.startTime = time.Now()
// the counterTime should be set to the current time
p.state.counterTime = time.Now()
}
// Reset will reset the clock that is used
// to calculate current time and the time left.
func (p *ProgressBar) Reset() {
@ -567,6 +696,10 @@ func (p *ProgressBar) Add64(num int64) error {
p.state.currentBytes += float64(num)
if p.state.counterTime.IsZero() {
p.state.counterTime = time.Now()
}
// reset the countdown timer every second to take rolling average
p.state.counterNumSinceLast += num
if time.Since(p.state.counterTime).Seconds() > 0.5 {
@ -596,6 +729,66 @@ func (p *ProgressBar) Add64(num int64) error {
return nil
}
// AddDetail adds a detail to the progress bar. Only used when maxDetailRow is set to a value greater than 0
func (p *ProgressBar) AddDetail(detail string) error {
if p.config.maxDetailRow == 0 {
return errors.New("maxDetailRow is set to 0, cannot add detail")
}
if p.IsFinished() {
return errors.New("cannot add detail to a finished progress bar")
}
p.lock.Lock()
defer p.lock.Unlock()
if p.state.details == nil {
// if we add a detail before the first add, it will be weird that we have detail but don't have the progress bar in the top.
// so when we add the first detail, we will render the progress bar first.
if err := p.render(); err != nil {
return err
}
}
p.state.details = append(p.state.details, detail)
if len(p.state.details) > p.config.maxDetailRow {
p.state.details = p.state.details[1:]
}
if err := p.renderDetails(); err != nil {
return err
}
return nil
}
// renderDetails renders the details of the progress bar
func (p *ProgressBar) renderDetails() error {
if p.config.invisible {
return nil
}
if p.state.finished {
return nil
}
if p.config.maxDetailRow == 0 {
return nil
}
b := strings.Builder{}
b.WriteString("\n")
// render the details row
for _, detail := range p.state.details {
b.WriteString(fmt.Sprintf("\u001B[K\r%s\n", detail))
}
// add empty lines to fill the maxDetailRow
for i := len(p.state.details); i < p.config.maxDetailRow; i++ {
b.WriteString("\u001B[K\n")
}
// move the cursor up to the start of the details row
b.WriteString(fmt.Sprintf("\u001B[%dF", p.config.maxDetailRow+1))
writeString(p.config, b.String())
return nil
}
// Clear erases the progress bar from the current line
func (p *ProgressBar) Clear() error {
return clearProgressBar(p.config, p.state)
@ -656,6 +849,7 @@ func (p *ProgressBar) ChangeMax64(newMax int64) {
p.config.useIECUnits)
}
p.lengthKnown(newMax)
p.lock.Unlock() // so p.Add can lock
p.Add(0) // re-render
@ -669,22 +863,31 @@ func (p *ProgressBar) IsFinished() bool {
return p.state.finished
}
// IsStarted returns true if progress bar is started
func (p *ProgressBar) IsStarted() bool {
return !p.state.startTime.IsZero()
}
// render renders the progress bar, updating the maximum
// rendered line width. this function is not thread-safe,
// so it must be called with an acquired lock.
func (p *ProgressBar) render() error {
// make sure that the rendering is not happening too quickly
// but always show if the currentNum reaches the max
if time.Since(p.state.lastShown).Nanoseconds() < p.config.throttleDuration.Nanoseconds() &&
if !p.IsStarted() {
p.state.startTime = time.Now()
} else if time.Since(p.state.lastShown).Nanoseconds() < p.config.throttleDuration.Nanoseconds() &&
p.state.currentNum < p.config.max {
return nil
}
if !p.config.useANSICodes {
// first, clear the existing progress bar
err := clearProgressBar(p.config, p.state)
if err != nil {
return err
// first, clear the existing progress bar, if not yet finished.
if !p.state.finished {
err := clearProgressBar(p.config, p.state)
if err != nil {
return err
}
}
}
@ -695,6 +898,11 @@ func (p *ProgressBar) render() error {
io.Copy(p.config.writer, &p.config.stdBuffer)
renderProgressBar(p.config, &p.state)
}
if p.config.maxDetailRow > 0 {
p.renderDetails()
// put the cursor back to the last line of the details
writeString(p.config, fmt.Sprintf("\u001B[%dB\r\u001B[%dC", p.config.maxDetailRow, len(p.state.details[len(p.state.details)-1])))
}
if p.config.onCompletion != nil {
p.config.onCompletion()
}
@ -726,6 +934,20 @@ func (p *ProgressBar) render() error {
return nil
}
// lengthUnknown sets the progress bar to ignore the length
func (p *ProgressBar) lengthUnknown() {
p.config.ignoreLength = true
p.config.max = int64(p.config.width)
p.config.predictTime = false
}
// lengthKnown sets the progress bar to do not ignore the length
func (p *ProgressBar) lengthKnown(max int64) {
p.config.ignoreLength = false
p.config.max = max
p.config.predictTime = true
}
// State returns the current state
func (p *ProgressBar) State() State {
p.lock.Lock()
@ -738,7 +960,12 @@ func (p *ProgressBar) State() State {
}
s.CurrentPercent = float64(p.state.currentNum) / float64(p.config.max)
s.CurrentBytes = p.state.currentBytes
s.SecondsSince = time.Since(p.state.startTime).Seconds()
if p.IsStarted() {
s.SecondsSince = time.Since(p.state.startTime).Seconds()
} else {
s.SecondsSince = 0
}
if p.state.currentNum > 0 {
s.SecondsLeft = s.SecondsSince / float64(p.state.currentNum) * (float64(p.config.max) - float64(p.state.currentNum))
}
@ -798,21 +1025,32 @@ func renderProgressBar(c config, s *state) (int, error) {
if c.showBytes {
currentHumanize, currentSuffix := humanizeBytes(s.currentBytes, c.useIECUnits)
if currentSuffix == c.maxHumanizedSuffix {
sb.WriteString(fmt.Sprintf("%s/%s%s",
currentHumanize, c.maxHumanized, c.maxHumanizedSuffix))
} else {
if c.showTotalBytes {
sb.WriteString(fmt.Sprintf("%s/%s%s",
currentHumanize, c.maxHumanized, c.maxHumanizedSuffix))
} else {
sb.WriteString(fmt.Sprintf("%s%s",
currentHumanize, c.maxHumanizedSuffix))
}
} else if c.showTotalBytes {
sb.WriteString(fmt.Sprintf("%s%s/%s%s",
currentHumanize, currentSuffix, c.maxHumanized, c.maxHumanizedSuffix))
} else {
sb.WriteString(fmt.Sprintf("%s%s", currentHumanize, currentSuffix))
}
} else {
} else if c.showTotalBytes {
sb.WriteString(fmt.Sprintf("%.0f/%d", s.currentBytes, c.max))
} else {
sb.WriteString(fmt.Sprintf("%.0f", s.currentBytes))
}
} else {
if c.showBytes {
currentHumanize, currentSuffix := humanizeBytes(s.currentBytes, c.useIECUnits)
sb.WriteString(fmt.Sprintf("%s%s", currentHumanize, currentSuffix))
} else {
} else if c.showTotalBytes {
sb.WriteString(fmt.Sprintf("%.0f/%s", s.currentBytes, "-"))
} else {
sb.WriteString(fmt.Sprintf("%.0f", s.currentBytes))
}
}
}
@ -848,6 +1086,10 @@ func renderProgressBar(c config, s *state) (int, error) {
}
leftBrac, rightBrac, saucer, saucerHead := "", "", "", ""
barStart, barEnd := c.theme.BarStart, c.theme.BarEnd
if s.finished && c.theme.BarEndFilled != "" {
barEnd = c.theme.BarEndFilled
}
// show time prediction in "current/total" seconds format
switch {
@ -884,6 +1126,9 @@ func renderProgressBar(c config, s *state) (int, error) {
c.width = width - getStringWidth(c, c.description, true) - 10 - amend - sb.Len() - len(leftBrac) - len(rightBrac)
s.currentSaucerSize = int(float64(s.currentPercent) / 100.0 * float64(c.width))
}
if (s.currentSaucerSize > 0 || s.currentPercent > 0) && c.theme.BarStartFilled != "" {
barStart = c.theme.BarStartFilled
}
if s.currentSaucerSize > 0 {
if c.ignoreLength {
saucer = strings.Repeat(c.theme.SaucerPadding, s.currentSaucerSize-1)
@ -925,7 +1170,16 @@ func renderProgressBar(c config, s *state) (int, error) {
if len(c.spinner) > 0 {
selectedSpinner = c.spinner
}
spinner := selectedSpinner[int(math.Round(math.Mod(float64(time.Since(s.startTime).Milliseconds()/100), float64(len(selectedSpinner)))))]
var spinner string
if c.spinnerChangeInterval != 0 {
// if the spinner is changed according to an interval, calculate it
spinner = selectedSpinner[int(math.Round(math.Mod(float64(time.Since(s.startTime).Nanoseconds()/c.spinnerChangeInterval.Nanoseconds()), float64(len(selectedSpinner)))))]
} else {
// if the spinner is changed according to the number render was called
spinner = selectedSpinner[s.spinnerIdx]
s.spinnerIdx = (s.spinnerIdx + 1) % len(selectedSpinner)
}
if c.elapsedTime {
if c.showDescriptionAtLineEnd {
str = fmt.Sprintf("\r%s %s [%s] %s ",
@ -956,11 +1210,11 @@ func renderProgressBar(c config, s *state) (int, error) {
} else if rightBrac == "" {
str = fmt.Sprintf("%4d%% %s%s%s%s%s %s",
s.currentPercent,
c.theme.BarStart,
barStart,
saucer,
saucerHead,
strings.Repeat(c.theme.SaucerPadding, repeatAmount),
c.theme.BarEnd,
barEnd,
sb.String())
if (s.currentPercent == 100 && c.showElapsedTimeOnFinish) || c.elapsedTime {
str = fmt.Sprintf("%s [%s]", str, leftBrac)
@ -975,11 +1229,11 @@ func renderProgressBar(c config, s *state) (int, error) {
if s.currentPercent == 100 {
str = fmt.Sprintf("%4d%% %s%s%s%s%s %s",
s.currentPercent,
c.theme.BarStart,
barStart,
saucer,
saucerHead,
strings.Repeat(c.theme.SaucerPadding, repeatAmount),
c.theme.BarEnd,
barEnd,
sb.String())
if c.showElapsedTimeOnFinish {
@ -994,11 +1248,11 @@ func renderProgressBar(c config, s *state) (int, error) {
} else {
str = fmt.Sprintf("%4d%% %s%s%s%s%s %s [%s:%s]",
s.currentPercent,
c.theme.BarStart,
barStart,
saucer,
saucerHead,
strings.Repeat(c.theme.SaucerPadding, repeatAmount),
c.theme.BarEnd,
barEnd,
sb.String(),
leftBrac,
rightBrac)
@ -1153,6 +1407,8 @@ func shouldCacheOutput(pb *ProgressBar) bool {
}
func Bprintln(pb *ProgressBar, a ...interface{}) (int, error) {
pb.lock.Lock()
defer pb.lock.Unlock()
if !shouldCacheOutput(pb) {
return fmt.Fprintln(pb.config.writer, a...)
} else {
@ -1161,6 +1417,8 @@ func Bprintln(pb *ProgressBar, a ...interface{}) (int, error) {
}
func Bprintf(pb *ProgressBar, format string, a ...interface{}) (int, error) {
pb.lock.Lock()
defer pb.lock.Unlock()
if !shouldCacheOutput(pb) {
return fmt.Fprintf(pb.config.writer, format, a...)
} else {

@ -1539,8 +1539,8 @@ github.com/rivo/uniseg
# github.com/rs/xid v1.6.0
## explicit; go 1.16
github.com/rs/xid
# github.com/schollz/progressbar/v3 v3.14.6
## explicit; go 1.13
# github.com/schollz/progressbar/v3 v3.17.0
## explicit; go 1.22
github.com/schollz/progressbar/v3
# github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529
## explicit

Loading…
Cancel
Save