mpb

package module
v2.0.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Mar 8, 2017 License: MIT Imports: 11 Imported by: 505

README

Multi Progress Bar GoDoc Build Status

mpb is a Go lib for rendering progress bars in terminal applications.

It is inspired by uiprogress library, but unlike the last one, implementation is mutex free, following Go's idiom:

Don't communicate by sharing memory, share memory by communicating.

Features

  • Multiple Bars: mpb can render multiple progress bars that can be tracked concurrently
  • Cancellable: cancel rendering goroutine at any time
  • Dynamic Addition: Add additional progress bar at any time
  • Dynamic Removal: Remove rendering progress bar at any time
  • Dynamic Sorting: Sort bars as you wish
  • Dynamic Resize: Resize bars on terminal width change
  • Custom Decorator Functions: Add custom functions around the bar along with helper functions
  • Dynamic Decorator's Width Sync: Sync width among decorator group (column)
  • Predefined Decoratros: Elapsed time, Ewmaest based ETA, Percentage, Bytes counter

Installation

To get the package, execute:

go get gopkg.in/vbauerster/mpb.v1
go get gopkg.in/vbauerster/mpb.v2

Usage

Following is the simplest use case:

	// Star mpb's rendering goroutine.
	p := mpb.New()
	// Set custom width for every bar, which mpb will render
	// The default one in 70
	p.SetWidth(80)
	// Set custom format for every bar, the default one is "[=>-]"
	p.Format("╢▌▌░╟")
	// Set custom refresh rate, the default one is 100 ms
	p.RefreshRate(120 * time.Millisecond)

	// Add a bar. You're not limited to just one bar, add many if you need.
	bar := p.AddBar(100).PrependName("Single Bar:", 0, 0).AppendPercentage(5, 0)

	for i := 0; i < 100; i++ {
		bar.Incr(1) // increment progress bar
		time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
	}

	// Don't forget to stop mpb's rendering goroutine
	p.Stop()

	// You cannot add bars after p.Stop() has been called
	// p.AddBar(100) // will panic

Running this, will produce:

gif

However mpb was designed with concurrency in mind. Each new bar renders in its own goroutine, therefore adding multiple bars is easy and safe:

	var wg sync.WaitGroup
	p := mpb.New()
	wg.Add(3) // add wg delta
	for i := 0; i < 3; i++ {
		name := fmt.Sprintf("Bar#%d:", i)
		bar := p.AddBar(100).
			PrependName(name, len(name), 0).
			AppendPercentage(5, 0)
		go func() {
			defer wg.Done()
			// you can p.AddBar() here, but ordering will be non deterministic
			// if you still need p.AddBar() here and maintain ordering, use
			// (*mpb.Progress).BeforeRenderFunc(f mpb.BeforeRender)
			for i := 0; i < 100; i++ {
				bar.Incr(1)
				time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
			}
		}()
	}
	wg.Wait() // Wait for goroutines to finish
	p.Stop()  // Stop mpb's rendering goroutine

simple.gif

The source code: example/simple/main.go

Cancel

cancel.gif

The source code: example/cancel/main.go

Removing bar

remove.gif

The source code: example/remove/main.go

Sorting bars by progress

sort.gif

The source code: example/sort/main.go

Resizing bars on terminal width change

resize.gif

The source code: example/prependETA/main.go

Multiple io

io-multiple.gif

The source code: example/io/multiple/main.go

Custom Decorators

Here is example from getparty src code.

License

MIT

The typeface used in screen shots: Iosevka

Documentation

Overview

Package mpb is a library for rendering progress bars in terminal applications.

Example
package main

import (
	"math/rand"
	"time"

	"github.com/vbauerster/mpb"
)

func main() {
	// Star mpb's rendering goroutine.
	// If you don't plan to cancel, feed with nil
	// otherwise provide context.Context, see cancel example
	p := mpb.New()
	// Set custom width for every bar, which mpb will contain
	// The default one in 70
	p.SetWidth(80)
	// Set custom format for every bar, the default one is "[=>-]"
	p.Format("╢▌▌░╟")
	// Set custom refresh rate, the default one is 100 ms
	p.RefreshRate(120 * time.Millisecond)

	// Add a bar. You're not limited to just one bar, add many if you need.
	bar := p.AddBar(100).
		PrependName("Single Bar:", 0, 0).
		AppendPercentage(5, 0)

	for i := 0; i < 100; i++ {
		bar.Incr(1) // increment progress bar
		time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
	}

	// Don't forget to stop mpb's rendering goroutine
	p.Stop()

	// You cannot add bars after p.Stop() has been called
	// p.AddBar(100) // will panic
}
Output:

Index

Examples

Constants

View Source
const (
	// DidentRight specifies identation direction.
	// |   foo|     b| Without DidentRight
	// |foo   |b     | With DidentRight
	DidentRight = 1 << iota

	// DwidthSync will auto sync max width
	DwidthSync

	// DextraSpace adds extra space, makes sence with DwidthSync only.
	// When DidentRight bit set, the space will be added to the right,
	// otherwise to the left.
	DextraSpace
)
View Source
const (
	UnitBytes
)

Variables

View Source
var ErrCallAfterStop = errors.New("method call on stopped Progress instance")

ErrCallAfterStop thrown by panic, if Progress methods like (*Progress).AddBar() are called after (*Progress).Stop() has been called

Functions

func Format

func Format(i int64) *formatter

Types

type Bar

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

Bar represents a progress Bar

func (*Bar) AppendETA

func (b *Bar) AppendETA(minWidth int, conf byte) *Bar

func (*Bar) AppendElapsed

func (b *Bar) AppendElapsed(minWidth int, conf byte) *Bar

func (*Bar) AppendFunc

func (b *Bar) AppendFunc(f DecoratorFunc) *Bar

AppendFunc appends DecoratorFunc

Example
package main

import (
	"fmt"
	"math/rand"
	"time"
	"unicode/utf8"

	"github.com/vbauerster/mpb"
)

func main() {
	decor := func(s *mpb.Statistics, myWidth chan<- int, maxWidth <-chan int) string {
		str := fmt.Sprintf("%3d/%3d", s.Current, s.Total)
		myWidth <- utf8.RuneCountInString(str)
		max := <-maxWidth
		return fmt.Sprintf(fmt.Sprintf("%%%ds", max+1), str)
	}

	totalItem := 100
	p := mpb.New()
	bar := p.AddBar(int64(totalItem)).AppendFunc(decor)

	for i := 0; i < totalItem; i++ {
		bar.Incr(1) // increment progress bar
		time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
	}
}
Output:

func (*Bar) AppendPercentage

func (b *Bar) AppendPercentage(minWidth int, conf byte) *Bar

func (*Bar) Completed

func (b *Bar) Completed()

Completed signals to the bar, that process has been completed. You should call this method when total is unknown and you've reached the point of process completion.

func (*Bar) Format

func (b *Bar) Format(format string) *Bar

Format overrides format of individual bar

func (*Bar) GetAppenders

func (b *Bar) GetAppenders() []DecoratorFunc

GetAppenders returns slice of appender DecoratorFunc

func (*Bar) GetID

func (b *Bar) GetID() int

GetID returs id of the bar

func (*Bar) GetPrependers

func (b *Bar) GetPrependers() []DecoratorFunc

GetPrependers returns slice of prepender DecoratorFunc

func (*Bar) GetStatistics

func (b *Bar) GetStatistics() *Statistics

GetStatistics returs *Statistics, which contains information like Tottal, Current, TimeElapsed and TimePerItemEstimate

func (*Bar) InProgress

func (b *Bar) InProgress() bool

InProgress returns true, while progress is running Can be used as condition in for loop

Example
package main

import (
	"time"

	"github.com/vbauerster/mpb"
)

func main() {
	p := mpb.New()
	bar := p.AddBar(100).AppendPercentage(5, 0)

	for bar.InProgress() {
		bar.Incr(1)
		time.Sleep(time.Millisecond * 20)
	}
}
Output:

func (*Bar) Incr

func (b *Bar) Incr(n int)

Incr increments progress bar

func (*Bar) IncrWithReFill

func (b *Bar) IncrWithReFill(n int, r rune)

IncrWithReFill increments pb with different fill character

func (*Bar) NumOfAppenders

func (b *Bar) NumOfAppenders() int

func (*Bar) NumOfPrependers

func (b *Bar) NumOfPrependers() int

func (*Bar) PrependCounters

func (b *Bar) PrependCounters(pairFormat string, unit Units, minWidth int, conf byte) *Bar

func (*Bar) PrependETA

func (b *Bar) PrependETA(minWidth int, conf byte) *Bar

func (*Bar) PrependElapsed

func (b *Bar) PrependElapsed(minWidth int, conf byte) *Bar

func (*Bar) PrependFunc

func (b *Bar) PrependFunc(f DecoratorFunc) *Bar

PrependFunc prepends DecoratorFunc

Example
package main

import (
	"fmt"
	"math/rand"
	"time"
	"unicode/utf8"

	"github.com/vbauerster/mpb"
)

func main() {
	decor := func(s *mpb.Statistics, myWidth chan<- int, maxWidth <-chan int) string {
		str := fmt.Sprintf("%3d/%3d", s.Current, s.Total)
		myWidth <- utf8.RuneCountInString(str)
		max := <-maxWidth
		return fmt.Sprintf(fmt.Sprintf("%%%ds", max+1), str)
	}

	totalItem := 100
	p := mpb.New()
	bar := p.AddBar(int64(totalItem)).PrependFunc(decor)

	for i := 0; i < totalItem; i++ {
		bar.Incr(1) // increment progress bar
		time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)
	}
}
Output:

func (*Bar) PrependName

func (b *Bar) PrependName(name string, minWidth int, conf byte) *Bar

PrependName prepends name argument to the bar. The conf argument defines the formatting properties

func (*Bar) PrependPercentage

func (b *Bar) PrependPercentage(minWidth int, conf byte) *Bar

func (*Bar) ProxyReader

func (b *Bar) ProxyReader(r io.Reader) *Reader

ProxyReader wrapper for io operations, like io.Copy

func (*Bar) RemoveAllAppenders

func (b *Bar) RemoveAllAppenders()

RemoveAllAppenders removes all append functions

func (*Bar) RemoveAllPrependers

func (b *Bar) RemoveAllPrependers()

RemoveAllPrependers removes all prepend functions

func (*Bar) SetEtaAlpha

func (b *Bar) SetEtaAlpha(a float64) *Bar

SetEtaAlpha sets alfa for exponential-weighted-moving-average ETA estimator Defaults to 0.25 Normally you shouldn't touch this

func (*Bar) SetWidth

func (b *Bar) SetWidth(n int) *Bar

SetWidth overrides width of individual bar

func (*Bar) TrimLeftSpace

func (b *Bar) TrimLeftSpace() *Bar

TrimLeftSpace removes space befor LeftEnd charater

func (*Bar) TrimRightSpace

func (b *Bar) TrimRightSpace() *Bar

TrimRightSpace removes space after RightEnd charater

type BeforeRender

type BeforeRender func([]*Bar)

BeforeRender is a func, which gets called before render process

type DecoratorFunc

type DecoratorFunc func(s *Statistics, myWidth chan<- int, maxWidth <-chan int) string

DecoratorFunc is a function that can be prepended and appended to the progress bar

type Progress

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

Progress represents the container that renders Progress bars

func New

func New() *Progress

New creates new Progress instance, which will orchestrate bars rendering process. It acceepts context.Context, for cancellation. If you don't plan to cancel, it is safe to feed with nil

func (*Progress) AddBar

func (p *Progress) AddBar(total int64) *Bar

AddBar creates a new progress bar and adds to the container pancis, if called on stopped Progress instance, i.e after (*Progress).Stop()

func (*Progress) AddBarWithID

func (p *Progress) AddBarWithID(id int, total int64) *Bar

AddBarWithID creates a new progress bar and adds to the container pancis, if called on stopped Progress instance, i.e after (*Progress).Stop()

func (*Progress) BarCount

func (p *Progress) BarCount() int

BarCount returns bars count in the container. Pancis if called on stopped Progress instance, i.e after (*Progress).Stop()

func (*Progress) BeforeRenderFunc

func (p *Progress) BeforeRenderFunc(f BeforeRender) *Progress

BeforeRenderFunc accepts a func, which gets called before render process.

func (*Progress) Format

func (p *Progress) Format(format string) *Progress

Format sets custom format for underlying bar(s). The default one is "[=>-]"

func (*Progress) RefreshRate

func (p *Progress) RefreshRate(d time.Duration) *Progress

RefreshRate overrides default (100ms) refresh rate value pancis, if called on stopped Progress instance, i.e after (*Progress).Stop()

func (*Progress) RemoveBar

func (p *Progress) RemoveBar(b *Bar) bool

RemoveBar removes bar at any time. Pancis, if called on stopped Progress instance, i.e after (*Progress).Stop()

func (*Progress) SetOut

func (p *Progress) SetOut(w io.Writer) *Progress

SetOut sets underlying writer of progress. Default is os.Stdout pancis, if called on stopped Progress instance, i.e after (*Progress).Stop()

func (*Progress) SetWidth

func (p *Progress) SetWidth(n int) *Progress

SetWidth overrides default (70) width of bar(s)

func (*Progress) Stop

func (p *Progress) Stop()

Stop shutdowns Progress' goroutine Should be called only after each bor's work done, i.e. bar has reached its 100 %. It is NOT for concelation. Use WithContext or WithCancel for cancelation purposes.

func (*Progress) WithCancel

func (p *Progress) WithCancel(ch <-chan struct{}) *Progress

WithCancel cancellation via channel

func (*Progress) WithContext

func (p *Progress) WithContext(ctx context.Context) *Progress

WithContext cancellation via context

type Reader

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

Reader is io.Reader wrapper, for proxy read bytes

func (*Reader) Close

func (r *Reader) Close() error

Close the reader when it implements io.Closer

func (*Reader) Read

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

type Statistics

type Statistics struct {
	Total, Current                   int64
	TimeElapsed, TimePerItemEstimate time.Duration
}

Statistics represents statistics of the progress bar. Cantains: Total, Current, TimeElapsed, TimePerItemEstimate

func (*Statistics) Eta

func (s *Statistics) Eta() time.Duration

Eta returns exponential-weighted-moving-average ETA estimator

type Units

type Units uint

Directories

Path Synopsis
_examples
barExtender Module
cancel Module
complex Module
io Module
merge Module
multiBars Module
panic Module
poplog Module
remove Module
spinTipBar Module
spinnerBar Module
stress Module
suppressBar Module
tipOnComplete Module
example

Jump to

Keyboard shortcuts

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