Created
February 14, 2022 07:02
-
-
Save mlanin/fab7a5610f0d2ce481688da1af134dab to your computer and use it in GitHub Desktop.
Create a nice progress bar using symbols
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package progress_bar | |
import ( | |
"strings" | |
"text/template" | |
) | |
// Options can be used to customize look of the progress bar. DefaultProgressOptions() has pretty good defaults. | |
type Options struct { | |
Fill string // The character(s) used to fill in the progress bar | |
Empty string // The character(s) used to indicate empty space at the end of progress bar | |
Width int // How many characters wide the progress bar should be. A value of 10 looks good on slack phone clients. | |
Msg *template.Template // The message template that will be sent to slack. Uses text/template for creating templates. | |
} | |
var defaultTemplate = template.Must(template.New("default_progress_msg").Parse("`{{.ProgBar}}` {{.Done}}% ({{.Pos}}/{{.Total}})")) | |
// DefaultProgressOptions creates an Options struct with decent defaults. | |
func DefaultProgressOptions() *Options { | |
return &Options{ | |
Fill: "🟦", | |
Empty: "⬜", | |
Width: 10, // Looks good on slack phone clients | |
Msg: defaultTemplate, | |
} | |
} | |
type Progress struct { | |
Opts *Options | |
} | |
// NewProgress creates a new progress bar. Uses default options if non were set | |
func NewProgress(opts *Options) *Progress { | |
progress := &Progress{ | |
Opts: opts, | |
} | |
if opts == nil { | |
progress.Opts = DefaultProgressOptions() | |
} | |
return progress | |
} | |
func (p *Progress) drawBar(pos int, total int) string { | |
if pos == 0 || total == 0 { | |
return strings.Repeat(p.Opts.Empty, p.Opts.Width) | |
} | |
done := pos * 100 / total | |
bar := strings.Repeat(p.Opts.Fill, done/p.Opts.Width) | |
bar += strings.Repeat(p.Opts.Empty, p.Opts.Width-len([]rune(bar))) | |
return bar | |
} | |
func (p *Progress) GetProgress(pos int, total int) (string, error) { | |
msg := &strings.Builder{} | |
done := 0 | |
if total != 0 { | |
done = pos * 100 / total | |
} | |
data := map[string]interface{}{ | |
"ProgBar": p.drawBar(pos, total), | |
"Done": done, | |
"Pos": pos, | |
"Total": total, | |
"Complete": pos == total, | |
} | |
err := p.Opts.Msg.Execute(msg, data) | |
return msg.String(), err | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment