refactoring drawImpl
no need to stripansi each decorator's output string
because with new Decorator signature there is
view width available right away.
Vladimir Bauer
2 years ago
| 496 | 496 | } |
| 497 | 497 | |
| 498 | 498 | func (s *bState) drawImpl(stat decor.Statistics) (io.Reader, error) { |
| 499 | decorFiller := func(buf *bytes.Buffer, decorators []decor.Decorator) (res struct { | |
| 500 | width int | |
| 501 | truncate bool | |
| 502 | err error | |
| 503 | }) { | |
| 504 | res.width = stat.AvailableWidth | |
| 499 | decorFiller := func(buf *bytes.Buffer, decorators []decor.Decorator) (err error) { | |
| 505 | 500 | for _, d := range decorators { |
| 506 | str := d.Decor(stat) | |
| 507 | if stat.AvailableWidth > 0 { | |
| 508 | stat.AvailableWidth -= runewidth.StringWidth(stripansi.Strip(str)) | |
| 509 | if res.err == nil { | |
| 510 | _, res.err = buf.WriteString(str) | |
| 511 | } | |
| 501 | // need to call Decor in any case becase of width synchronization | |
| 502 | str, width := d.Decor(stat) | |
| 503 | if err != nil { | |
| 504 | continue | |
| 512 | 505 | } |
| 513 | } | |
| 514 | res.truncate = stat.AvailableWidth < 0 | |
| 515 | return res | |
| 506 | if w := stat.AvailableWidth - width; w >= 0 { | |
| 507 | _, err = buf.WriteString(str) | |
| 508 | stat.AvailableWidth = w | |
| 509 | } else if stat.AvailableWidth > 0 { | |
| 510 | trunc := runewidth.Truncate(stripansi.Strip(str), stat.AvailableWidth, "…") | |
| 511 | _, err = buf.WriteString(trunc) | |
| 512 | stat.AvailableWidth = 0 | |
| 513 | } | |
| 514 | } | |
| 515 | return err | |
| 516 | 516 | } |
| 517 | 517 | |
| 518 | 518 | bufP, bufB, bufA := s.buffers[0], s.buffers[1], s.buffers[2] |
| 519 | 519 | |
| 520 | resP := decorFiller(bufP, s.pDecorators) | |
| 521 | resA := decorFiller(bufA, s.aDecorators) | |
| 522 | ||
| 523 | for _, err := range []error{resP.err, resA.err} { | |
| 524 | if err != nil { | |
| 525 | return nil, err | |
| 526 | } | |
| 527 | } | |
| 528 | ||
| 529 | if resP.truncate { | |
| 530 | trunc := strings.NewReader(runewidth.Truncate(stripansi.Strip(bufP.String()), resP.width, "…")) | |
| 531 | bufP.Reset() | |
| 532 | bufA.Reset() | |
| 533 | return trunc, nil | |
| 534 | } | |
| 535 | ||
| 536 | if resA.truncate { | |
| 537 | trunc := strings.NewReader(runewidth.Truncate(stripansi.Strip(bufA.String()), resA.width, "…")) | |
| 538 | bufA.Reset() | |
| 539 | return io.MultiReader(bufP, trunc), nil | |
| 520 | err := eitherError(decorFiller(bufP, s.pDecorators), decorFiller(bufA, s.aDecorators)) | |
| 521 | if err != nil { | |
| 522 | return nil, err | |
| 540 | 523 | } |
| 541 | 524 | |
| 542 | 525 | if !s.trimSpace && stat.AvailableWidth >= 2 { |
| 661 | 644 | func writeSpace(buf *bytes.Buffer) error { |
| 662 | 645 | return buf.WriteByte(' ') |
| 663 | 646 | } |
| 647 | ||
| 648 | func eitherError(errors ...error) error { | |
| 649 | for _, err := range errors { | |
| 650 | if err != nil { | |
| 651 | return err | |
| 652 | } | |
| 653 | } | |
| 654 | return nil | |
| 655 | } | |