bar.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. package progress
  2. import (
  3. "fmt"
  4. "math"
  5. "os"
  6. "strings"
  7. "time"
  8. "github.com/jmorganca/ollama/format"
  9. "golang.org/x/term"
  10. )
  11. type Bar struct {
  12. message string
  13. messageWidth int
  14. maxValue int64
  15. initialValue int64
  16. currentValue int64
  17. started time.Time
  18. stopped time.Time
  19. }
  20. func NewBar(message string, maxValue, initialValue int64) *Bar {
  21. return &Bar{
  22. message: message,
  23. messageWidth: -1,
  24. maxValue: maxValue,
  25. initialValue: initialValue,
  26. currentValue: initialValue,
  27. started: time.Now(),
  28. }
  29. }
  30. func (b *Bar) String() string {
  31. termWidth, _, err := term.GetSize(int(os.Stderr.Fd()))
  32. if err != nil {
  33. termWidth = 80
  34. }
  35. var pre, mid, suf strings.Builder
  36. if b.message != "" {
  37. message := strings.TrimSpace(b.message)
  38. if b.messageWidth > 0 && len(message) > b.messageWidth {
  39. message = message[:b.messageWidth]
  40. }
  41. fmt.Fprintf(&pre, "%s", message)
  42. if b.messageWidth-pre.Len() >= 0 {
  43. pre.WriteString(strings.Repeat(" ", b.messageWidth-pre.Len()))
  44. }
  45. pre.WriteString(" ")
  46. }
  47. fmt.Fprintf(&pre, "%3.0f%% ", math.Floor(b.percent()))
  48. fmt.Fprintf(&suf, "(%s/%s, %s/s, %s)",
  49. format.HumanBytes(b.currentValue),
  50. format.HumanBytes(b.maxValue),
  51. format.HumanBytes(int64(b.rate())),
  52. b.elapsed())
  53. mid.WriteString("▕")
  54. // add 3 extra spaces: 2 boundary characters and 1 space at the end
  55. f := termWidth - pre.Len() - suf.Len() - 3
  56. n := int(float64(f) * b.percent() / 100)
  57. if n > 0 {
  58. mid.WriteString(strings.Repeat("█", n))
  59. }
  60. if f-n > 0 {
  61. mid.WriteString(strings.Repeat(" ", f-n))
  62. }
  63. mid.WriteString("▏")
  64. return pre.String() + mid.String() + suf.String()
  65. }
  66. func (b *Bar) Set(value int64) {
  67. if value >= b.maxValue {
  68. value = b.maxValue
  69. b.stopped = time.Now()
  70. }
  71. b.currentValue = value
  72. }
  73. func (b *Bar) percent() float64 {
  74. if b.maxValue > 0 {
  75. return float64(b.currentValue) / float64(b.maxValue) * 100
  76. }
  77. return 0
  78. }
  79. func (b *Bar) rate() float64 {
  80. elapsed := b.elapsed()
  81. if elapsed.Seconds() > 0 {
  82. return (float64(b.currentValue) - float64(b.initialValue)) / elapsed.Seconds()
  83. }
  84. return 0
  85. }
  86. func (b *Bar) elapsed() time.Duration {
  87. stopped := b.stopped
  88. if stopped.IsZero() {
  89. stopped = time.Now()
  90. }
  91. return stopped.Sub(b.started).Round(time.Second)
  92. }