Files
cameradar/vendor/github.com/gernest/wow/wow.go
T
Brendan LE GLAUNEC 5849898283 Cameradar 3.0.0: Uses ullaakut/nmap, runs faster, removed legacy code (#188)
Unit tests functional and coverage back to 100%

Add more routes to dictionary, add more credentials, add default port 5554, rename cameradar logs ENV variable, improve unit test readability, remove tmp file
2019-01-22 21:16:16 +01:00

123 lines
2.4 KiB
Go

package wow
import (
"context"
"fmt"
"io"
"os"
"sync"
"time"
"github.com/gernest/wow/spin"
"golang.org/x/crypto/ssh/terminal"
)
const erase = "\033[2K\r"
// Wow writes beautiful spinners on the terminal.
type Wow struct {
txt string
s spin.Spinner
out io.Writer
running bool
done func()
mu sync.RWMutex
IsTerminal bool
}
// New creates a new wow instance ready to start spinning.
func New(o io.Writer, s spin.Spinner, text string, options ...func(*Wow)) *Wow {
isTerminal := terminal.IsTerminal(int(os.Stdout.Fd()))
wow := Wow{out: o, s: s, txt: text, IsTerminal: isTerminal}
for _, option := range options {
option(&wow)
}
return &wow
}
// Start starts the spinner. The frames are written based on the spinner
// interval.
func (w *Wow) Start() {
if !w.running {
ctx, done := context.WithCancel(context.Background())
t := time.NewTicker(time.Duration(w.s.Interval) * time.Millisecond)
w.done = done
w.running = true
go func() {
at := 0
for {
select {
case <-ctx.Done():
t.Stop()
break
case <-t.C:
txt := erase + w.s.Frames[at%len(w.s.Frames)] + w.txt
if w.IsTerminal {
fmt.Fprint(w.out, txt)
}
at++
}
}
}()
}
}
// Stop stops the spinner
func (w *Wow) Stop() {
if w.done != nil {
w.done()
}
w.running = false
}
// Spinner sets s to the current spinner
func (w *Wow) Spinner(s spin.Spinner) *Wow {
w.Stop()
w.s = s
w.Start()
return w
}
// Text adds text to the current spinner
func (w *Wow) Text(txt string) *Wow {
w.mu.Lock()
w.txt = txt
w.mu.Unlock()
return w
}
// Persist writes the last character of the currect spinner frames together with
// the text on stdout.
//
// A new line is added at the end to ensure the text stay that way.
func (w *Wow) Persist() {
w.Stop()
at := len(w.s.Frames) - 1
txt := erase + w.s.Frames[at] + w.txt + "\n"
if w.IsTerminal {
fmt.Fprint(w.out, txt)
}
}
// PersistWith writes the last frame of s together with text with a new line
// added to make it stick.
func (w *Wow) PersistWith(s spin.Spinner, text string) {
w.Stop()
var a string
if len(s.Frames) > 0 {
a = s.Frames[len(s.Frames)-1]
}
txt := erase + a + text + "\n"
if w.IsTerminal {
fmt.Fprint(w.out, txt)
}
}
// ForceOutput forces all output even if not not outputting directly to a terminal
func ForceOutput(w *Wow) {
w.IsTerminal = true
}