-
Notifications
You must be signed in to change notification settings - Fork 6
/
fstab.go
121 lines (108 loc) · 3.9 KB
/
fstab.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
package main
import (
"bytes"
)
// format can format the contents of /etc/fstab files. The suggested number of spaces is 2.
func format(data []byte, spaces int) []byte {
var (
buf bytes.Buffer
nl = []byte{'\n'}
longest = make(map[int]int) // The longest length of a field, for each field index
byteLines = bytes.Split(data, nl)
)
// Find the longest field length for each field on each line
for _, line := range byteLines {
trimmedLine := bytes.TrimSpace(line)
if len(trimmedLine) == 0 || bytes.HasPrefix(trimmedLine, []byte{'#'}) {
continue
}
// Find the longest field length for each field
for i, field := range bytes.Fields(trimmedLine) {
fieldLength := len(string(field))
if val, ok := longest[i]; ok {
if fieldLength > val {
longest[i] = fieldLength
}
} else {
longest[i] = fieldLength
}
}
}
// Format the lines nicely
for i, line := range byteLines {
// Get the previous line, if possible
var prevLineTrimmed []byte
if (i - 1) > 0 {
prevLineTrimmed = bytes.TrimSpace(byteLines[i-1])
}
// Get the current line
thisLineTrimmed := bytes.TrimSpace(line)
// Get the next line, if possible
var nextLineTrimmed []byte
if (i + 1) < len(byteLines) {
nextLineTrimmed = bytes.TrimSpace(byteLines[i+1])
}
// Get the next next line, if possible
var nextNextLineTrimmed []byte
if (i + 2) < len(byteLines) {
nextNextLineTrimmed = bytes.TrimSpace(byteLines[i+2])
}
// Get the next next next line, if possible
var nextNextNextLineTrimmed []byte
if (i + 3) < len(byteLines) {
nextNextLineTrimmed = bytes.TrimSpace(byteLines[i+3])
}
// Gather stats for if the lines are blank
prevLineIsBlank := len(prevLineTrimmed) == 0
thisLineIsBlank := len(thisLineTrimmed) == 0
nextLineIsBlank := len(nextLineTrimmed) == 0
nextNextLineIsBlank := len(nextNextLineTrimmed) == 0
nextNextNextLineIsBlank := len(nextNextNextLineTrimmed) == 0
// Gether stats for if the lines are comments
prevLineIsComment := bytes.HasPrefix(prevLineTrimmed, []byte{'#'})
thisLineIsComment := bytes.HasPrefix(thisLineTrimmed, []byte{'#'})
nextLineIsComment := bytes.HasPrefix(nextLineTrimmed, []byte{'#'})
nextNextLineIsComment := bytes.HasPrefix(nextNextLineTrimmed, []byte{'#'})
nextNextNextLineIsComment := bytes.HasPrefix(nextNextNextLineTrimmed, []byte{'#'})
// Gether stats for if the lines have content
prevLineIsContent := !prevLineIsBlank && !prevLineIsComment
nextLineIsContent := !nextLineIsBlank && !nextLineIsComment
nextNextLineIsContent := !nextNextLineIsBlank && !nextNextLineIsComment
nextNextNextLineIsContent := !nextNextNextLineIsBlank && !nextNextNextLineIsComment
if thisLineIsBlank {
if prevLineIsContent && nextLineIsComment {
buf.Write(nl)
} else if nextLineIsComment && nextNextLineIsContent {
buf.Write(nl)
} else if prevLineIsComment && nextLineIsComment && (nextNextLineIsContent || (nextNextLineIsBlank && nextNextNextLineIsContent)) {
buf.Write(nl)
}
} else if thisLineIsComment {
if prevLineIsComment && nextLineIsContent {
buf.Write(nl)
} else if prevLineIsBlank && nextLineIsContent {
buf.Write(nl)
} else if prevLineIsContent && nextLineIsContent {
buf.Write(nl)
}
buf.Write(thisLineTrimmed)
buf.Write(nl)
} else { // This line has contents, format the fields
for i, field := range bytes.Fields(thisLineTrimmed) {
fieldLength := len(string(field))
padCount := spaces // Space between the fields if all fields have equal length
if longest[i] > fieldLength {
padCount += longest[i] - fieldLength
}
buf.Write(field)
if padCount > 0 {
buf.Write(bytes.Repeat([]byte{' '}, padCount))
}
}
buf.Write(nl)
}
}
// TODO: Find out why double blank lines are sometimes inserted below,
// when formatting twice, to avoid using bytes.ReplaceAll.
return bytes.ReplaceAll(buf.Bytes(), []byte{'\n', '\n', '\n'}, []byte{'\n', '\n'})
}