Codebase list golang-github-vbauerster-mpb / d3b78c9
refactoring bar filler Vladimir Bauer 6 years ago
6 changed file(s) with 127 addition(s) and 185 deletion(s). Raw diff Collapse all Expand all
1717 rRefill
1818 )
1919
20 var defaultBarStyle = "[=>-]<+"
20 // DefaultBarStyle is applied when bar constructed with *Progress.AddBar method.
21 //
22 // '1th rune' stands for left boundary rune
23 //
24 // '2th rune' stands for fill rune
25 //
26 // '3th rune' stands for tip rune
27 //
28 // '4th rune' stands for empty rune
29 //
30 // '5th rune' stands for right boundary rune
31 //
32 // '6th rune' stands for reverse tip rune
33 //
34 // '7th rune' stands for refill rune
35 //
36 const DefaultBarStyle string = "[=>-]<+"
2137
2238 type barFiller struct {
23 format [][]byte
24 refillAmount int64
25 reverse bool
26 noBrackets bool
39 format [][]byte
40 tip []byte
41 refill int64
42 reverse bool
43 flush func(w io.Writer, bb [][]byte)
2744 }
2845
29 // NewBarFiller bar Filler used with *Progress.AddBar
30 func NewBarFiller() Filler {
31 filler := &barFiller{
32 format: make([][]byte, utf8.RuneCountInString(defaultBarStyle)),
46 // NewBarFiller constucts mpb.Filler, to be used with *Progress.Add method.
47 func NewBarFiller(style string, reverse bool) Filler {
48 if style == "" {
49 style = DefaultBarStyle
3350 }
34 filler.setStyle(defaultBarStyle)
35 return filler
51 bf := &barFiller{
52 format: make([][]byte, utf8.RuneCountInString(style)),
53 }
54 bf.SetStyle(style)
55 bf.SetReverse(reverse)
56 return bf
3657 }
3758
38 func (s *barFiller) setStyle(style string) {
59 func (s *barFiller) SetStyle(style string) {
3960 if !utf8.ValidString(style) {
4061 return
4162 }
4465 src = append(src, []byte(string(r)))
4566 }
4667 copy(s.format, src)
68 if s.reverse {
69 s.tip = s.format[rRevTip]
70 } else {
71 s.tip = s.format[rTip]
72 }
73 }
74
75 func (s *barFiller) SetReverse(reverse bool) {
76 if reverse {
77 s.tip = s.format[rRevTip]
78 s.flush = func(w io.Writer, bb [][]byte) {
79 for i := len(bb) - 1; i >= 0; i-- {
80 w.Write(bb[i])
81 }
82 }
83 } else {
84 s.tip = s.format[rTip]
85 s.flush = func(w io.Writer, bb [][]byte) {
86 for i := 0; i < len(bb); i++ {
87 w.Write(bb[i])
88 }
89 }
90 }
91 s.reverse = reverse
4792 }
4893
4994 func (s *barFiller) SetRefill(amount int64) {
50 s.refillAmount = amount
95 s.refill = amount
5196 }
5297
5398 func (s *barFiller) Fill(w io.Writer, width int, stat *decor.Statistics) {
54
55 if !s.noBrackets {
56 // don't count rLeft and rRight as progress
57 width -= 2
58 if width < 2 {
59 return
60 }
61 w.Write(s.format[rLeft])
62 defer w.Write(s.format[rRight])
99 // don't count rLeft and rRight as progress
100 width -= 2
101 if width < 2 {
102 return
63103 }
104 w.Write(s.format[rLeft])
105 defer w.Write(s.format[rRight])
64106
65107 bb := make([][]byte, width)
66108
70112 bb[i] = s.format[rFill]
71113 }
72114
73 if s.refillAmount > 0 {
115 if s.refill > 0 {
74116 var rwidth int
75 if s.refillAmount > stat.Current {
117 if s.refill > stat.Current {
76118 rwidth = cwidth
77119 } else {
78 rwidth = int(internal.PercentageRound(stat.Total, int64(s.refillAmount), width))
120 rwidth = int(internal.PercentageRound(stat.Total, int64(s.refill), width))
79121 }
80122 for i := 0; i < rwidth; i++ {
81123 bb[i] = s.format[rRefill]
83125 }
84126
85127 if cwidth > 0 && cwidth < width {
86 bb[cwidth-1] = s.format[rTip]
128 bb[cwidth-1] = s.tip
87129 }
88130
89131 for i := cwidth; i < width; i++ {
90132 bb[i] = s.format[rEmpty]
91133 }
92134
93 if s.reverse {
94 if cwidth > 0 && cwidth < width {
95 bb[cwidth-1] = s.format[rRevTip]
96 }
97 for i := len(bb) - 1; i >= 0; i-- {
98 w.Write(bb[i])
99 }
100 } else {
101 for i := 0; i < len(bb); i++ {
102 w.Write(bb[i])
103 }
104 }
135 s.flush(w, bb)
105136 }
129129 }
130130 }
131131
132 // BarStyle sets custom bar style, default one is "[=>-]<+".
133 //
134 // '[' left bracket rune
135 //
136 // '=' fill rune
137 //
138 // '>' tip rune
139 //
140 // '-' empty rune
141 //
142 // ']' right bracket rune
143 //
144 // '<' reverse tip rune, used when BarReverse option is set
145 //
146 // '+' refill rune, used when *Bar.SetRefill(int64) is called
147 //
148 // It's ok to provide first five runes only, for example BarStyle("╢▌▌░╟").
149 // To omit left and right bracket runes, either set style as " =>- "
150 // or use BarNoBrackets option.
132 // BarStyle overrides mpb.DefaultBarStyle, for example BarStyle("╢▌▌░╟").
133 // If you need to override `reverse tip` and `refill rune` set 6th and
134 // 7th rune respectively, for example BarStyle("[=>-]<+").
151135 func BarStyle(style string) BarOption {
152 chk := func(filler Filler) (interface{}, bool) {
153 if style == "" {
154 return nil, false
155 }
156 t, ok := filler.(*barFiller)
157 return t, ok
158 }
159 cb := func(t interface{}) {
160 t.(*barFiller).setStyle(style)
161 }
162 return MakeFillerTypeSpecificBarOption(chk, cb)
163 }
164
165 // BarNoBrackets omits left and right edge runes of the bar. Edges are
166 // brackets in default bar style, hence the name of the option.
167 func BarNoBrackets() BarOption {
168 chk := func(filler Filler) (interface{}, bool) {
169 t, ok := filler.(*barFiller)
170 return t, ok
171 }
172 cb := func(t interface{}) {
173 t.(*barFiller).noBrackets = true
174 }
175 return MakeFillerTypeSpecificBarOption(chk, cb)
136 if style == "" {
137 return nil
138 }
139 type styleSetter interface {
140 SetStyle(string)
141 }
142 return func(s *bState) {
143 if t, ok := s.filler.(styleSetter); ok {
144 t.SetStyle(style)
145 }
146 }
176147 }
177148
178149 // BarNoPop disables bar pop out of container. Effective when
185156
186157 // BarReverse reverse mode, bar will progress from right to left.
187158 func BarReverse() BarOption {
188 chk := func(filler Filler) (interface{}, bool) {
189 t, ok := filler.(*barFiller)
190 return t, ok
191 }
192 cb := func(t interface{}) {
193 t.(*barFiller).reverse = true
194 }
195 return MakeFillerTypeSpecificBarOption(chk, cb)
159 type revSetter interface {
160 SetReverse(bool)
161 }
162 return func(s *bState) {
163 if t, ok := s.filler.(revSetter); ok {
164 t.SetReverse(true)
165 }
166 }
196167 }
197168
198169 // SpinnerStyle sets custom spinner style.
1212 total, current int64
1313 barWidth int
1414 trimSpace bool
15 noBrackets bool
15 reverse bool
1616 rup int64
1717 want string
1818 }{
3232 trimSpace: true,
3333 want: "",
3434 },
35 {
36 name: "t,c,bw,noBrackets{60,20,80}",
37 total: 60,
38 current: 20,
39 barWidth: 80,
40 noBrackets: true,
41 want: "",
42 },
4335 },
4436 1: {
4537 {
5749 trimSpace: true,
5850 want: "",
5951 },
60 {
61 name: "t,c,bw,noBrackets{60,20,80}",
62 total: 60,
63 current: 20,
64 barWidth: 80,
65 noBrackets: true,
66 want: "",
67 },
6852 },
6953 2: {
7054 {
8266 trimSpace: true,
8367 want: "",
8468 },
85 {
86 name: "t,c,bw,noBrackets{60,20,80,true}",
87 total: 60,
88 current: 20,
89 barWidth: 80,
90 noBrackets: true,
91 want: " ",
92 },
9369 },
9470 3: {
9571 {
10783 trimSpace: true,
10884 want: "",
10985 },
110 {
111 name: "t,c,bw,trim{60,20,80,true}",
112 total: 60,
113 current: 20,
114 barWidth: 80,
115 noBrackets: true,
116 want: " - ",
117 },
11886 },
11987 4: {
12088 {
132100 trimSpace: true,
133101 want: "[>-]",
134102 },
135 {
136 name: "t,c,bw,noBrackets{60,20,80,true}",
137 total: 60,
138 current: 20,
139 barWidth: 80,
140 noBrackets: true,
141 want: " >- ",
142 },
143103 },
144104 5: {
145105 {
157117 trimSpace: true,
158118 want: "[>--]",
159119 },
160 {
161 name: "t,c,bw,noBrackets{60,20,80,true}",
162 total: 60,
163 current: 20,
164 barWidth: 80,
165 noBrackets: true,
166 want: " >-- ",
167 },
168120 },
169121 6: {
170122 {
182134 trimSpace: true,
183135 want: "[>---]",
184136 },
185 {
186 name: "t,c,bw,noBrackets{60,20,80,true}",
187 total: 60,
188 current: 20,
189 barWidth: 80,
190 noBrackets: true,
191 want: " >--- ",
192 },
193137 },
194138 7: {
195139 {
207151 trimSpace: true,
208152 want: "[=>---]",
209153 },
210 {
211 name: "t,c,bw,noBrackets{60,20,80,true}",
212 total: 60,
213 current: 20,
214 barWidth: 80,
215 noBrackets: true,
216 want: " =>--- ",
217 },
218154 },
219155 8: {
220156 {
232168 trimSpace: true,
233169 want: "[=>----]",
234170 },
235 {
236 name: "t,c,bw,noBrackets{60,20,80,true}",
237 total: 60,
238 current: 20,
239 barWidth: 80,
240 noBrackets: true,
241 want: " =>---- ",
242 },
243171 },
244172 80: {
245173 {
257185 trimSpace: true,
258186 want: "[=========================>----------------------------------------------------]",
259187 },
260 {
261 name: "t,c,bw,noBrackets{60,20,80,true}",
262 total: 60,
263 current: 20,
264 barWidth: 80,
265 noBrackets: true,
266 want: " =========================>---------------------------------------------------- ",
267 },
268188 },
269189 100: {
270190 {
311231 barWidth: 100,
312232 trimSpace: true,
313233 want: "[===============================>------------------------------------------------------------------]",
234 },
235 {
236 name: "t,c,bw,trim{100,33,100,true}",
237 total: 100,
238 current: 33,
239 barWidth: 100,
240 trimSpace: true,
241 reverse: true,
242 want: "[------------------------------------------------------------------<===============================]",
314243 },
315244 {
316245 name: "t,c,bw,rup{100,33,100,33}",
328257 rup: 33,
329258 trimSpace: true,
330259 want: "[+++++++++++++++++++++++++++++++>------------------------------------------------------------------]",
260 },
261 {
262 name: "t,c,bw,rup,trim{100,33,100,33,true}",
263 total: 100,
264 current: 33,
265 barWidth: 100,
266 rup: 33,
267 trimSpace: true,
268 reverse: true,
269 want: "[------------------------------------------------------------------<+++++++++++++++++++++++++++++++]",
331270 },
332271 {
333272 name: "t,c,bw,rup{100,40,100,32}",
382321 var tmpBuf bytes.Buffer
383322 for termWidth, cases := range testSuite {
384323 for _, tc := range cases {
385 s := newTestState()
324 s := newTestState(tc.reverse)
386325 s.width = tc.barWidth
387326 s.total = tc.total
388327 s.current = tc.current
389328 s.trimSpace = tc.trimSpace
390 s.filler.(*barFiller).noBrackets = tc.noBrackets
391329 if tc.rup > 0 {
392330 if f, ok := s.filler.(interface{ SetRefill(int64) }); ok {
393331 f.SetRefill(tc.rup)
410348 }
411349 }
412350
413 func newTestState() *bState {
351 func newTestState(reverse bool) *bState {
414352 s := &bState{
415 filler: NewBarFiller(),
353 filler: NewBarFiller(DefaultBarStyle, reverse),
416354 bufP: new(bytes.Buffer),
417355 bufB: new(bytes.Buffer),
418356 bufA: new(bytes.Buffer),
00 package mpb
11
2 var (
3 SyncWidth = syncWidth
4 DefaultBarStyle = defaultBarStyle
5 )
2 // make syncWidth func public in test
3 var SyncWidth = syncWidth
9898
9999 // AddBar creates a new progress bar and adds to the container.
100100 func (p *Progress) AddBar(total int64, options ...BarOption) *Bar {
101 return p.Add(total, NewBarFiller(), options...)
101 return p.Add(total, NewBarFiller(DefaultBarStyle, false), options...)
102102 }
103103
104104 // AddSpinner creates a new spinner bar and adds to the container.
105105 func (p *Progress) AddSpinner(total int64, alignment SpinnerAlignment, options ...BarOption) *Bar {
106 return p.Add(total, NewSpinnerFiller(alignment), options...)
106 return p.Add(total, NewSpinnerFiller(DefaultSpinnerStyle, alignment), options...)
107107 }
108108
109109 // Add creates a bar which renders itself by provided filler.
110110 // Set total to 0, if you plan to update it later.
111111 func (p *Progress) Add(total int64, filler Filler, options ...BarOption) *Bar {
112112 if filler == nil {
113 filler = NewBarFiller()
113 filler = NewBarFiller(DefaultBarStyle, false)
114114 }
115115 p.bwg.Add(1)
116116 result := make(chan *Bar)
1717 SpinnerOnRight
1818 )
1919
20 var defaultSpinnerStyle = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
20 // DefaultSpinnerStyle is applied when bar constructed with *Progress.AddSpinner method.
21 var DefaultSpinnerStyle = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
2122
2223 type spinnerFiller struct {
2324 frames []string
2526 alignment SpinnerAlignment
2627 }
2728
28 // NewSpinnerFiller spinner Filler used with *Progress.AddSpinner
29 func NewSpinnerFiller(alignment SpinnerAlignment) Filler {
29 // NewSpinnerFiller constucts mpb.Filler, to be used with *Progress.Add method.
30 func NewSpinnerFiller(style []string, alignment SpinnerAlignment) Filler {
31 if len(style) == 0 {
32 style = DefaultSpinnerStyle
33 }
3034 filler := &spinnerFiller{
31 frames: defaultSpinnerStyle,
35 frames: style,
3236 alignment: alignment,
3337 }
3438 return filler