pb

package
v5.1.15+incompatible Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 26, 2020 License: Apache-2.0, BSD-3-Clause Imports: 19 Imported by: 0

README

Terminal progress bar for Go

Coverage Status

It's beta, some features may be changed

This is proposal for the second version of progress bar

  • based on text/template
  • can take custom elements
  • using colors is easy

Installation

go get gopkg.in/cheggaaa/pb.v2

Usage

package main

import (
	"gopkg.in/cheggaaa/pb.v2"
	"time"
)

func main() {
	simple()
	fromPreset()
	customTemplate(`Custom template: {{counters . }}`)
	customTemplate(`{{ red "With colors:" }} {{bar . | green}} {{speed . | blue }}`)
	customTemplate(`{{ red "With funcs:" }} {{ bar . "<" "-" (cycle . "↖" "↗" "↘" "↙" ) "." ">"}} {{speed . | rndcolor }}`)
	customTemplate(`{{ bar . "[<" "·····•·····" (rnd "ᗧ" "◔" "◕" "◷" ) "•" ">]"}}`)
}

func simple() {
	count := 1000
	bar := pb.StartNew(count)
	for i := 0; i < count; i++ {
		bar.Increment()
		time.Sleep(time.Millisecond * 2)
	}
	bar.Finish()
}

func fromPreset() {
	count := 1000
	//bar := pb.Default.Start(total)
	//bar := pb.Simple.Start(total)
	bar := pb.Full.Start(count)
	defer bar.Finish()
	bar.Set("prefix", "fromPreset(): ")
	for i := 0; i < count/2; i++ {
		bar.Add(2)
		time.Sleep(time.Millisecond * 4)
	}
}

func customTemplate(tmpl string) {
	count := 1000
	bar := pb.ProgressBarTemplate(tmpl).Start(count)
	defer bar.Finish()
	for i := 0; i < count/2; i++ {
		bar.Add(2)
		time.Sleep(time.Millisecond * 4)
	}
}

Documentation

Index

Constants

View Source
const (
	// Bytes means we're working with byte sizes. Numbers will print as Kb, Mb, etc
	// bar.Set(pb.Bytes, true)
	Bytes key = 1 << iota

	// Terminal means we're will print to terminal and can use ascii sequences
	// Also we're will try to use terminal width
	Terminal

	// Static means progress bar will not update automaticly
	Static

	// ReturnSymbol - by default in terminal mode it's '\r'
	ReturnSymbol

	// Color by default is true when output is tty, but you can set to false for disabling colors
	Color
)
View Source
const Version = "2.0.6"

Version of ProgressBar library

Variables

View Source
var UnsafeDefaultTemplateFuncs = defaultTemplateFuncs

Functions

func CellCount

func CellCount(s string) int

func RegisterElement

func RegisterElement(name string, el Element, adaptive bool)

RegisterElement give you a chance to use custom elements

func StripString

func StripString(s string, w int) string

func StripStringToBuffer

func StripStringToBuffer(s string, w int, buf *bytes.Buffer)

Types

type Element

type Element interface {
	ProgressElement(state *State, args ...string) string
}

Element is an interface for bar elements

type ElementFunc

type ElementFunc func(state *State, args ...string) string

ElementFunc type implements Element interface and created for simplify elements

var ElementBar ElementFunc = func(state *State, args ...string) string {
	// init
	var p = getProgressObj(state, args...)

	total, value := state.Total(), state.Value()
	if total < 0 {
		total = -total
	}
	if value < 0 {
		value = -value
	}

	if total != 0 && value > total {
		total = value
	}

	p.buf.Reset()

	var widthLeft = state.AdaptiveElWidth()
	if widthLeft <= 0 || !state.IsAdaptiveWidth() {
		widthLeft = 30
	}

	if p.cc[0] < widthLeft {
		widthLeft -= p.write(state, 0, p.cc[0])
	} else {
		p.write(state, 0, widthLeft)
		return p.buf.String()
	}

	if p.cc[4] < widthLeft {

		widthLeft -= p.cc[4]
	} else {
		p.write(state, 4, widthLeft)
		return p.buf.String()
	}

	var curCount int

	if total > 0 {

		curCount = int(math.Ceil((float64(value) / float64(total)) * float64(widthLeft)))
	}

	if total == value && state.IsFinished() {
		widthLeft -= p.write(state, 1, curCount)
	} else if toWrite := curCount - p.cc[2]; toWrite > 0 {
		widthLeft -= p.write(state, 1, toWrite)
		widthLeft -= p.write(state, 2, p.cc[2])
	} else if curCount > 0 {
		widthLeft -= p.write(state, 2, curCount)
	}
	if widthLeft > 0 {
		widthLeft -= p.write(state, 3, widthLeft)
	}

	p.write(state, 4, p.cc[4])

	return p.buf.String()
}

ElementBar make progress bar view [-->__] Optionally can take up to 5 string arguments. Defaults is "[", "-", ">", "_", "]" In template use as follows: {{bar . }} or {{bar . "<" "oOo" "|" "~" ">"}} Color args: {{bar . (red "[") (green "-") ...

var ElementCounters ElementFunc = func(state *State, args ...string) string {
	var f string
	if state.Total() > 0 {
		f = argsHelper(args).getNotEmptyOr(0, "%s / %s")
	} else {
		f = argsHelper(args).getNotEmptyOr(1, "%[1]s")
	}
	return fmt.Sprintf(f, state.Format(state.Value()), state.Format(state.Total()))
}

ElementCounters shows current and total values. Optionally can take one or two string arguments. First string will be used as format value when Total is present (>0). Default is "%s / %s" Second string will be used when total <= 0. Default is "%[1]s" In template use as follows: {{counters .}} or {{counters . "%s/%s"}} or {{counters . "%s/%s" "%s/?"}}

var ElementCycle ElementFunc = func(state *State, args ...string) string {
	if len(args) == 0 {
		return ""
	}
	n, _ := state.Get(cycleObj).(int)
	if n >= len(args) {
		n = 0
	}
	state.Set(cycleObj, n+1)
	return args[n]
}

ElementCycle return next argument for every call In template use as follows: {{cycle . "1" "2" "3"}} Or mix width other elements: {{ bar . "" "" (cycle . "↖" "↗" "↘" "↙" )}}

var ElementElapsedTime ElementFunc = func(state *State, args ...string) string {
	etm := state.Time().Truncate(time.Second).Sub(state.StartTime().Truncate(time.Second))
	return fmt.Sprintf(argsHelper(args).getOr(0, "%s"), etm.String())
}

ElementElapsedTime shows elapsed time Optionally cat take one argument - it's format for time string. In template use as follows: {{etime .}} or {{etime . "%s elapsed"}}

var ElementPercent ElementFunc = func(state *State, args ...string) string {
	argsh := argsHelper(args)
	if state.Total() > 0 {
		return fmt.Sprintf(
			argsh.getNotEmptyOr(0, "%.02f%%"),
			float64(state.Value())/(float64(state.Total())/float64(100)),
		)
	}
	return argsh.getOr(1, "?%")
}

ElementPercent shows current percent of progress. Optionally can take one or two string arguments. First string will be used as value for format float64, default is "%.02f%%". Second string will be used when percent can't be calculated, default is "?%" In template use as follows: {{percent .}} or {{percent . "%.03f%%"}} or {{percent . "%.03f%%" "?"}}

var ElementRemainingTime ElementFunc = func(state *State, args ...string) string {
	var rts string
	sp := getSpeedObj(state).value(state)
	if !state.IsFinished() {
		if sp > 0 {
			remain := float64(state.Total() - state.Value())
			remainDur := time.Duration(remain/sp) * time.Second
			rts = remainDur.String()
		} else {
			return argsHelper(args).getOr(2, "?")
		}
	} else {
		rts = state.Time().Truncate(time.Second).Sub(state.StartTime().Truncate(time.Second)).String()
		return fmt.Sprintf(argsHelper(args).getOr(1, "%s"), rts)
	}
	return fmt.Sprintf(argsHelper(args).getOr(0, "%s"), rts)
}

ElementRemainingTime calculates remaining time based on speed (EWMA) Optionally can take one or two string arguments. First string will be used as value for format time duration string, default is "%s". Second string will be used when bar finished and value indicates elapsed time, default is "%s" Third string will be used when value not available, default is "?" In template use as follows: {{rtime .}} or {{rtime . "%s remain"}} or {{rtime . "%s remain" "%s total" "???"}}

var ElementSpeed ElementFunc = func(state *State, args ...string) string {
	sp := getSpeedObj(state).value(state)
	if sp == 0 {
		return argsHelper(args).getNotEmptyOr(1, "? p/s")
	}
	return fmt.Sprintf(argsHelper(args).getNotEmptyOr(0, "%s p/s"), state.Format(int64(round(sp))))
}

ElementSpeed calculates current speed by EWMA Optionally can take one or two string arguments. First string will be used as value for format speed, default is "%s p/s". Second string will be used when speed not available, default is "? p/s" In template use as follows: {{speed .}} or {{speed . "%s per second"}} or {{speed . "%s ps" "..."}

var ElementString ElementFunc = func(state *State, args ...string) string {
	if len(args) == 0 {
		return ""
	}
	v := state.Get(args[0])
	if v == nil {
		return ""
	}
	return fmt.Sprint(v)
}

ElementString get value from bar by given key and print them bar.Set("myKey", "string to print") In template use as follows: {{string . "myKey"}}

func (ElementFunc) ProgressElement

func (e ElementFunc) ProgressElement(state *State, args ...string) string

ProgressElement just call self func

type ProgressBar

type ProgressBar struct {
	// contains filtered or unexported fields
}

ProgressBar is the main object of bar

func New

func New(total int) *ProgressBar

New creates new ProgressBar object

func New64

func New64(total int64) *ProgressBar

New64 creates new ProgressBar object using int64 as total

func Start64

func Start64(total int64) *ProgressBar

Start64 starts new ProgressBar with Default template. Using int64 as total.

func StartNew

func StartNew(total int) *ProgressBar

StartNew starts new ProgressBar with Default template

func (*ProgressBar) Add

func (pb *ProgressBar) Add(value int) *ProgressBar

Add adding given int value to bar value

func (*ProgressBar) Add64

func (pb *ProgressBar) Add64(value int64) *ProgressBar

Add adding given int64 value to bar value

func (*ProgressBar) Current

func (pb *ProgressBar) Current() int64

Current return current bar value

func (*ProgressBar) Err

func (pb *ProgressBar) Err() error

Err return possible error When all ok - will be nil May contain template.Execute errors

func (*ProgressBar) Finish

func (pb *ProgressBar) Finish() *ProgressBar

Finish stops the bar

func (*ProgressBar) Format

func (pb *ProgressBar) Format(v int64) string

Format convert int64 to string according to the current settings

func (*ProgressBar) Get

func (pb *ProgressBar) Get(key interface{}) interface{}

Get return value by key

func (*ProgressBar) GetBool

func (pb *ProgressBar) GetBool(key interface{}) bool

GetBool return value by key and try to convert there to boolean If value doesn't set or not boolean - return false

func (*ProgressBar) Increment

func (pb *ProgressBar) Increment() *ProgressBar

Increment atomically increments the progress

func (*ProgressBar) IsStarted

func (pb *ProgressBar) IsStarted() bool

IsStarted indicates progress bar state

func (*ProgressBar) NewProxyReader

func (pb *ProgressBar) NewProxyReader(r io.Reader) *Reader

NewProxyReader creates a wrapper for given reader, but with progress handle Takes io.Reader or io.ReadCloser Also, it automatically switches progress bar to handle units as bytes

func (*ProgressBar) ProgressElement

func (pb *ProgressBar) ProgressElement(s *State, args ...string) string

ProgressElement implements Element interface

func (*ProgressBar) Set

func (pb *ProgressBar) Set(key, value interface{}) *ProgressBar

Set sets any value by any key

func (*ProgressBar) SetCurrent

func (pb *ProgressBar) SetCurrent(value int64) *ProgressBar

SetCurrent sets the current bar value

func (*ProgressBar) SetErr

func (pb *ProgressBar) SetErr(err error) *ProgressBar

SetErr sets error to the ProgressBar Error will be available over Err()

func (*ProgressBar) SetRefreshRate

func (pb *ProgressBar) SetRefreshRate(dur time.Duration) *ProgressBar

func (*ProgressBar) SetTemplate

func (pb *ProgressBar) SetTemplate(tmpl ProgressBarTemplate) *ProgressBar

SetTemplateString sets ProgressBarTempate and parse it

func (*ProgressBar) SetTemplateString

func (pb *ProgressBar) SetTemplateString(tmpl string) *ProgressBar

SetTemplateString sets ProgressBar tempate string and parse it

func (*ProgressBar) SetTotal

func (pb *ProgressBar) SetTotal(value int64) *ProgressBar

SetTotal sets the total bar value

func (*ProgressBar) SetWidth

func (pb *ProgressBar) SetWidth(width int) *ProgressBar

SetWidth sets the bar width When given value <= 0 would be using the terminal width (if possible) or default value.

func (*ProgressBar) SetWriter

func (pb *ProgressBar) SetWriter(w io.Writer) *ProgressBar

SetWriter sets the io.Writer. Bar will write in this writer By default this is os.Stderr

func (*ProgressBar) Start

func (pb *ProgressBar) Start() *ProgressBar

Start starts the bar

func (*ProgressBar) StartTime

func (pb *ProgressBar) StartTime() time.Time

StartTime return the time when bar started

func (*ProgressBar) String

func (pb *ProgressBar) String() string

String return currrent string representation of ProgressBar

func (*ProgressBar) Total

func (pb *ProgressBar) Total() int64

Total return current total bar value

func (*ProgressBar) Width

func (pb *ProgressBar) Width() (width int)

Width return the bar width It's current terminal width or settled over 'SetWidth' value.

func (*ProgressBar) Write

func (pb *ProgressBar) Write() *ProgressBar

Write performs write to the output

type ProgressBarTemplate

type ProgressBarTemplate string

ProgressBarTemplate that template string

var (
	// Full - preset with all default available elements
	// Example: 'Prefix 20/100 [-->______] 20% 1 p/s ETA 1m Suffix'
	Full ProgressBarTemplate = `{{string . "prefix"}}{{counters . }} {{bar . }} {{percent . }} {{speed . }} {{rtime . "ETA %s"}}{{string . "suffix"}}`

	// Default - preset like Full but without elapsed time
	// Example: 'Prefix 20/100 [-->______] 20% 1 p/s ETA 1m Suffix'
	Default ProgressBarTemplate = `{{string . "prefix"}}{{counters . }} {{bar . }} {{percent . }} {{speed . }}{{string . "suffix"}}`

	// Simple - preset without speed and any timers. Only counters, bar and percents
	// Example: 'Prefix 20/100 [-->______] 20% Suffix'
	Simple ProgressBarTemplate = `{{string . "prefix"}}{{counters . }} {{bar . }} {{percent . }}{{string . "suffix"}}`
)

func (ProgressBarTemplate) New

func (pbt ProgressBarTemplate) New(total int) *ProgressBar

New creates new bar from template

func (ProgressBarTemplate) Start

func (pbt ProgressBarTemplate) Start(total int) *ProgressBar

Start create and start new bar with given int total value

func (ProgressBarTemplate) Start64

func (pbt ProgressBarTemplate) Start64(total int64) *ProgressBar

Start64 create and start new bar with given int64 total value

type Reader

type Reader struct {
	io.Reader
	// contains filtered or unexported fields
}

Reader it's a wrapper for given reader, but with progress handle

func (*Reader) Close

func (r *Reader) Close() (err error)

Close the wrapped reader when it implements io.Closer

func (*Reader) Read

func (r *Reader) Read(p []byte) (n int, err error)

Read reads bytes from wrapped reader and add amount of bytes to progress bar

type State

type State struct {
	*ProgressBar
	// contains filtered or unexported fields
}

State represents the current state of bar Need for bar elements

func (*State) AdaptiveElWidth

func (s *State) AdaptiveElWidth() int

AdaptiveElWidth - adaptive elements must return string with given cell count (when AdaptiveElWidth > 0)

func (*State) Id

func (s *State) Id() uint64

Id it's the current state identifier - incremental - starts with 1 - resets after finish/start

func (*State) IsAdaptiveWidth

func (s *State) IsAdaptiveWidth() bool

IsAdaptiveWidth returns true when element must be shown as adaptive

func (*State) IsFinished

func (s *State) IsFinished() bool

IsFinished return true when bar is finished

func (*State) IsFirst

func (s *State) IsFirst() bool

IsFirst return true only in first render

func (*State) Time

func (s *State) Time() time.Time

Time when state was created

func (*State) Total

func (s *State) Total() int64

Total it's bar int64 total

func (*State) Value

func (s *State) Value() int64

Value it's current value

func (*State) Width

func (s *State) Width() int

Width of bar

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL