goprogressor

package module
v0.0.0-...-159043e Latest Latest
Warning

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

Go to latest
Published: Dec 1, 2019 License: MIT Imports: 9 Imported by: 0

README

goprogressor

A Go library to render progress bars in terminal applications. It provides a set of flexible features with a customizable API.

example

Progress bars improve readability for terminal applications with long outputs by providing a concise feedback loop.

Features

  • Multiple Bars: goprogressor can render multiple progress bars that can be tracked concurrently
  • Dynamic Addition: Add additional progress bars any time, even after the progress tracking has started
  • Prepend and Append Functions: Append or prepend completion percent and time elapsed to the progress bars
  • Custom Decorator Functions: Add custom functions around the bar along with helper functions

Usage

To start listening for progress bars, call goprogressor.Start() and add a progress bar using goprogressor.AddBar(total int). Update the progress using bar.Incr() or bar.Set(n int). Full source code for the below example is available at example/simple/simple.go

goprogressor.Start()            // start rendering
bar := goprogressor.AddBar(100) // Add a new bar

// optionally, append and prepend completion and elapsed time
bar.AppendCompleted()
bar.PrependElapsed()

for bar.Incr() {
  time.Sleep(time.Millisecond * 20)
}

This will render the below in the terminal

example

Using Custom Decorators

You can also add a custom decorator function in addition to default bar.AppendCompleted() and bar.PrependElapsed() decorators. The below example tracks the current step for an application deploy progress. Source code for the below example is available at example/full/full.go

var steps = []string{"downloading source", "installing deps", "compiling", "packaging", "seeding database", "deploying", "staring servers"}
bar := goprogressor.AddBar(len(steps))

// prepend the current step to the bar
bar.PrependFunc(func(b *goprogressor.Bar) string {
  return "app: " + steps[b.Current()-1]
})

for bar.Incr() {
  time.Sleep(time.Millisecond * 10)
}
Rendering Multiple bars

You can add multiple bars using goprogressor.AddBar(n). The below example demonstrates updating multiple bars concurrently and adding a new bar later in the pipeline. Source for this example is available at example/multi/multi.go

waitTime := time.Millisecond * 100
goprogressor.Start()

// start the progress bars in go routines
var wg sync.WaitGroup

bar1 := goprogressor.AddBar(20).AppendCompleted().PrependElapsed()
wg.Add(1)
go func() {
  defer wg.Done()
  for bar1.Incr() {
    time.Sleep(waitTime)
  }
}()

bar2 := goprogressor.AddBar(40).AppendCompleted().PrependElapsed()
wg.Add(1)
go func() {
  defer wg.Done()
  for bar2.Incr() {
    time.Sleep(waitTime)
  }
}()

time.Sleep(time.Second)
bar3 := goprogressor.AddBar(20).PrependElapsed().AppendCompleted()
wg.Add(1)
go func() {
  defer wg.Done()
  for i := 1; i <= bar3.Total; i++ {
    bar3.Set(i)
    time.Sleep(waitTime)
  }
}()

// wait for all the go routines to finish
wg.Wait()

This will produce

example

Incr counter

Bar.Incr() is an atomic counter and can be used as a general tracker, making it ideal for tracking progress of work fanned out to a lots of go routines. The source code for the below example is available at example/incr/incr.go

runtime.GOMAXPROCS(runtime.NumCPU()) // use all available cpu cores

// create a new bar and prepend the task progress to the bar and fanout into 1k go routines
count := 1000
bar := goprogressor.AddBar(count).AppendCompleted().PrependElapsed()
bar.PrependFunc(func(b *goprogressor.Bar) string {
  return fmt.Sprintf("Task (%d/%d)", b.Current(), count)
})

goprogressor.Start()
var wg sync.WaitGroup

// fanout into go routines
for i := 0; i < count; i++ {
  wg.Add(1)
  go func() {
    defer wg.Done()
    time.Sleep(time.Millisecond * time.Duration(rand.Intn(500)))
    bar.Incr()
  }()
}
time.Sleep(time.Second) // wait for a second for all the go routines to finish
wg.Wait()
goprogressor.Stop()

Installation

$ go get -v gitee.com/shirdonl/goProgressor

Todos

  • Resize bars and decorators by auto detecting window's dimensions
  • Handle more progress bars than vertical screen allows

License

goprogressor is released under the MIT License. See LICENSE.

Documentation

Overview

Package goprogressor is a library to render progress bars in terminal applications

Example
goprogressor.Start()            // start rendering
bar := goprogressor.AddBar(100) // Add a new bar

// optionally, append and prepend completion and elapsed time
bar.AppendCompleted()
bar.PrependElapsed()

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

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// Fill is the default character representing completed progress
	Fill byte = '='

	// Head is the default character that moves when progress is updated
	Head byte = '>'

	// Empty is the default character that represents the empty progress
	Empty byte = '-'

	// LeftEnd is the default character in the left most part of the progress indicator
	LeftEnd byte = '['

	// RightEnd is the default character in the right most part of the progress indicator
	RightEnd byte = ']'

	// Width is the default width of the progress bar
	Width = 70

	// ErrMaxCurrentReached is error when trying to set current value that exceeds the total value
	ErrMaxCurrentReached = errors.New("errors: current value is greater total value")
)
View Source
var Out = os.Stdout

Out is the default writer to render progress bars to

View Source
var RefreshInterval = time.Millisecond * 10

RefreshInterval in the default time duration to wait for refreshing the output

Functions

func Listen

func Listen()

Listen listens for updates and renders the progress bars

func Start

func Start()

Start starts the rendering the progress of progress bars using the DefaultProgress. It listens for updates using `bar.Set(n)` and new bars when added using `AddBar`

func Stop

func Stop()

Stop stops listening

Types

type Bar

type Bar struct {
	// Total of the total  for the progress bar
	Total int

	// LeftEnd is character in the left most part of the progress indicator. Defaults to '['
	LeftEnd byte

	// RightEnd is character in the right most part of the progress indicator. Defaults to ']'
	RightEnd byte

	// Fill is the character representing completed progress. Defaults to '='
	Fill byte

	// Head is the character that moves when progress is updated.  Defaults to '>'
	Head byte

	// Empty is the character that represents the empty progress. Default is '-'
	Empty byte

	// TimeStated is time progress began
	TimeStarted time.Time

	// Width is the width of the progress bar
	Width int
	// contains filtered or unexported fields
}

Bar represents a progress bar

func AddBar

func AddBar(total int) *Bar

AddBar creates a new progress bar and adds it to the default progress container

func NewBar

func NewBar(total int) *Bar

NewBar returns a new progress bar

func (*Bar) AppendCompleted

func (b *Bar) AppendCompleted() *Bar

AppendCompleted appends the completion percent to the progress bar

func (*Bar) AppendElapsed

func (b *Bar) AppendElapsed() *Bar

AppendElapsed appends the time elapsed the be progress bar

func (*Bar) AppendFunc

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

AppendFunc runs the decorator function and renders the output on the right of the progress bar

func (*Bar) Bytes

func (b *Bar) Bytes() []byte

Bytes returns the byte presentation of the progress bar

func (*Bar) CompletedPercent

func (b *Bar) CompletedPercent() float64

CompletedPercent return the percent completed

func (*Bar) CompletedPercentString

func (b *Bar) CompletedPercentString() string

CompletedPercentString returns the formatted string representation of the completed percent

func (*Bar) Current

func (b *Bar) Current() int

Current returns the current progress of the bar

func (*Bar) Incr

func (b *Bar) Incr() bool

Incr increments the current value by 1, time elapsed to current time and returns true. It returns false if the cursor has reached or exceeds total value.

Example
runtime.GOMAXPROCS(runtime.NumCPU()) // use all available cpu cores

// create a new bar and prepend the task progress to the bar
count := 1000
bar := goprogressor.AddBar(count).AppendCompleted().PrependElapsed()
bar.PrependFunc(func(b *goprogressor.Bar) string {
	return fmt.Sprintf("Task (%d/%d)", b.Current(), count)
})

goprogressor.Start()
var wg sync.WaitGroup

// fanout into 1k go routines
for i := 0; i < count; i++ {
	wg.Add(1)
	go func() {
		defer wg.Done()
		time.Sleep(time.Millisecond * time.Duration(rand.Intn(500)))
		bar.Incr()
	}()
}
time.Sleep(time.Second) // wait for a second for all the go routines to finish
wg.Wait()
goprogressor.Stop()
Output:

func (*Bar) PrependCompleted

func (b *Bar) PrependCompleted() *Bar

PrependCompleted prepends the precent completed to the progress bar

func (*Bar) PrependElapsed

func (b *Bar) PrependElapsed() *Bar

PrependElapsed prepends the time elapsed to the begining of the bar

func (*Bar) PrependFunc

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

PrependFunc runs decorator function and render the output left the progress bar

func (*Bar) Set

func (b *Bar) Set(n int) error

Set the current count of the bar. It returns ErrMaxCurrentReached when trying n exceeds the total value. This is atomic operation and concurrency safe.

func (*Bar) String

func (b *Bar) String() string

String returns the string representation of the bar

func (*Bar) TimeElapsed

func (b *Bar) TimeElapsed() time.Duration

TimeElapsed returns the time elapsed

func (*Bar) TimeElapsedString

func (b *Bar) TimeElapsedString() string

TimeElapsedString returns the formatted string represenation of the time elapsed

type DecoratorFunc

type DecoratorFunc func(b *Bar) string

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

Example
var steps = []string{"downloading source", "installing deps", "compiling", "packaging", "seeding database", "deploying", "staring servers"}
bar := goprogressor.AddBar(len(steps))

// prepend the current step to the bar
bar.PrependFunc(func(b *goprogressor.Bar) string {
	return "app: " + steps[b.Current()-1]
})

for bar.Incr() {
	time.Sleep(time.Millisecond)
}
Output:

type Progress

type Progress struct {
	// Out is the writer to render progress bars to
	Out io.Writer

	// Width is the width of the progress bars
	Width int

	// Bars is the collection of progress bars
	Bars []*Bar

	// RefreshInterval in the time duration to wait for refreshing the output
	RefreshInterval time.Duration
	// contains filtered or unexported fields
}

Progress represents the container that renders progress bars

func New

func New() *Progress

New returns a new progress bar with defaults

func (*Progress) AddBar

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

AddBar creates a new progress bar and adds to the container

Example
waitTime := time.Millisecond * 100
goprogressor.Start()
// start the progress bars in go routines
var wg sync.WaitGroup

bar1 := goprogressor.AddBar(20).AppendCompleted().PrependElapsed()
wg.Add(1)
go func() {
	defer wg.Done()
	for bar1.Incr() {
		time.Sleep(waitTime)
	}
}()

bar2 := goprogressor.AddBar(40).AppendCompleted().PrependElapsed()
wg.Add(1)
go func() {
	defer wg.Done()
	for bar2.Incr() {
		time.Sleep(waitTime)
	}
}()

time.Sleep(time.Second)
bar3 := goprogressor.AddBar(20).PrependElapsed().AppendCompleted()
wg.Add(1)
go func() {
	defer wg.Done()
	for i := 1; i <= bar3.Total; i++ {
		bar3.Set(i)
		time.Sleep(waitTime)
	}
}()
// wait for all the go routines to finish
wg.Wait()
Output:

func (*Progress) Bypass

func (p *Progress) Bypass() io.Writer

Bypass returns a writer which allows non-buffered data to be written to the underlying output

func (*Progress) Listen

func (p *Progress) Listen()

Listen listens for updates and renders the progress bars

func (*Progress) SetOut

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

func (*Progress) SetRefreshInterval

func (p *Progress) SetRefreshInterval(interval time.Duration)

func (*Progress) Start

func (p *Progress) Start()

Start starts the rendering the progress of progress bars. It listens for updates using `bar.Set(n)` and new bars when added using `AddBar`

func (*Progress) Stop

func (p *Progress) Stop()

Stop stops listening

Directories

Path Synopsis
example
util
strutil
Package strutil provides various utilities for manipulating strings
Package strutil provides various utilities for manipulating strings

Jump to

Keyboard shortcuts

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