refactoring: simplify BarFiller's signature
Move reqWidth param into decor.Statistics.
Latter one already had AvailableWidth,
so having RequestedWidth there feels ok.
Vladimir Bauer
3 years ago
| 28 | 28 | recoveredPanic interface{} |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | type extenderFunc func(rows []io.Reader, width int, stat decor.Statistics) []io.Reader | |
| 31 | type extenderFunc func(rows []io.Reader, stat decor.Statistics) []io.Reader | |
| 32 | 32 | |
| 33 | 33 | // bState is actual bar's state. |
| 34 | 34 | type bState struct { |
| 383 | 383 | b.recoveredPanic = p |
| 384 | 384 | } |
| 385 | 385 | if fn := s.extender; fn != nil { |
| 386 | rows = fn(rows, s.reqWidth, stat) | |
| 386 | rows = fn(rows, stat) | |
| 387 | 387 | } |
| 388 | 388 | frame := &renderFrame{ |
| 389 | 389 | rows: rows, |
| 405 | 405 | rows = append(rows, s.draw(stat)) |
| 406 | 406 | } |
| 407 | 407 | if fn := s.extender; fn != nil { |
| 408 | rows = fn(rows, s.reqWidth, stat) | |
| 408 | rows = fn(rows, stat) | |
| 409 | 409 | } |
| 410 | 410 | frame := &renderFrame{ |
| 411 | 411 | rows: rows, |
| 487 | 487 | return io.MultiReader(bufP, bufB, trunc, nlr) |
| 488 | 488 | } |
| 489 | 489 | |
| 490 | s.filler.Fill(bufB, s.reqWidth, stat) | |
| 490 | s.filler.Fill(bufB, stat) | |
| 491 | 491 | |
| 492 | 492 | return io.MultiReader(bufP, bufB, bufA, nlr) |
| 493 | 493 | } |
| 588 | 588 | func newStatistics(tw int, s *bState) decor.Statistics { |
| 589 | 589 | return decor.Statistics{ |
| 590 | 590 | AvailableWidth: tw, |
| 591 | RequestedWidth: s.reqWidth, | |
| 591 | 592 | ID: s.id, |
| 592 | 593 | Total: s.total, |
| 593 | 594 | Current: s.current, |
| 606 | 607 | |
| 607 | 608 | func makePanicExtender(p interface{}) extenderFunc { |
| 608 | 609 | pstr := fmt.Sprint(p) |
| 609 | return func(rows []io.Reader, _ int, stat decor.Statistics) []io.Reader { | |
| 610 | return func(rows []io.Reader, stat decor.Statistics) []io.Reader { | |
| 610 | 611 | r := io.MultiReader( |
| 611 | 612 | strings.NewReader(runewidth.Truncate(pstr, stat.AvailableWidth, "…")), |
| 612 | 613 | bytes.NewReader([]byte("\n")), |
| 8 | 8 | // BarFiller interface. |
| 9 | 9 | // Bar (without decorators) renders itself by calling BarFiller's Fill method. |
| 10 | 10 | // |
| 11 | // reqWidth is requested width set by `func WithWidth(int) ContainerOption`. | |
| 12 | 11 | // If not set, it defaults to terminal width. |
| 13 | // | |
| 14 | 12 | type BarFiller interface { |
| 15 | Fill(w io.Writer, reqWidth int, stat decor.Statistics) | |
| 13 | Fill(w io.Writer, stat decor.Statistics) | |
| 16 | 14 | } |
| 17 | 15 | |
| 18 | 16 | // BarFillerBuilder interface. |
| 21 | 19 | // BarStyle() |
| 22 | 20 | // SpinnerStyle() |
| 23 | 21 | // NopStyle() |
| 24 | // | |
| 25 | 22 | type BarFillerBuilder interface { |
| 26 | 23 | Build() BarFiller |
| 27 | 24 | } |
| 28 | 25 | |
| 29 | 26 | // BarFillerFunc is function type adapter to convert compatible function |
| 30 | 27 | // into BarFiller interface. |
| 31 | type BarFillerFunc func(w io.Writer, reqWidth int, stat decor.Statistics) | |
| 28 | type BarFillerFunc func(w io.Writer, stat decor.Statistics) | |
| 32 | 29 | |
| 33 | func (f BarFillerFunc) Fill(w io.Writer, reqWidth int, stat decor.Statistics) { | |
| 34 | f(w, reqWidth, stat) | |
| 30 | func (f BarFillerFunc) Fill(w io.Writer, stat decor.Statistics) { | |
| 31 | f(w, stat) | |
| 35 | 32 | } |
| 36 | 33 | |
| 37 | 34 | // BarFillerBuilderFunc is function type adapter to convert compatible |
| 147 | 147 | return bf |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | func (s *bFiller) Fill(w io.Writer, width int, stat decor.Statistics) { | |
| 151 | width = internal.CheckRequestedWidth(width, stat.AvailableWidth) | |
| 150 | func (s *bFiller) Fill(w io.Writer, stat decor.Statistics) { | |
| 151 | width := internal.CheckRequestedWidth(stat.RequestedWidth, stat.AvailableWidth) | |
| 152 | 152 | brackets := s.components[iLbound].width + s.components[iRbound].width |
| 153 | 153 | // don't count brackets as progress |
| 154 | 154 | width -= brackets |
| 8 | 8 | // NopStyle provides BarFillerBuilder which builds NOP BarFiller. |
| 9 | 9 | func NopStyle() BarFillerBuilder { |
| 10 | 10 | return BarFillerBuilderFunc(func() BarFiller { |
| 11 | return BarFillerFunc(func(io.Writer, int, decor.Statistics) {}) | |
| 11 | return BarFillerFunc(func(io.Writer, decor.Statistics) {}) | |
| 12 | 12 | }) |
| 13 | 13 | } |
| 62 | 62 | return sf |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | func (s *sFiller) Fill(w io.Writer, width int, stat decor.Statistics) { | |
| 66 | width = internal.CheckRequestedWidth(width, stat.AvailableWidth) | |
| 65 | func (s *sFiller) Fill(w io.Writer, stat decor.Statistics) { | |
| 66 | width := internal.CheckRequestedWidth(stat.RequestedWidth, stat.AvailableWidth) | |
| 67 | 67 | |
| 68 | 68 | frame := s.frames[s.count%uint(len(s.frames))] |
| 69 | 69 | frameWidth := runewidth.StringWidth(stripansi.Strip(frame)) |
| 90 | 90 | // BarFillerOnComplete replaces bar's filler with message, on complete event. |
| 91 | 91 | func BarFillerOnComplete(message string) BarOption { |
| 92 | 92 | return BarFillerMiddleware(func(base BarFiller) BarFiller { |
| 93 | return BarFillerFunc(func(w io.Writer, reqWidth int, st decor.Statistics) { | |
| 93 | return BarFillerFunc(func(w io.Writer, st decor.Statistics) { | |
| 94 | 94 | if st.Completed { |
| 95 | 95 | _, err := io.WriteString(w, message) |
| 96 | 96 | if err != nil { |
| 97 | 97 | panic(err) |
| 98 | 98 | } |
| 99 | 99 | } else { |
| 100 | base.Fill(w, reqWidth, st) | |
| 100 | base.Fill(w, st) | |
| 101 | 101 | } |
| 102 | 102 | }) |
| 103 | 103 | }) |
| 143 | 143 | |
| 144 | 144 | func makeExtenderFunc(filler BarFiller, rev bool) extenderFunc { |
| 145 | 145 | buf := new(bytes.Buffer) |
| 146 | base := func(rows []io.Reader, width int, stat decor.Statistics) []io.Reader { | |
| 146 | base := func(rows []io.Reader, stat decor.Statistics) []io.Reader { | |
| 147 | 147 | buf.Reset() |
| 148 | filler.Fill(buf, width, stat) | |
| 148 | filler.Fill(buf, stat) | |
| 149 | 149 | for { |
| 150 | 150 | b, err := buf.ReadBytes('\n') |
| 151 | 151 | if err != nil { |
| 159 | 159 | if !rev { |
| 160 | 160 | return base |
| 161 | 161 | } else { |
| 162 | return func(rows []io.Reader, width int, stat decor.Statistics) []io.Reader { | |
| 163 | rows = base(rows, width, stat) | |
| 162 | return func(rows []io.Reader, stat decor.Statistics) []io.Reader { | |
| 163 | rows = base(rows, stat) | |
| 164 | 164 | for left, right := 0, len(rows)-1; left < right; left, right = left+1, right-1 { |
| 165 | 165 | rows[left], rows[right] = rows[right], rows[left] |
| 166 | 166 | } |