forked from antonmedv/walk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.go
120 lines (109 loc) · 2.51 KB
/
util.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
package walk
import (
"math"
"os"
. "strings"
)
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func fileInfo(path string) os.FileInfo {
fi, err := os.Stat(path)
if err != nil {
panic(err)
}
return fi
}
func lookup(names []string, val string) string {
for _, name := range names {
val, ok := os.LookupEnv(name)
if ok && val != "" {
return val
}
}
return val
}
func leaveOnlyAscii(content []byte) string {
var result []byte
for _, b := range content {
if b == '\t' {
result = append(result, ' ', ' ', ' ', ' ')
} else if b == '\r' {
continue
} else if (b >= 32 && b <= 127) || b == '\n' { // '\n' is kept if newline needs to be retained
result = append(result, b)
}
}
return string(result)
}
func wrap(files []os.DirEntry, width int, height int, callback func(name string, i, j int)) ([][]string, int, int) {
// If it's possible to fit all files in one column on a third of the screen,
// just use one column. Otherwise, let's squeeze listing in half of screen.
columns := len(files) / (height / 3)
if columns <= 0 {
columns = 1
}
start:
// Let's try to fit everything in terminal width with this many columns.
// If we are not able to do it, decrease column number and goto start.
rows := int(math.Ceil(float64(len(files)) / float64(columns)))
names := make([][]string, columns)
n := 0
for i := 0; i < columns; i++ {
names[i] = make([]string, rows)
// Columns size is going to be of max file name size.
max := 0
for j := 0; j < rows; j++ {
name := ""
if n < len(files) {
if showIcons {
info, err := files[n].Info()
if err == nil {
icon := icons.getIcon(info)
if icon != "" {
name += icon + " "
}
}
}
name += files[n].Name()
if callback != nil {
callback(files[n].Name(), i, j)
}
if files[n].IsDir() {
// Dirs should have a slash at the end.
name += fileSeparator
}
n++
}
if max < len(name) {
max = len(name)
}
names[i][j] = name
}
// Append spaces to make all names in one column of same size.
for j := 0; j < rows; j++ {
names[i][j] += Repeat(" ", max-len(names[i][j]))
}
}
for j := 0; j < rows; j++ {
row := make([]string, columns)
for i := 0; i < columns; i++ {
row[i] = names[i][j]
}
if len(Join(row, separator)) > width && columns > 1 {
// Yep. No luck, let's decrease number of columns and try one more time.
columns--
goto start
}
}
return names, rows, columns
}