spinner.go 1.3 KB

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