func (s *Spinner) Status() SpinnerStatus {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.status == nil {
		panic("status field is nil")
	}
	return SpinnerStatus(atomic.LoadUint32(s.status))
}
Status returns the current status of the internal state machine. Returned
value is of type SpinnerStatus which has package constants available.
package yacspin
import (
	"fmt"
	"io"
	"os"
	"runtime"
	"strings"
	"sync"
	"sync/atomic"
	"time"
	"github.com/mattn/go-runewidth"
	"github.com/pkg/errors"
)
type character struct {
	Value string
	Size  int
}
func setToCharSlice(ss []string) ([]character, int) {
	if len(ss) == 0 {
		return nil, 0
	}
	var maxWidth int
	c := make([]character, len(ss))
	for i, s := range ss {
		n := runewidth.StringWidth(s)
		if n > maxWidth {
			maxWidth = n
		}
		c[i] = character{
			Value: s,
			Size:  n,
		}
	}
	return c, maxWidth
}
type Config struct {
	Frequency time.Duration
	Delay time.Duration
	Writer io.Writer
	HideCursor bool
	ColorAll bool
	Colors []string
	CharSet []string
	Prefix string
	Suffix string
	SuffixAutoColon bool
	Message string
	StopMessage string
	StopCharacter string
	StopColors []string
	StopFailMessage string
	StopFailCharacter string
	StopFailColors []string
}
type Spinner struct {
	writer          io.Writer
	colorAll        bool
	cursorHidden    bool
	suffixAutoColon bool
	isDumbTerm      bool
	status       *uint32
	lastPrintLen int
	cancelCh     chan struct{}  
	doneCh       chan struct{}
	pauseCh      chan struct{}
	unpauseCh    chan struct{}
	unpausedCh   chan struct{}
	mu                *sync.Mutex
	frequency         time.Duration
	chars             []character
	maxWidth          int
	index             int
	prefix            string
	suffix            string
	message           string
	colorFn           func(format string, a ...interface{}) string
	stopMsg           string
	stopChar          character
	stopColorFn       func(format string, a ...interface{}) string
	stopFailMsg       string
	stopFailChar      character
	stopFailColorFn   func(format string, a ...interface{}) string
	frequencyUpdateCh chan time.Duration
	dataUpdateCh      chan struct{}
}
const (
	statusStopped uint32 = iota
	statusStarting
	statusRunning
	statusStopping
	statusPausing
	statusPaused
	statusUnpausing
)
func New(cfg Config) (*Spinner, error) {
	if cfg.Delay > 0 && cfg.Frequency == 0 {
		cfg.Frequency = cfg.Delay
	}
	if cfg.Frequency < 1 {
		return nil, errors.New("cfg.Frequency must be greater than 0")
	}
	s := &Spinner{
		mu:                &sync.Mutex{},
		frequency:         cfg.Frequency,
		status:            uint32Ptr(0),
		frequencyUpdateCh: make(chan time.Duration),
		dataUpdateCh:      make(chan struct{}),
		colorAll:        cfg.ColorAll,
		cursorHidden:    cfg.HideCursor,
		suffixAutoColon: cfg.SuffixAutoColon,
		isDumbTerm:      os.Getenv("TERM") == "dumb" || runtime.GOOS == "windows",
		colorFn:         fmt.Sprintf,
		stopColorFn:     fmt.Sprintf,
		stopFailColorFn: fmt.Sprintf,
	}
	if err := s.Colors(cfg.Colors...); err != nil {
		return nil, err
	}
	if err := s.StopColors(cfg.StopColors...); err != nil {
		return nil, err
	}
	if err := s.StopFailColors(cfg.StopFailColors...); err != nil {
		return nil, err
	}
	if len(cfg.CharSet) == 0 {
		cfg.CharSet = CharSets[9]
	}
	_ = s.CharSet(cfg.CharSet)
	if cfg.Writer == nil {
		cfg.Writer = os.Stdout
	}
	s.writer = cfg.Writer
	if len(cfg.Prefix) > 0 {
		s.Prefix(cfg.Prefix)
	}
	if len(cfg.Suffix) > 0 {
		s.Suffix(cfg.Suffix)
	}
	if len(cfg.Message) > 0 {
		s.Message(cfg.Message)
	}
	if len(cfg.StopMessage) > 0 {
		s.StopMessage(cfg.StopMessage)
	}
	if len(cfg.StopCharacter) > 0 {
		s.StopCharacter(cfg.StopCharacter)
	}
	if len(cfg.StopFailMessage) > 0 {
		s.StopFailMessage(cfg.StopFailMessage)
	}
	if len(cfg.StopFailCharacter) > 0 {
		s.StopFailCharacter(cfg.StopFailCharacter)
	}
	return s, nil
}
func (s *Spinner) notifyDataChange() {
	select {
	case s.dataUpdateCh <- struct{}{}:
	default:
	}
}
func (s *Spinner) Active() bool {
	v := atomic.LoadUint32(s.status)
	return v == 1 || v == 2
}
type SpinnerStatus uint32
const (
	SpinnerStopped SpinnerStatus = iota
	SpinnerStarting
	SpinnerRunning
	SpinnerStopping
	SpinnerPausing
	SpinnerPaused
	SpinnerUnpausing
)
func (s SpinnerStatus) String() string {
	switch s {
	case SpinnerStopped:
		return "stopped"
	case SpinnerStarting:
		return "starting"
	case SpinnerRunning:
		return "running"
	case SpinnerStopping:
		return "stopping"
	case SpinnerPausing:
		return "pausing"
	case SpinnerPaused:
		return "paused"
	case SpinnerUnpausing:
		return "unpausing"
	default:
		return fmt.Sprintf("unknown (%d)", s)
	}
}