A really basic thread-safe progress bar for Golang applications

progressbar

travis go report card coverage godocs

A very simple thread-safe progress bar which should work on every OS without problems. I needed a progressbar for croc and everything I tried had problems, so I made another one. In order to be OS agnostic I do not plan to support multi-line outputs.

Install

go get -u github.com/schollz/progressbar/v3

Usage

Basic usage

bar := progressbar.Default(100)
for i := 0; i < 100; i++ {
    bar.Add(1)
    time.Sleep(40 * time.Millisecond)
}

which looks like:

Example of basic bar

I/O operations

The progressbar implements an io.Writer so it can automatically detect the number of bytes written to a stream, so you can use it as a progressbar for an io.Reader.

req, _ := http.NewRequest("GET", "https://dl.google.com/go/go1.14.2.src.tar.gz", nil)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()

f, _ := os.OpenFile("go1.14.2.src.tar.gz", os.O_CREATE|os.O_WRONLY, 0644)
defer f.Close()

bar := progressbar.DefaultBytes(
    resp.ContentLength,
    "downloading",
)
io.Copy(io.MultiWriter(f, bar), resp.Body)

which looks like:

Example of download bar

Progress bar with unknown length

A progressbar with unknown length is a spinner. Any bar with -1 length will automatically convert it to a spinner with a customizable spinner type. For example, the above code can be run and set the resp.ContentLength to -1.

which looks like:

Example of download bar with unknown length

Customization

There is a lot of customization that you can do - change the writer, the color, the width, description, theme, etc. See all the options.

bar := progressbar.NewOptions(1000,
    progressbar.OptionSetWriter(ansi.NewAnsiStdout()),
    progressbar.OptionEnableColorCodes(true),
    progressbar.OptionShowBytes(true),
    progressbar.OptionSetWidth(15),
    progressbar.OptionSetDescription("[cyan][1/3][reset] Writing moshable file..."),
    progressbar.OptionSetTheme(progressbar.Theme{
        Saucer:        "[green]=[reset]",
        SaucerHead:    "[green]>[reset]",
        SaucerPadding: " ",
        BarStart:      "[",
        BarEnd:        "]",
    }))
for i := 0; i < 1000; i++ {
    bar.Add(1)
    time.Sleep(5 * time.Millisecond)
}

which looks like:

Example of customized bar

Contributing

Pull requests are welcome. Feel free to...

  • Revise documentation
  • Add new features
  • Fix bugs
  • Suggest improvements

Thanks

Thanks @Dynom for massive improvements in version 2.0!

Thanks @CrushedPixel for adding descriptions and color code support!

Thanks @MrMe42 for adding some minor features!

Thanks @tehstun for some great PRs!

Thanks @Benzammour and @haseth for helping create v3!

Thanks @briandowns for compiling the list of spinners.

License

MIT

Comments
  • OptionShowCount incorrectly renders with items below 1%

    OptionShowCount incorrectly renders with items below 1%

    Currently, if a bar is created with maximum number of items X and then updated (.Add(i)) with i that is significantly lower than 1% of X (e.g. 0.1%), then the item count shown to the right of the bar ((n/X)) will only update when it has accumulated to a whole percentage value (e.g. 1%, 2%) and so on. When you have a lot of items in between, it looks really weird.

    It is possible to introduce fractional percentage (which i guess will by default fix this behaviour), or somehow re-render the item count text on Add?

  • Refactor to functional options

    Refactor to functional options

    TL;DR

    The title is a bit misleading but currently this PR:

    • ✅ Introduces a "default value render" where it can render a 0% progress (instead when .Add(n) is called
    • ✅ Removes the instance setters and replace 'm with construction time Functional Options
    • ✅ Introduces a setting to change the initial rendering behaviour
    • ❎ Obliterates backward compatibility
    • ❎ Depends on Go 1.10 to run the tests (uses strings.Builder)

    The details

    This PR removes any of the "setters" and is more in line with the immutability concept. I'm not sure what the typical use-case is, but I don't expect people changing the options frequently once the bar is configured. This design supports that philosophy by having this moment a bit "sooner". Once the constructor is called, it's ready to be used and doesn't support any "configuration" changes.

    This way we can also render a blank bar on the get-go and voids the need to call bar.RenderBlank(). However I've tinkered with it and I don't think I personally like the implicit behaviour. So I've made it optional (disabled by default) and we can pick and choose.

    New API

    I think the API speaks for itself, but now it'll work like:

    bar := progressbar.NewOptions(100, OptionSetSize(10))
    bar.RenderBlank()
    bar.Add(5)
    
    • SetSize() has been removed and renamed to it's Width equivalent OptionSetWidth()
    • OptionSetRenderBlankState() is introduced to define the rendering behaviour of a blank progress bar

    Pending considerations

    • I've left progressbar.New(max) in, but I can just as easily replace it with what's now called progressbar.NewOptions().
    • ~~Decide if we want to set the maximum bar units using FO or as a straight-up parameter.~~

    Should resolve https://github.com/schollz/progressbar/issues/12

  • #79 breaks rendering on bars in GoLand terminal Windows 10

    #79 breaks rendering on bars in GoLand terminal Windows 10

    This error happens every 9 out of 10 times, all renders error out with: golang.org/x/sys/windows.ERROR_INVALID_HANDLE (6). I am using the default GoLand configuration, so it's a Command Prompt terminal.

    Ref: #79

  • Cannot get newline to print properly

    Cannot get newline to print properly

    Issue pictured image Code:

    	bar := progressbar.NewOptions(-1,
    		progressbar.OptionSetDescription("downloading emojis "+count),
    		progressbar.OptionSpinnerType(4),
    		progressbar.OptionShowCount(),
    		progressbar.OptionShowBytes(true),
    		progressbar.OptionOnCompletion(func() {
    			fmt.Fprint(os.Stderr, "\n")
    		}),
    	)
    

    I can't get the bar to properly add a newline afterwards for whatever reason.

  • Create String and Silent funcs

    Create String and Silent funcs

    This PR adds the ProgressBar.String() method that returns the rendered version of the progress bar as a string. This is useful for environments where one doesn't want to output to stdout, but use the progess bar somewhere else. Personally I'm using it in Amfora, which is a TUI application.

    This PR also adds the DefaultSilent and DefaultBytesSilent funcs, which create a ProgressBar that doesn't output anywhere, and doesn't have

    OptionOnCompletion(func() {
    	fmt.Fprint(os.Stderr, "\n")
    })
    
  • added infinite scrolling option

    added infinite scrolling option

    Here are the following changes made in code:

    1. Added ignoreLength flag.
    2. config.currentByte takes care of the number of bytes progressed.
    3. Able to show infinite progress bar withiteration/sec.
    4. Added showByte Option to toggle the speed rate display.
    5. Added test cases.
    6. Removed option to update max value through ChangeMax() function.

    Resolves #27

  • screen scrolling

    screen scrolling

    my progressbar init:

            max := 10000
    	writer := os.Stdout
    	bar := progressbar.NewOptions(max,
    		progressbar.OptionSetDescription(""),
    		progressbar.OptionSetWriter(writer),
    		progressbar.OptionSetWidth(50),
    		progressbar.OptionThrottle(65*time.Millisecond),
    		progressbar.OptionShowCount(),
    		progressbar.OptionShowIts(),
    		progressbar.OptionOnCompletion(func() {
    			fmt.Fprint(writer, "\n")
    		}),
    		progressbar.OptionSpinnerType(14),
    		progressbar.OptionFullWidth(),
    	)
    	_ = bar.RenderBlank()
    
    	for i := 0; i <= max; i++ {
    		bar.Add(1)
    		time.Sleep(time.Millisecond * 50)
    	}
    

    2020-07-07 16 30 27 it starts scrolling.so what i can do?

  • Feature request: unknown length (e.g. network io)

    Feature request: unknown length (e.g. network io)

    most IO progress implementations seem to only allow for a known fixed length denominator. in the case where the operation is for instance an HTTP POST, the total length/duration is not known and there doesn't seem to be a way to easily tie into the network layer to do a 'better' job. to satisfy this use case it would be great to have the progress bar simply ping back and forth, ping pong style, until progress bar Finish or Reset is called. Passing -1 perhaps to OptionSetWidth could be an approach to indicate unknown length.

  • int64 for maxbytes

    int64 for maxbytes

    Anything against having int64 for maxBytes, currentNum and so on? If we're processing a file, and we're using a progressbar, it's likely it's a huge file :)

    int will do in 64bit OS, but not in 32bit one (such as raspbian)

  • [Bug] Console output after progress bar doesn't start with new line

    [Bug] Console output after progress bar doesn't start with new line

    Affected version

    3.9.0

    Steps To Reproduce

    Create the following code example

    package main
    
    import (
    	"fmt"
    	"github.com/schollz/progressbar/v3"
    	"time"
    )
    
    func main() {
    	count := 10
    	progressBar := progressbar.NewOptions(
    		count,
    		progressbar.OptionFullWidth(),
    		progressbar.OptionSetRenderBlankState(true),
    		progressbar.OptionShowCount(),
    		progressbar.OptionSetVisibility(true),
    		progressbar.OptionSetPredictTime(false),
    		progressbar.OptionClearOnFinish(),
    	)
    
    	for i := 0; i < count; i++ {
    		time.Sleep(time.Millisecond * 100)
    		_ = progressBar.Add(1)
    	}
    
    	fmt.Println("hello")
    }
    

    Run

    go get github.com/schollz/progressbar/[email protected]
    

    Then run the example.

    The result is

    > go run .
    hello
    

    Then run

    go get github.com/schollz/progressbar/[email protected]
    

    And run the example again.

    The result is

    > go run .
                                                                                                                                               hello
    

    Notice number of spaces before the hello word.

    See the playground https://go.dev/play/p/Tpiz7wA-E2g?v=goprev

  • Adding the option to render the bar, before calling Add()

    Adding the option to render the bar, before calling Add()

    I've introduced a new function to call to render the blank bar. I've refrained from adding it as an option, since the current API doesn't easily allow for setting options. I've also refrained from adding it by default as I didn't wanted to introduce a backwards incompatible change.

    
    b := progressbar.New(10)
    b.RenderBlank()
    ticker := time.NewTicker(1 * time.Second)
    now := time.Now()
    for t := range ticker.C {
    	b.Add(1)
    	if t.Sub(now).Seconds() >= 10 {
    		break
    	}
    }
    
    ticker.Stop()
    
  • feature/allow-custom-spinners

    feature/allow-custom-spinners

    Description

    This PR makes the spinner type custom so that you can use one of the 76 preset spinners or any custom animation. To do this, the OptionSpinnerType now accepts a []string instead of an int, so any animation can be passed. If you want to use one of the presets, just use the new func GetPresetSpinner(spinnerType int) which gives you access to the previous standard animations.

  • docker logs -f does not show progress bar

    docker logs -f does not show progress bar

    When trying to follow docker container logs with "docker logs container -f" the progress bar is not showing even though by default it's following StdOut and the progress bar is writing to os.Stdout

    main.go

    package main
    
    import (
    	"time"
    
    	"github.com/schollz/progressbar/v3"
    )
    
    func main() {
    	bar := progressbar.Default(100)
    
    	for i := 0; i < 100; i++ {
    		bar.Add(1)
    		time.Sleep(1 * time.Second)
    	}
    }
    

    Dockerfile

    FROM golang:1.18-alpine
    WORKDIR /app
    COPY go.mod ./
    COPY go.sum ./
    RUN go mod download
    COPY *.go ./
    RUN go build -o /application
    CMD [ "/application" ]
    

    Building:

    docker build -t app . Running:

    docker run -d -t app Follow logs:

    docker logs 0b26e53d7321 -f

  • ChangeMax not working

    ChangeMax not working

    I start my progress bar as indeterminate for the first query that retrieves the count.
    Then I set the count as the new max, my log line does show the correct number.
    The progress bar never changes from indeterminate to an actual progress bar.

    Here is my setup.

    bar := progressbar.NewOptions(
    	-1,
    	progressbar.OptionSetDescription("Fetching messages from API"),
    	progressbar.OptionSetWriter(os.Stderr),
    	progressbar.OptionFullWidth(),
    	progressbar.OptionEnableColorCodes(true),
    	progressbar.OptionSetPredictTime(true),
    	progressbar.OptionShowCount(),
    	progressbar.OptionShowIts(),
    	progressbar.OptionShowElapsedTimeOnFinish(),
    	progressbar.OptionSetItsString("Msgs"),
    	progressbar.OptionSpinnerType(14),
    	progressbar.OptionSetRenderBlankState(true),
    )
    
    // This is just the initial query
    folderMessages := f.getMessages(client, log.Named("Messages"), queryLimit)
    msgCount := *folderMessages.GetOdataCount()
    log.With(zap.Int64("Count", msgCount)).Info("Message Count")
    bar.ChangeMax64(msgCount)
    
    // Proceeds to the processing loop
    

    And inside my loop.

    if err := bar.Add(1); err != nil {
    	log.With(zap.Error(err)).Error("Failed to increment progress bar!")
    }
    
  • How to display all steps in spinner

    How to display all steps in spinner

    I'm trying this code:

    func main() {
    	bar := progressbar.NewOptions(-1,
    		progressbar.OptionSetDescription("spinnertest"),
    		progressbar.OptionShowIts(),
    		progressbar.OptionShowCount(),
    		progressbar.OptionSpinnerType(7),
    	)
    
    	for i:=0; i < 100; i++ {
    		bar.Add(1)
    		time.Sleep(1 * time.Second)
    	}
    }
    

    And I'm expecting that each time it updates, it would move 1 step in the spinner, instead it just flops back and forth between 2 values. If I use spinners with more steps, 1 second intervals also seem to skip steps.

    If I change the delay to be time.Sleep(500 * time.Millisecond) it does work and I see all 4 steps, but my proposed usage would be at 1 second intervals. On the other hand, if I go to time.Sleep(2 * time.Second) I get no change in the spinner, although in all situations the count increments correctly.

    Is there somewhere I need to set the "total time lapse" of a spinner rotation?

  • feat!: Add ability to use custom style for bytes showing

    feat!: Add ability to use custom style for bytes showing

    I have added ability to customize way of bytes show by adding an option.

    func ExampleOptionUseCustomBytesShowWithMax() {
    	bar := NewOptions(100,
    		OptionSetWidth(10),
    		OptionShowIts(),
    		OptionShowCount(),
    		OptionSetElapsedTime(false), OptionUseCustomBytesShow(func(f float64, i int64) string {
    			return fmt.Sprintf("%.0f of %d items", f, i)
    		}))
    	bar.Reset()
    	time.Sleep(1 * time.Second)
    	bar.Add(5)
    
    	// Output:
    	// -  (5 of 100 items, 5 it/s)
    }
    

    closes #138

Console progress bar for Golang

Terminal progress bar for Go Installation go get github.com/cheggaaa/pb/v3 Documentation for v1 bar available here Quick start package main import (

Jan 9, 2023
progress_bar creates a single customizable progress bar for Linux terminal.
progress_bar creates a single customizable progress bar for Linux terminal.

progress_bar Go Progress Bar Features progress_bar creates a single customizable progress bar for Linux terminal. Installation go get -u github.com/er

Aug 12, 2022
Go simple progress bar writing to output
Go simple progress bar writing to output

?? progress-go Go simple progress bar writing to output ?? ABOUT Contributors: Rafał Lorenz Want to contribute ? Feel free to send pull requests! Have

Oct 30, 2022
🍫 A customisable, universally compatible terminal status bar
🍫 A customisable, universally compatible terminal status bar

Shox: Terminal Status Bar A customisable terminal status bar with universal shell/terminal compatibility. Currently works on Mac/Linux. Installation N

Dec 27, 2022
A cli that shows a GitHub-like language usage statistics bar.
A cli that shows a GitHub-like language usage statistics bar.

barley A cli that shows a GitHub-like language usage statistics bar. barley analyses the programming languages used in a directory and creates a used

Jan 8, 2022
Custom i3status bar built with Barista.

Custom i3status Customized i3status command built with Barista. Includes a Barista module for strongSwan. Install go install enr0n.net/i3status/cmd/i3

Jan 10, 2022
Go (golang) package with 70+ configurable terminal spinner/progress indicators.
Go (golang) package with 70+ configurable terminal spinner/progress indicators.

Spinner spinner is a simple package to add a spinner / progress indicator to any terminal application. Examples can be found below as well as full exa

Dec 26, 2022
Golang-video-screensaver - A work in progress Microsoft Windows video screensaver implemented in Go

golang-video-screensaver A work in progress Microsoft Windows video screensaver

Sep 5, 2022
Utilities to prettify console output of tables, lists, progress-bars, text, etc.
Utilities to prettify console output of tables, lists, progress-bars, text, etc.

go-pretty Utilities to prettify console output of tables, lists, progress-bars, text, etc. Table Pretty-print tables into ASCII/Unicode strings.

Dec 29, 2022
hierarchical progress bars in terminal on steroids
hierarchical progress bars in terminal on steroids

Echelon - hierarchical progress in terminals Cross-platform library to organize logs in a hierarchical structure. Here is an example how it looks for

Nov 26, 2022
Print day progress in your terminal

Day progress Print day progress in your terminal Install go install github.com/tsivinsky/day-progress@latest Usage day-progress By default, day-progre

Jan 10, 2022
cTRL is a server for remote execution of pending tasks and commands in real time, supporting a queue with continuous thread limiting and throttling.

Документация на русском: https://github.com/eltaline/ctrl/blob/master/README-RUS.md cTRL is a server written in Go language that uses a modified versi

Mar 3, 2022
A Go package for converting RGB and other color formats/colorspaces into DMC thread colors (DMC color name and floss number)

go-c2dmc A Go package for converting RGB and other color formats/colorspaces into DMC thread colors (DMC color name and floss number). Implemented as

Jul 25, 2022
Basic command line example using golang grpc client tools

This is a basic command line interface that demonstrates using the golang GRPC API. The API is reused between dishy and the wifi router, however both

Jan 3, 2023
Source code of a YouTube tutorial about writing terminal applications with Golang

Bubble Tea Demo 00 Source code of a YouTube tutorial about writing terminal applications with Golang by using Bubble Tea. Contains a simple counter ap

Nov 10, 2022
A general purpose project template for golang CLI applications

golang-cli-template A general purpose project template for golang CLI applications golang-cli-template Features Project Layout How to use this templat

Jan 15, 2022
a python command-line tool which draws basic graphs in the terminal
a python command-line tool which draws basic graphs in the terminal

Termgraph A command-line tool that draws basic graphs in the terminal, written in Python. Graph types supported: Bar Graphs Color charts Multi-variabl

Dec 30, 2022
A Go package for drawing basic graphics in a terminal

Tgraph Tgraph is a Go package for drawing basic graphics in a terminal. It was inspired by termgraph. Graph types supported: Bar Graphs Multi-variable

Nov 14, 2022
A template and a functioning example for a basic JFrog CLI plugin

hello-frog About this plugin This plugin is a template and a functioning example for a basic JFrog CLI plugin. This README shows the expected structur

Dec 21, 2021