BarFiller: use all term width by default
WithWidth
Vladimir Bauer
6 years ago
| 46 | 46 | baseF BarFiller |
| 47 | 47 | filler BarFiller |
| 48 | 48 | id int |
| 49 | width int | |
| 49 | reqWidth int | |
| 50 | 50 | total int64 |
| 51 | 51 | current int64 |
| 52 | 52 | lastN int64 |
| 321 | 321 | }() |
| 322 | 322 | |
| 323 | 323 | st := newStatistics(tw, s) |
| 324 | frame, lines := s.extender(s.draw(st), s.width, st) | |
| 324 | frame, lines := s.extender(s.draw(st), s.reqWidth, st) | |
| 325 | 325 | b.extendedLines = lines |
| 326 | 326 | |
| 327 | 327 | b.toShutdown = s.toComplete && !s.completeFlushed |
| 331 | 331 | case <-b.done: |
| 332 | 332 | s := b.cacheState |
| 333 | 333 | st := newStatistics(tw, s) |
| 334 | frame, lines := s.extender(s.draw(st), s.width, st) | |
| 334 | frame, lines := s.extender(s.draw(st), s.reqWidth, st) | |
| 335 | 335 | b.extendedLines = lines |
| 336 | 336 | b.frameCh <- frame |
| 337 | 337 | } |
| 398 | 398 | |
| 399 | 399 | s.bufA.WriteByte('\n') |
| 400 | 400 | |
| 401 | if !s.trimSpace && stat.TermWidth >= 2 { | |
| 401 | if !s.trimSpace { | |
| 402 | 402 | defer s.bufB.WriteByte(' ') |
| 403 | 403 | s.bufB.WriteByte(' ') |
| 404 | 404 | stat.OccupiedWidth += 2 |
| 405 | 405 | } |
| 406 | 406 | |
| 407 | s.filler.Fill(s.bufB, s.width, stat) | |
| 407 | s.filler.Fill(s.bufB, s.reqWidth, stat) | |
| 408 | 408 | |
| 409 | 409 | return io.MultiReader(s.bufP, s.bufB, s.bufA) |
| 410 | 410 | } |
| 84 | 84 | s.refill = amount |
| 85 | 85 | } |
| 86 | 86 | |
| 87 | func (s *barFiller) Fill(w io.Writer, width int, stat decor.Statistics) { | |
| 88 | // auto shrink | |
| 89 | if stat.OccupiedWidth+width > stat.TermWidth { | |
| 90 | width = stat.TermWidth - stat.OccupiedWidth | |
| 91 | } | |
| 92 | // don't count rLeft and rRight as progress | |
| 93 | width -= 2 | |
| 87 | func (s *barFiller) Fill(w io.Writer, reqWidth int, stat decor.Statistics) { | |
| 88 | width := internal.CalcWidthForBarFiller(reqWidth, stat.TermWidth-stat.OccupiedWidth) | |
| 89 | ||
| 90 | width -= 2 // don't count rLeft and rRight as progress | |
| 94 | 91 | if width < 2 { |
| 95 | 92 | return |
| 96 | 93 | } |
| 5 | 5 | "unicode/utf8" |
| 6 | 6 | |
| 7 | 7 | "github.com/vbauerster/mpb/v5/decor" |
| 8 | "github.com/vbauerster/mpb/v5/internal" | |
| 8 | 9 | ) |
| 9 | 10 | |
| 10 | 11 | // SpinnerAlignment enum. |
| 38 | 39 | return filler |
| 39 | 40 | } |
| 40 | 41 | |
| 41 | func (s *spinnerFiller) Fill(w io.Writer, width int, stat decor.Statistics) { | |
| 42 | // auto shrink | |
| 43 | if stat.OccupiedWidth+width > stat.TermWidth { | |
| 44 | width = stat.TermWidth - stat.OccupiedWidth | |
| 45 | } | |
| 42 | func (s *spinnerFiller) Fill(w io.Writer, reqWidth int, stat decor.Statistics) { | |
| 43 | width := internal.CalcWidthForBarFiller(reqWidth, stat.TermWidth-stat.OccupiedWidth) | |
| 46 | 44 | |
| 47 | 45 | frame := s.frames[s.count%uint(len(s.frames))] |
| 48 | 46 | frameWidth := utf8.RuneCountInString(frame) |
| 45 | 45 | // BarWidth sets bar width independent of the container. |
| 46 | 46 | func BarWidth(width int) BarOption { |
| 47 | 47 | return func(s *bState) { |
| 48 | s.width = width | |
| 48 | s.reqWidth = width | |
| 49 | 49 | } |
| 50 | 50 | } |
| 51 | 51 |
| 143 | 143 | func TestBarStyle(t *testing.T) { |
| 144 | 144 | var buf bytes.Buffer |
| 145 | 145 | customFormat := "╢▌▌░╟" |
| 146 | p := New(WithOutput(&buf)) | |
| 147 | 146 | total := 80 |
| 147 | p := New(WithOutput(&buf), WithWidth(total)) | |
| 148 | 148 | bar := p.AddBar(int64(total), BarStyle(customFormat), TrimSpace()) |
| 149 | 149 | |
| 150 | 150 | for i := 0; i < total; i++ { |
| 20 | 20 | } |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | // WithWidth sets container width. Default is 80. Bars inherit this | |
| 24 | // width, as long as no BarWidth is applied. | |
| 23 | // WithWidth sets container width. If not set underlying bars will | |
| 24 | // occupy whole term width. | |
| 25 | 25 | func WithWidth(width int) ContainerOption { |
| 26 | 26 | return func(s *pState) { |
| 27 | if width < 0 { | |
| 28 | return | |
| 29 | } | |
| 30 | s.width = width | |
| 27 | s.reqWidth = width | |
| 31 | 28 | } |
| 32 | 29 | } |
| 33 | 30 |
| 2 | 2 | import ( |
| 3 | 3 | "bytes" |
| 4 | 4 | "testing" |
| 5 | "unicode/utf8" | |
| 6 | 5 | ) |
| 7 | 6 | |
| 8 | 7 | func TestDraw(t *testing.T) { |
| 22 | 21 | total: 60, |
| 23 | 22 | current: 20, |
| 24 | 23 | barWidth: 80, |
| 25 | want: "", | |
| 24 | want: " ", | |
| 26 | 25 | }, |
| 27 | 26 | { |
| 28 | 27 | name: "t,c,bw{60,20,80}trim", |
| 39 | 38 | total: 60, |
| 40 | 39 | current: 20, |
| 41 | 40 | barWidth: 80, |
| 42 | want: "", | |
| 41 | want: " ", | |
| 43 | 42 | }, |
| 44 | 43 | { |
| 45 | 44 | name: "t,c,bw{60,20,80}trim", |
| 322 | 321 | for termWidth, cases := range testSuite { |
| 323 | 322 | for _, tc := range cases { |
| 324 | 323 | s := newTestState(tc.reverse) |
| 325 | s.width = tc.barWidth | |
| 324 | s.reqWidth = tc.barWidth | |
| 326 | 325 | s.total = tc.total |
| 327 | 326 | s.current = tc.current |
| 328 | 327 | s.trimSpace = tc.trimSpace |
| 336 | 335 | by := tmpBuf.Bytes() |
| 337 | 336 | by = by[:len(by)-1] |
| 338 | 337 | |
| 339 | if utf8.RuneCount(by) > termWidth { | |
| 340 | t.Errorf("termWidth:%d %q barWidth:%d overflow termWidth\n", termWidth, tc.name, utf8.RuneCount(by)) | |
| 341 | } | |
| 342 | ||
| 343 | 338 | got := string(by) |
| 344 | 339 | if got != tc.want { |
| 345 | 340 | t.Errorf("termWidth:%d %q want: %q %d, got: %q %d\n", termWidth, tc.name, tc.want, len(tc.want), got, len(got)) |
| 15 | 15 | func PercentageRound(total, current int64, width int) float64 { |
| 16 | 16 | return math.Round(Percentage(total, current, width)) |
| 17 | 17 | } |
| 18 | ||
| 19 | func CalcWidthForBarFiller(reqWidth, available int) int { | |
| 20 | if reqWidth <= 0 || reqWidth >= available { | |
| 21 | return available | |
| 22 | } | |
| 23 | return reqWidth | |
| 24 | } |
| 18 | 18 | const ( |
| 19 | 19 | // default RefreshRate |
| 20 | 20 | prr = 120 * time.Millisecond |
| 21 | // default width | |
| 22 | pwidth = 80 | |
| 23 | 21 | ) |
| 24 | 22 | |
| 25 | 23 | // Progress represents the container that renders Progress bars |
| 45 | 43 | |
| 46 | 44 | // following are provided/overrided by user |
| 47 | 45 | idCount int |
| 48 | width int | |
| 46 | reqWidth int | |
| 49 | 47 | popCompleted bool |
| 50 | 48 | rr time.Duration |
| 51 | 49 | uwg *sync.WaitGroup |
| 69 | 67 | func NewWithContext(ctx context.Context, options ...ContainerOption) *Progress { |
| 70 | 68 | s := &pState{ |
| 71 | 69 | bHeap: priorityQueue{}, |
| 72 | width: pwidth, | |
| 73 | 70 | rr: prr, |
| 74 | 71 | parkedBars: make(map[*Bar]*Bar), |
| 75 | 72 | output: os.Stdout, |
| 112 | 109 | // Panics if *Progress instance is done, i.e. called after *Progress.Wait(). |
| 113 | 110 | func (p *Progress) Add(total int64, filler BarFiller, options ...BarOption) *Bar { |
| 114 | 111 | if filler == nil { |
| 115 | filler = NewBarFiller(DefaultBarStyle, false) | |
| 112 | filler = BarFillerFunc(func(io.Writer, int, decor.Statistics) {}) | |
| 116 | 113 | } |
| 117 | 114 | p.bwg.Add(1) |
| 118 | 115 | result := make(chan *Bar) |
| 232 | 229 | |
| 233 | 230 | tw, err := cw.GetWidth() |
| 234 | 231 | if err != nil { |
| 235 | tw = s.width | |
| 232 | tw = s.reqWidth | |
| 236 | 233 | } |
| 237 | 234 | for i := 0; i < s.bHeap.Len(); i++ { |
| 238 | 235 | bar := s.bHeap[i] |
| 346 | 343 | filler: filler, |
| 347 | 344 | priority: s.idCount, |
| 348 | 345 | id: s.idCount, |
| 349 | width: s.width, | |
| 346 | reqWidth: s.reqWidth, | |
| 350 | 347 | debugOut: s.debugOut, |
| 351 | 348 | extender: func(r io.Reader, _ int, _ decor.Statistics) (io.Reader, int) { |
| 352 | 349 | return r, 0 |
| 363 | 360 | bs.priority = -1 |
| 364 | 361 | } |
| 365 | 362 | |
| 366 | bs.bufP = bytes.NewBuffer(make([]byte, 0, bs.width)) | |
| 367 | bs.bufB = bytes.NewBuffer(make([]byte, 0, bs.width)) | |
| 368 | bs.bufA = bytes.NewBuffer(make([]byte, 0, bs.width)) | |
| 363 | bs.bufP = bytes.NewBuffer(make([]byte, 0, 64)) | |
| 364 | bs.bufB = bytes.NewBuffer(make([]byte, 0, 128)) | |
| 365 | bs.bufA = bytes.NewBuffer(make([]byte, 0, 64)) | |
| 369 | 366 | |
| 370 | 367 | return bs |
| 371 | 368 | } |