Codebase list golang-github-vbauerster-mpb / 9fad571
refactoring: SpinnerStyleComposer Vladimir Bauer 5 years ago
1 changed file(s) with 56 addition(s) and 34 deletion(s). Raw diff Collapse all Expand all
33 "io"
44 "strings"
55
6 "github.com/acarl005/stripansi"
67 "github.com/mattn/go-runewidth"
78 "github.com/vbauerster/mpb/v6/decor"
89 "github.com/vbauerster/mpb/v6/internal"
910 )
1011
11 // SpinnerAlignment enum.
12 type SpinnerAlignment int
13
14 // SpinnerAlignment kinds.
1512 const (
16 SpinnerOnLeft SpinnerAlignment = iota
17 SpinnerOnMiddle
18 SpinnerOnRight
13 positionLeft = 1 + iota
14 positionRight
1915 )
2016
21 // SpinnerDefaultStyle is a style for rendering a spinner.
22 var SpinnerDefaultStyle = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
23
24 type spinnerFiller struct {
25 frames []string
26 count uint
27 alignment SpinnerAlignment
17 // SpinnerStyleComposer interface.
18 type SpinnerStyleComposer interface {
19 BarFillerBuilder
20 PositionLeft() SpinnerStyleComposer
21 PositionRight() SpinnerStyleComposer
2822 }
2923
30 // NewSpinnerFiller returns a BarFiller implementation which renders
31 // a spinner. If style is nil or zero length, SpinnerDefaultStyle is
32 // applied. To be used with `*Progress.Add(...) *Bar` method.
33 func NewSpinnerFiller(style []string, alignment SpinnerAlignment) BarFiller {
34 if len(style) == 0 {
35 style = SpinnerDefaultStyle
36 }
37 filler := &spinnerFiller{
38 frames: style,
39 alignment: alignment,
40 }
41 return filler
24 type sFiller struct {
25 count uint
26 position uint
27 frames []string
4228 }
4329
44 func (s *spinnerFiller) Fill(w io.Writer, reqWidth int, stat decor.Statistics) {
45 width := internal.CheckRequestedWidth(reqWidth, stat.AvailableWidth)
30 type spinnerStyle struct {
31 position uint
32 frames []string
33 }
34
35 // SpinnerStyle constructs default spinner style which can be altered via
36 // SpinnerStyleComposer interface.
37 func SpinnerStyle(frames ...string) SpinnerStyleComposer {
38 ss := new(spinnerStyle)
39 if len(frames) != 0 {
40 ss.frames = append(ss.frames, frames...)
41 } else {
42 ss.frames = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
43 }
44 return ss
45 }
46
47 func (s *spinnerStyle) PositionLeft() SpinnerStyleComposer {
48 s.position = positionLeft
49 return s
50 }
51
52 func (s *spinnerStyle) PositionRight() SpinnerStyleComposer {
53 s.position = positionRight
54 return s
55 }
56
57 func (s *spinnerStyle) Build() BarFiller {
58 sf := &sFiller{
59 position: s.position,
60 frames: s.frames,
61 }
62 return sf
63 }
64
65 func (s *sFiller) Fill(w io.Writer, width int, stat decor.Statistics) {
66 width = internal.CheckRequestedWidth(width, stat.AvailableWidth)
4667
4768 frame := s.frames[s.count%uint(len(s.frames))]
48 frameWidth := runewidth.StringWidth(frame)
69 frameWidth := runewidth.StringWidth(stripansi.Strip(frame))
4970
5071 if width < frameWidth {
5172 return
5273 }
5374
54 switch rest := width - frameWidth; s.alignment {
55 case SpinnerOnLeft:
75 rest := width - frameWidth
76 switch s.position {
77 case positionLeft:
5678 io.WriteString(w, frame+strings.Repeat(" ", rest))
57 case SpinnerOnMiddle:
79 case positionRight:
80 io.WriteString(w, strings.Repeat(" ", rest)+frame)
81 default:
5882 str := strings.Repeat(" ", rest/2) + frame + strings.Repeat(" ", rest/2+rest%2)
5983 io.WriteString(w, str)
60 case SpinnerOnRight:
61 io.WriteString(w, strings.Repeat(" ", rest)+frame)
6284 }
6385 s.count++
6486 }