-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbarbase.go
145 lines (113 loc) · 3.14 KB
/
barbase.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
package ttyprogress
import (
"github.com/mandelsoft/goutils/generics"
"github.com/mandelsoft/object"
"github.com/mandelsoft/ttyprogress/ppi"
"github.com/mandelsoft/ttyprogress/specs"
)
type barGroupNotifier struct {
started bool
}
var _ specs.GroupNotifier = (*barGroupNotifier)(nil)
func (n *barGroupNotifier) Add(b ProgressElement, p any) {
eff := b.(*IntBarBase[IntBarImpl])
defer eff.elem.Lock()()
if !n.started {
eff.elem.Protected().SetTotal(0)
n.started = true
}
eff.elem.Protected().SetTotal(eff.elem.Protected().Total() + 1)
}
func (*barGroupNotifier) Done(b ProgressElement, p any) {
eff := b.(*IntBarBase[IntBarImpl])
eff.Incr()
}
////////////////////////////////////////////////////////////////////////////////
type IntBarInterface interface {
ppi.BarInterface[int]
Current() int
CompletedPercent() float64
Set(n int) bool
Incr() bool
}
type IntBarImpl interface {
ppi.BarImpl[int]
IntBarInterface
}
type IntBarBase[T IntBarImpl] struct {
*ppi.BarBase[T, int]
elem *IntBarBaseImpl[T]
}
func (b *IntBarBase[T]) CompletedPercent() float64 {
defer b.elem.Lock()()
return b.elem.Protected().CompletedPercent()
}
func (b *IntBarBase[T]) Current() int {
defer b.elem.Lock()()
return b.elem.Protected().Current()
}
func (b *IntBarBase[T]) Set(n int) bool {
defer b.elem.Lock()()
return b.elem.Protected().Set(n)
}
func (b *IntBarBase[T]) Incr() bool {
defer b.elem.Lock()()
return b.elem.Protected().Incr()
}
type IntBarBaseImpl[T IntBarImpl] struct {
*ppi.BarBaseImpl[T, int]
current int
}
func newIntBar[T IntBarImpl](p Container, c specs.BarBaseConfiguration, total int, self object.Self[T, any]) (*IntBarBase[T], *IntBarBaseImpl[T], error) {
e := &IntBarBaseImpl[T]{}
o := &IntBarBase[T]{elem: e}
if self == nil {
// T must be IntBarImpl
self = object.NewSelf[T, any](generics.Cast[T](e), o)
}
b, s, err := ppi.NewBarBase[T, int](self, p, c, total, nil)
if err != nil {
return nil, nil, err
}
e.BarBaseImpl = s
o.BarBase = b
return o, e, nil
}
// Set the current count of the bar. It returns ErrMaxCurrentReached when trying n exceeds the total value. This is atomic operation and concurrency safe.
func (b *IntBarBaseImpl[T]) Set(n int) bool {
b.Start()
if b.current >= b.Protected().Total() {
return false
}
if n >= b.Protected().Total() {
n = b.Protected().Total()
}
b.current = n
b.Protected().Flush()
return true
}
// Incr increments the current value by 1, time elapsed to current time and returns true. It returns false if the cursor has reached or exceeds total value.
func (b *IntBarBaseImpl[T]) Incr() bool {
b.Protected().Start()
if b.current == b.Protected().Total() {
return false
}
n := b.current + 1
b.current = n
b.Protected().Flush()
return true
}
func (b *IntBarBaseImpl[T]) IsFinished() bool {
return b.current == b.Protected().Total()
}
// Current returns the current progress of the bar
func (b *IntBarBaseImpl[T]) Current() int {
return b.current
}
func runeBytes(r rune) []byte {
return []byte(string(r))
}
// CompletedPercent return the percent completed
func (b *IntBarBaseImpl[T]) CompletedPercent() float64 {
return (float64(b.Current()) / float64(b.Total())) * 100.00
}