1
0
mirror of https://github.com/containers/skopeo.git synced 2025-05-11 01:15:29 +00:00
skopeo/vendor/github.com/vbauerster/mpb/v8/bar_filler_bar.go
renovate[bot] 299848119c
fix(deps): update module github.com/containers/image/v5 to v5.32.0
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-27 15:02:36 +00:00

291 lines
6.8 KiB
Go

package mpb
import (
"io"
"github.com/mattn/go-runewidth"
"github.com/vbauerster/mpb/v8/decor"
"github.com/vbauerster/mpb/v8/internal"
)
const (
iLbound = iota
iRbound
iRefiller
iFiller
iTip
iPadding
components
)
var defaultBarStyle = [components]string{"[", "]", "+", "=", ">", "-"}
// BarStyleComposer interface.
type BarStyleComposer interface {
BarFillerBuilder
Lbound(string) BarStyleComposer
LboundMeta(func(string) string) BarStyleComposer
Rbound(string) BarStyleComposer
RboundMeta(func(string) string) BarStyleComposer
Filler(string) BarStyleComposer
FillerMeta(func(string) string) BarStyleComposer
Refiller(string) BarStyleComposer
RefillerMeta(func(string) string) BarStyleComposer
Padding(string) BarStyleComposer
PaddingMeta(func(string) string) BarStyleComposer
Tip(frames ...string) BarStyleComposer
TipMeta(func(string) string) BarStyleComposer
TipOnComplete() BarStyleComposer
Reverse() BarStyleComposer
}
type component struct {
width int
bytes []byte
}
type flushSection struct {
meta func(io.Writer, []byte) error
bytes []byte
}
type bFiller struct {
components [components]component
meta [components]func(io.Writer, []byte) error
flush func(io.Writer, ...flushSection) error
tipOnComplete bool
tip struct {
frames []component
count uint
}
}
type barStyle struct {
style [components]string
metaFuncs [components]func(io.Writer, []byte) error
tipFrames []string
tipOnComplete bool
rev bool
}
// BarStyle constructs default bar style which can be altered via
// BarStyleComposer interface.
func BarStyle() BarStyleComposer {
bs := barStyle{
style: defaultBarStyle,
tipFrames: []string{defaultBarStyle[iTip]},
}
for i := range bs.metaFuncs {
bs.metaFuncs[i] = defaultMeta
}
return bs
}
func (s barStyle) Lbound(bound string) BarStyleComposer {
s.style[iLbound] = bound
return s
}
func (s barStyle) LboundMeta(fn func(string) string) BarStyleComposer {
s.metaFuncs[iLbound] = makeMetaFunc(fn)
return s
}
func (s barStyle) Rbound(bound string) BarStyleComposer {
s.style[iRbound] = bound
return s
}
func (s barStyle) RboundMeta(fn func(string) string) BarStyleComposer {
s.metaFuncs[iRbound] = makeMetaFunc(fn)
return s
}
func (s barStyle) Filler(filler string) BarStyleComposer {
s.style[iFiller] = filler
return s
}
func (s barStyle) FillerMeta(fn func(string) string) BarStyleComposer {
s.metaFuncs[iFiller] = makeMetaFunc(fn)
return s
}
func (s barStyle) Refiller(refiller string) BarStyleComposer {
s.style[iRefiller] = refiller
return s
}
func (s barStyle) RefillerMeta(fn func(string) string) BarStyleComposer {
s.metaFuncs[iRefiller] = makeMetaFunc(fn)
return s
}
func (s barStyle) Padding(padding string) BarStyleComposer {
s.style[iPadding] = padding
return s
}
func (s barStyle) PaddingMeta(fn func(string) string) BarStyleComposer {
s.metaFuncs[iPadding] = makeMetaFunc(fn)
return s
}
func (s barStyle) Tip(frames ...string) BarStyleComposer {
if len(frames) != 0 {
s.tipFrames = frames
}
return s
}
func (s barStyle) TipMeta(fn func(string) string) BarStyleComposer {
s.metaFuncs[iTip] = makeMetaFunc(fn)
return s
}
func (s barStyle) TipOnComplete() BarStyleComposer {
s.tipOnComplete = true
return s
}
func (s barStyle) Reverse() BarStyleComposer {
s.rev = true
return s
}
func (s barStyle) Build() BarFiller {
bf := &bFiller{
meta: s.metaFuncs,
tipOnComplete: s.tipOnComplete,
}
bf.components[iLbound] = component{
width: runewidth.StringWidth(s.style[iLbound]),
bytes: []byte(s.style[iLbound]),
}
bf.components[iRbound] = component{
width: runewidth.StringWidth(s.style[iRbound]),
bytes: []byte(s.style[iRbound]),
}
bf.components[iFiller] = component{
width: runewidth.StringWidth(s.style[iFiller]),
bytes: []byte(s.style[iFiller]),
}
bf.components[iRefiller] = component{
width: runewidth.StringWidth(s.style[iRefiller]),
bytes: []byte(s.style[iRefiller]),
}
bf.components[iPadding] = component{
width: runewidth.StringWidth(s.style[iPadding]),
bytes: []byte(s.style[iPadding]),
}
bf.tip.frames = make([]component, len(s.tipFrames))
for i, t := range s.tipFrames {
bf.tip.frames[i] = component{
width: runewidth.StringWidth(t),
bytes: []byte(t),
}
}
if s.rev {
bf.flush = func(w io.Writer, sections ...flushSection) error {
for i := len(sections) - 1; i >= 0; i-- {
if s := sections[i]; len(s.bytes) != 0 {
err := s.meta(w, s.bytes)
if err != nil {
return err
}
}
}
return nil
}
} else {
bf.flush = func(w io.Writer, sections ...flushSection) error {
for _, s := range sections {
if len(s.bytes) != 0 {
err := s.meta(w, s.bytes)
if err != nil {
return err
}
}
}
return nil
}
}
return bf
}
func (s *bFiller) Fill(w io.Writer, stat decor.Statistics) error {
width := internal.CheckRequestedWidth(stat.RequestedWidth, stat.AvailableWidth)
// don't count brackets as progress
width -= (s.components[iLbound].width + s.components[iRbound].width)
if width < 0 {
return nil
}
err := s.meta[iLbound](w, s.components[iLbound].bytes)
if err != nil {
return err
}
if width == 0 {
return s.meta[iRbound](w, s.components[iRbound].bytes)
}
var tip component
var refilling, filling, padding []byte
var fillCount int
curWidth := int(internal.PercentageRound(stat.Total, stat.Current, int64(width)))
if curWidth != 0 {
if !stat.Completed || s.tipOnComplete {
tip = s.tip.frames[s.tip.count%uint(len(s.tip.frames))]
s.tip.count++
fillCount += tip.width
}
switch refWidth := 0; {
case stat.Refill != 0:
refWidth = int(internal.PercentageRound(stat.Total, stat.Refill, int64(width)))
curWidth -= refWidth
refWidth += curWidth
fallthrough
default:
for w := s.components[iFiller].width; curWidth-fillCount >= w; fillCount += w {
filling = append(filling, s.components[iFiller].bytes...)
}
for w := s.components[iRefiller].width; refWidth-fillCount >= w; fillCount += w {
refilling = append(refilling, s.components[iRefiller].bytes...)
}
}
}
for w := s.components[iPadding].width; width-fillCount >= w; fillCount += w {
padding = append(padding, s.components[iPadding].bytes...)
}
for w := 1; width-fillCount >= w; fillCount += w {
padding = append(padding, "…"...)
}
err = s.flush(w,
flushSection{s.meta[iRefiller], refilling},
flushSection{s.meta[iFiller], filling},
flushSection{s.meta[iTip], tip.bytes},
flushSection{s.meta[iPadding], padding},
)
if err != nil {
return err
}
return s.meta[iRbound](w, s.components[iRbound].bytes)
}
func makeMetaFunc(fn func(string) string) func(io.Writer, []byte) error {
return func(w io.Writer, p []byte) (err error) {
_, err = io.WriteString(w, fn(string(p)))
return err
}
}
func defaultMeta(w io.Writer, p []byte) (err error) {
_, err = w.Write(p)
return err
}