forked from gizak/termui
-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathutils.go
More file actions
237 lines (212 loc) · 5.02 KB
/
utils.go
File metadata and controls
237 lines (212 loc) · 5.02 KB
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
package gotui
import (
"fmt"
"math"
"reflect"
rw "github.com/mattn/go-runewidth"
wordwrap "github.com/mitchellh/go-wordwrap"
)
// InterfaceSlice converts a slice of any type to a slice of interface{}.
func InterfaceSlice(slice any) []any {
s := reflect.ValueOf(slice)
if s.Kind() != reflect.Slice {
panic("InterfaceSlice() given a non-slice type")
}
ret := make([]any, s.Len())
for i := 0; i < s.Len(); i++ {
ret[i] = s.Index(i).Interface()
}
return ret
}
// TrimString trims a string to a given width.
func TrimString(s string, w int) string {
if w <= 0 {
return ""
}
if rw.StringWidth(s) > w {
return rw.Truncate(s, w, string(ELLIPSES))
}
return s
}
// SelectColor selects a color from a slice of colors based on an index.
func SelectColor(colors []Color, index int) Color {
return colors[index%len(colors)]
}
// SelectStyle selects a style from a slice of styles based on an index.
func SelectStyle(styles []Style, index int) Style {
return styles[index%len(styles)]
}
// SumIntSlice sums a slice of ints.
func SumIntSlice(slice []int) int {
sum := 0
for _, val := range slice {
sum += val
}
return sum
}
// SumFloat64Slice sums a slice of float64s.
func SumFloat64Slice(data []float64) float64 {
sum := 0.0
for _, v := range data {
sum += v
}
return sum
}
// GetMaxIntFromSlice returns the maximum value from a slice of ints.
func GetMaxIntFromSlice(slice []int) (int, error) {
if len(slice) == 0 {
return 0, fmt.Errorf("cannot get max value from empty slice")
}
var max int
for _, val := range slice {
if val > max {
max = val
}
}
return max, nil
}
// GetMaxFloat64FromSlice returns the maximum value from a slice of float64s.
func GetMaxFloat64FromSlice(slice []float64) (float64, error) {
if len(slice) == 0 {
return 0, fmt.Errorf("cannot get max value from empty slice")
}
var max float64
for _, val := range slice {
if val > max {
max = val
}
}
return max, nil
}
// GetMaxFloat64From2dSlice returns the maximum value from a 2D slice of float64s.
func GetMaxFloat64From2dSlice(slices [][]float64) (float64, error) {
if len(slices) == 0 {
return 0, fmt.Errorf("cannot get max value from empty slice")
}
var max float64
for _, slice := range slices {
for _, val := range slice {
if val > max {
max = val
}
}
}
return max, nil
}
// RoundFloat64 rounds a float64 to the nearest integer.
func RoundFloat64(x float64) float64 {
return math.Floor(x + 0.5)
}
// FloorFloat64 floors a float64.
func FloorFloat64(x float64) float64 {
return math.Floor(x)
}
// AbsInt returns the absolute value of an int.
func AbsInt(x int) int {
if x >= 0 {
return x
}
return -x
}
// MinFloat64 returns the minimum of two float64s.
func MinFloat64(x, y float64) float64 {
if x < y {
return x
}
return y
}
// MaxFloat64 returns the maximum of two float64s.
func MaxFloat64(x, y float64) float64 {
if x > y {
return x
}
return y
}
// MaxInt returns the maximum of two ints.
func MaxInt(x, y int) int {
if x > y {
return x
}
return y
}
// MinInt returns the minimum of two ints.
func MinInt(x, y int) int {
if x < y {
return x
}
return y
}
// WrapCells wraps a slice of cells to a given width.
func WrapCells(cells []Cell, width uint) []Cell {
str := CellsToString(cells)
wrapped := wordwrap.WrapString(str, width)
wrappedCells := []Cell{}
i := 0
for _, _rune := range wrapped {
if _rune == '\n' {
wrappedCells = append(wrappedCells, Cell{_rune, StyleClear})
} else {
wrappedCells = append(wrappedCells, Cell{_rune, cells[i].Style})
}
i++
}
return wrappedCells
}
// RunesToStyledCells converts a slice of runes to a slice of cells with a given style.
func RunesToStyledCells(runes []rune, style Style) []Cell {
cells := []Cell{}
for _, _rune := range runes {
cells = append(cells, Cell{_rune, style})
}
return cells
}
// CellsToString converts a slice of cells to a string.
func CellsToString(cells []Cell) string {
runes := make([]rune, len(cells))
for i, cell := range cells {
runes[i] = cell.Rune
}
return string(runes)
}
// TrimCells trims a slice of cells to a given width.
func TrimCells(cells []Cell, w int) []Cell {
s := CellsToString(cells)
s = TrimString(s, w)
runes := []rune(s)
newCells := []Cell{}
for i, r := range runes {
newCells = append(newCells, Cell{r, cells[i].Style})
}
return newCells
}
// SplitCells splits a slice of cells by a rune.
func SplitCells(cells []Cell, r rune) [][]Cell {
splitCells := [][]Cell{}
temp := []Cell{}
for _, cell := range cells {
if cell.Rune == r {
splitCells = append(splitCells, temp)
temp = []Cell{}
} else {
temp = append(temp, cell)
}
}
if len(temp) > 0 {
splitCells = append(splitCells, temp)
}
return splitCells
}
type CellWithX struct {
X int
Cell Cell
}
// BuildCellWithXArray builds an array of CellWithX from a slice of Cells.
func BuildCellWithXArray(cells []Cell) []CellWithX {
cellWithXArray := make([]CellWithX, len(cells))
index := 0
for i, cell := range cells {
cellWithXArray[i] = CellWithX{X: index, Cell: cell}
index += rw.RuneWidth(cell.Rune)
}
return cellWithXArray
}