func (p *Progress) Display() {
	if p.Format == "" {
		p.Format = DefFormat
	}
	p.render(p.buildLine())
}
Display outputs the current progress string.
package progress
import (
	"fmt"
	"regexp"
	"strings"
	"time"
	"github.com/gookit/color"
)
var widgetMatch = regexp.MustCompile(`{@([\w]+)(?::([\w-]+))?}`)
type WidgetFunc func(p *Progress) string
type Progresser interface {
	Start(maxSteps ...int)
	Advance(steps ...uint)
	AdvanceTo(step uint)
	Finish(msg ...string)
	Bound() interface{}
}
type Progress struct {
	Format string
	Newline bool
	MaxSteps uint
	StepWidth uint8
	Overwrite bool
	RedrawFreq uint8
	Widgets map[string]WidgetFunc
	Messages map[string]string
	step uint
	bound interface{}
	started bool
	percent float32
	firstRun bool
	startedAt  time.Time
	finishedAt time.Time
}
func New(maxSteps ...int) *Progress {
	var max uint
	if len(maxSteps) > 0 {
		max = uint(maxSteps[0])
	}
	return &Progress{
		Format:    DefFormat,
		MaxSteps:  max,
		StepWidth: 3,
		Overwrite: true,
		Widgets: make(map[string]WidgetFunc),
		Messages: map[string]string{"message": ""},
	}
}
func NewWithConfig(fn func(p *Progress), maxSteps ...int) *Progress {
	return New(maxSteps...).Config(fn)
}
func RenderFormat(f string) func(p *Progress) {
	return func(p *Progress) {
		p.Format = f
	}
}
func MaxSteps(maxStep int) func(p *Progress) {
	return func(p *Progress) {
		p.MaxSteps = uint(maxStep)
	}
}
func (p *Progress) Config(fn func(p *Progress)) *Progress {
	fn(p)
	return p
}
func (p *Progress) WithOptions(fns ...func(p *Progress)) *Progress {
	if len(fns) > 0 {
		for _, fn := range fns {
			fn(p)
		}
	}
	return p
}
func (p *Progress) WithMaxSteps(maxSteps ...int) *Progress {
	if len(maxSteps) > 0 {
		p.MaxSteps = uint(maxSteps[0])
	}
	return p
}
func (p *Progress) Binding(data interface{}) *Progress {
	p.bound = data
	return p
}
func (p *Progress) Bound() interface{} {
	return p.bound
}
func (p *Progress) AddMessage(name, message string) {
	p.Messages[name] = message
}
func (p *Progress) AddMessages(msgMap map[string]string) {
	if p.Messages == nil {
		p.Messages = make(map[string]string)
	}
	for name, message := range msgMap {
		p.Messages[name] = message
	}
}
func (p *Progress) AddWidget(name string, handler WidgetFunc) *Progress {
	if _, ok := p.Widgets[name]; !ok {
		p.Widgets[name] = handler
	}
	return p
}
func (p *Progress) SetWidget(name string, handler WidgetFunc) *Progress {
	p.Widgets[name] = handler
	return p
}
func (p *Progress) AddWidgets(widgets map[string]WidgetFunc) {
	if p.Widgets == nil {
		p.Widgets = make(map[string]WidgetFunc)
	}
	for name, handler := range widgets {
		p.AddWidget(name, handler)
	}
}
func (p *Progress) Start(maxSteps ...int) {
	if p.started {
		panic("Progress bar already started")
	}
	p.init(maxSteps...)
	p.Display()
}
func (p *Progress) init(maxSteps ...int) {
	p.step = 0
	p.percent = 0.0
	p.started = true
	p.firstRun = true
	p.startedAt = time.Now()
	if p.RedrawFreq == 0 {
		p.RedrawFreq = 1
	}
	if len(maxSteps) > 0 {
		p.MaxSteps = uint(maxSteps[0])
	}
	if p.MaxSteps > 0 {
		maxStepsLen := len(fmt.Sprint(p.MaxSteps))
		p.StepWidth = uint8(maxStepsLen)
	}
	if p.StepWidth == 0 {
		p.StepWidth = 3
	}
	p.AddWidgets(builtinWidgets)
}
func (p *Progress) Advance(steps ...uint) {
	p.checkStart()
	var step uint = 1
	if len(steps) > 0 && steps[0] > 0 {
		step = steps[0]
	}
	p.AdvanceTo(p.step + step)
}
func (p *Progress) AdvanceTo(step uint) {
	p.checkStart()
	if p.MaxSteps > 0 && step > p.MaxSteps {
		p.MaxSteps = step
	}
	freq := uint(p.RedrawFreq)
	prevPeriod := int(p.step / freq)
	currPeriod := int(step / freq)
	p.step = step
	if p.MaxSteps > 0 {
		p.percent = float32(p.step) / float32(p.MaxSteps)
	}
	if prevPeriod != currPeriod || p.MaxSteps == step {
		p.Display()
	}
}
func (p *Progress) Finish(message ...string) {
	p.checkStart()
	p.finishedAt = time.Now()
	if p.MaxSteps == 0 {
		p.MaxSteps = p.step
	}
	if p.step == p.MaxSteps && !p.Overwrite {
		return
	}
	p.AdvanceTo(p.MaxSteps)
	if len(message) > 0 {
		p.render(message[0])
	}
	fmt.Println()  
}