-
Notifications
You must be signed in to change notification settings - Fork 0
/
throbber.go
137 lines (125 loc) · 2.29 KB
/
throbber.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package busyIndicator
import (
"bufio"
"bytes"
"container/ring"
"fmt"
"os"
"time"
"unicode/utf8"
)
var (
space = []byte{32}
backSpace = []byte{8}
clearFromCursor = []byte{27, 91, 75}
//Spin is a standard spinner
Spin = []string{"-", "\\", "|", "/"}
//Dot is an ellipsis sequence
Dot = []string{"", ".", "..", "..."}
//Grow is a . that grows up to be an O
Grow = []string{".", "ₒ", "ⱺ", "O", "ⱺ", "ₒ", "."}
)
//Throbber starts a throbber
func Throbber(
vals []string,
speed time.Duration,
c chan bool,
) {
throb("", "", vals, speed, c)
}
//ThrobberPrefixed starts a throbber with a given static prefix
func ThrobberPrefixed(
prefix string,
vals []string,
speed time.Duration,
c chan bool,
) {
throb(prefix, "", vals, speed, c)
}
//ThrobberPostfixed starts a throbber with a given static postfix
func ThrobberPostfixed(
postfix string,
vals []string,
speed time.Duration,
c chan bool,
) {
throb("", postfix, vals, speed, c)
}
//ThrobberPrefixedAndPostfixed starts a throbber with a given static prefix and
//postfix
func ThrobberPrefixedAndPostfixed(
prefix string,
postfix string,
vals []string,
speed time.Duration,
c chan bool,
) {
throb(prefix, postfix, vals, speed, c)
}
func throb(
prefix string,
postfix string,
vals []string,
speed time.Duration,
c chan bool,
) {
var (
buffer = bufio.NewWriter(os.Stdout)
sequence, max = ringFromStringSlice(vals)
)
for {
select {
case <-c:
return
default:
step := sequence.Value.(string)
replaceLineAfter(
buffer,
[]byte(fmt.Sprintf(
"%s%s%s%s",
prefix,
step,
bytes.Repeat(space, max-utf8.RuneCountInString(step)),
postfix,
)),
speed,
)
sequence = sequence.Next()
}
}
}
func replaceLineAfter(
buffer *bufio.Writer,
s []byte,
wait time.Duration,
) {
var err error
defer buffer.Flush()
_, err = buffer.WriteString(fmt.Sprintf(
"%s%s",
bytes.Repeat(backSpace, len(s)),
clearFromCursor,
))
if err != nil {
return
}
_, err = buffer.Write(s)
if err != nil {
return
}
time.Sleep(wait)
}
func ringFromStringSlice(vals []string) (*ring.Ring, int) {
var (
r = ring.New(len(vals))
max int
)
for _, v := range vals {
if l := utf8.RuneCountInString(v); l > max {
max = l
}
r.Value = v
r = r.Next()
}
return r, max
}