forked from gosuri/uiprogress
-
Notifications
You must be signed in to change notification settings - Fork 1
/
progress.go
154 lines (124 loc) · 3.1 KB
/
progress.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package uiprogress
import (
"fmt"
"io"
"os"
"sync"
"time"
"github.com/slimtoolkit/uilive"
)
// Out is the default writer to render progress bars to
var Out = os.Stdout
// RefreshInterval in the default time duration to wait for refreshing the output
var RefreshInterval = time.Millisecond * 10
// defaultProgress is the default progress <- removing
//var defaultProgress = New()
// Progress represents the container that renders progress bars
type Progress struct {
// Out is the writer to render progress bars to
Out io.Writer
// Width is the width of the progress bars
Width int
// Bars is the collection of progress bars
Bars []*Bar
// RefreshInterval in the time duration to wait for refreshing the output
RefreshInterval time.Duration
lw *uilive.Writer
ticker *time.Ticker
tdone chan bool
mtx *sync.RWMutex
}
// New returns a new progress bar with defaults
func New() *Progress {
lw := uilive.New()
if lw == nil {
return nil
}
lw.Out = Out
return &Progress{
Width: Width,
Out: Out,
Bars: make([]*Bar, 0),
RefreshInterval: RefreshInterval,
tdone: make(chan bool),
lw: uilive.New(),
mtx: &sync.RWMutex{},
}
}
//removing...
// AddBar creates a new progress bar and adds it to the default progress container
//func AddBar(total int) *Bar {
// return defaultProgress.AddBar(total)
//}
//removing...
// Start starts the rendering the progress of progress bars using the DefaultProgress. It listens for updates using `bar.Set(n)` and new bars when added using `AddBar`
//func Start() {
// defaultProgress.Start()
//}
//removing...
// Stop stops listening
//func Stop() {
// defaultProgress.Stop()
//}
//removing...
// Listen listens for updates and renders the progress bars
//func Listen() {
// defaultProgress.Listen()
//}
func (p *Progress) SetOut(o io.Writer) {
p.mtx.Lock()
defer p.mtx.Unlock()
p.Out = o
p.lw.Out = o
}
func (p *Progress) SetRefreshInterval(interval time.Duration) {
p.mtx.Lock()
defer p.mtx.Unlock()
p.RefreshInterval = interval
}
// AddBar creates a new progress bar and adds to the container
func (p *Progress) AddBar(total int) *Bar {
p.mtx.Lock()
defer p.mtx.Unlock()
bar := NewBar(total)
bar.Width = p.Width
p.Bars = append(p.Bars, bar)
return bar
}
// Listen listens for updates and renders the progress bars
func (p *Progress) Listen() {
for {
p.mtx.Lock()
interval := p.RefreshInterval
p.mtx.Unlock()
select {
case <-time.After(interval):
p.print()
case <-p.tdone:
p.print()
close(p.tdone)
return
}
}
}
func (p *Progress) print() {
p.mtx.Lock()
defer p.mtx.Unlock()
for _, bar := range p.Bars {
fmt.Fprintln(p.lw, bar.String())
}
p.lw.Flush()
}
// Start starts the rendering the progress of progress bars. It listens for updates using `bar.Set(n)` and new bars when added using `AddBar`
func (p *Progress) Start() {
go p.Listen()
}
// Stop stops listening
func (p *Progress) Stop() {
p.tdone <- true
<-p.tdone
}
// Bypass returns a writer which allows non-buffered data to be written to the underlying output
func (p *Progress) Bypass() io.Writer {
return p.lw.Bypass()
}