spinner.go 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. package progress
  2. import (
  3. "fmt"
  4. "strings"
  5. "time"
  6. )
  7. type Spinner struct {
  8. message string
  9. messageWidth int
  10. value int
  11. ticker *time.Ticker
  12. started time.Time
  13. stopped time.Time
  14. }
  15. func NewSpinner(message string) *Spinner {
  16. s := &Spinner{
  17. message: message,
  18. started: time.Now(),
  19. value: 231,
  20. }
  21. go s.start()
  22. return s
  23. }
  24. func (s *Spinner) String() string {
  25. var sb strings.Builder
  26. if len(s.message) > 0 {
  27. message := strings.TrimSpace(s.message)
  28. if s.messageWidth > 0 && len(message) > s.messageWidth {
  29. message = message[:s.messageWidth]
  30. }
  31. fmt.Fprintf(&sb, "%s", message)
  32. if s.messageWidth-sb.Len() >= 0 {
  33. sb.WriteString(strings.Repeat(" ", s.messageWidth-sb.Len()))
  34. }
  35. sb.WriteString(" ")
  36. }
  37. if s.stopped.IsZero() {
  38. sb.WriteString(fmt.Sprintf("\033[48;5;%dm ", s.value))
  39. sb.WriteString("\033[0m")
  40. }
  41. return sb.String()
  42. }
  43. func (s *Spinner) start() {
  44. s.ticker = time.NewTicker(40 * time.Millisecond)
  45. for range s.ticker.C {
  46. if s.value < 255 {
  47. s.value++
  48. } else {
  49. s.value = 231
  50. }
  51. if !s.stopped.IsZero() {
  52. return
  53. }
  54. }
  55. }
  56. func (s *Spinner) Stop() {
  57. if s.stopped.IsZero() {
  58. s.stopped = time.Now()
  59. }
  60. }