Files
pigo/utils/progress.go

108 lines
2.3 KiB
Go

package utils
import (
"fmt"
"io"
"os"
"runtime"
"strings"
"sync"
"time"
"unicode/utf8"
)
// ProgressIndicator initializes the progress indicator.
type ProgressIndicator struct {
mu *sync.RWMutex
delay time.Duration
writer io.Writer
message string
lastOutput string
StopMsg string
hideCursor bool
stopChan chan struct{}
}
const (
errorColor = "\x1b[31m"
successColor = "\x1b[32m"
defaultColor = "\x1b[0m"
)
// NewSpinner instantiates a new progress indicator.
func NewSpinner(msg string, d time.Duration) *ProgressIndicator {
return &ProgressIndicator{
mu: &sync.RWMutex{},
delay: d,
writer: os.Stderr,
message: msg,
hideCursor: false,
stopChan: make(chan struct{}, 1),
}
}
// Start starts the progress indicator.
func (pi *ProgressIndicator) Start() {
if pi.hideCursor && runtime.GOOS != "windows" {
// hides the cursor
fmt.Fprintf(pi.writer, "\033[?25l")
}
go func() {
for {
for _, r := range `⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏` {
select {
case <-pi.stopChan:
return
default:
pi.mu.Lock()
output := fmt.Sprintf("\r%s%s %c%s", pi.message, successColor, r, defaultColor)
fmt.Fprintf(pi.writer, output)
pi.lastOutput = output
pi.mu.Unlock()
time.Sleep(pi.delay)
}
}
}
}()
}
// Stop stops the progress indicator.
func (pi *ProgressIndicator) Stop() {
pi.mu.Lock()
defer pi.mu.Unlock()
pi.clear()
pi.RestoreCursor()
if len(pi.StopMsg) > 0 {
fmt.Fprintf(pi.writer, pi.StopMsg)
}
pi.stopChan <- struct{}{}
}
// RestoreCursor restores back the cursor visibility.
func (pi *ProgressIndicator) RestoreCursor() {
if pi.hideCursor && runtime.GOOS != "windows" {
// makes the cursor visible
fmt.Fprint(pi.writer, "\033[?25h")
}
}
// clear deletes the last line. Caller must hold the the locker.
func (pi *ProgressIndicator) clear() {
n := utf8.RuneCountInString(pi.lastOutput)
if runtime.GOOS == "windows" {
clearString := "\r" + strings.Repeat(" ", n) + "\r"
fmt.Fprint(pi.writer, clearString)
pi.lastOutput = ""
return
}
for _, c := range []string{"\b", "\127", "\b", "\033[K"} { // "\033[K" for macOS Terminal
fmt.Fprint(pi.writer, strings.Repeat(c, n))
}
fmt.Fprintf(pi.writer, "\r\033[K") // clear line
pi.lastOutput = ""
}