github.com/xyproto/orbiton/v2@v2.65.12-0.20240516144430-e10a419274ec/fstab.go (about) 1 package main 2 3 import ( 4 "bytes" 5 ) 6 7 // formatFstab can format the contents of /etc/fstab files. The suggested number of spaces is 2. 8 func formatFstab(data []byte, spaces int) []byte { 9 var ( 10 buf bytes.Buffer 11 nl = []byte{'\n'} 12 longest = make(map[int]int) // The longest length of a field, for each field index 13 byteLines = bytes.Split(data, nl) 14 ) 15 16 // Find the longest field length for each field on each line 17 for _, line := range byteLines { 18 trimmedLine := bytes.TrimSpace(line) 19 if len(trimmedLine) == 0 || bytes.HasPrefix(trimmedLine, []byte{'#'}) { 20 continue 21 } 22 // Find the longest field length for each field 23 for i, field := range bytes.Fields(trimmedLine) { 24 fieldLength := len(string(field)) 25 if val, ok := longest[i]; ok { 26 if fieldLength > val { 27 longest[i] = fieldLength 28 } 29 } else { 30 longest[i] = fieldLength 31 } 32 } 33 } 34 35 // Format the lines nicely 36 for i, line := range byteLines { 37 38 // Get the previous line, if possible 39 var prevLineTrimmed []byte 40 if (i - 1) > 0 { 41 prevLineTrimmed = bytes.TrimSpace(byteLines[i-1]) 42 } 43 44 // Get the current line 45 thisLineTrimmed := bytes.TrimSpace(line) 46 47 // Get the next line, if possible 48 var nextLineTrimmed []byte 49 if (i + 1) < len(byteLines) { 50 nextLineTrimmed = bytes.TrimSpace(byteLines[i+1]) 51 } 52 53 // Get the next next line, if possible 54 var nextNextLineTrimmed []byte 55 if (i + 2) < len(byteLines) { 56 nextNextLineTrimmed = bytes.TrimSpace(byteLines[i+2]) 57 } 58 59 // Get the next next next line, if possible 60 var nextNextNextLineTrimmed []byte 61 if (i + 3) < len(byteLines) { 62 nextNextLineTrimmed = bytes.TrimSpace(byteLines[i+3]) 63 } 64 65 // Gather stats for if the lines are blank 66 prevLineIsBlank := len(prevLineTrimmed) == 0 67 thisLineIsBlank := len(thisLineTrimmed) == 0 68 nextLineIsBlank := len(nextLineTrimmed) == 0 69 nextNextLineIsBlank := len(nextNextLineTrimmed) == 0 70 nextNextNextLineIsBlank := len(nextNextNextLineTrimmed) == 0 71 72 // Gether stats for if the lines are comments 73 prevLineIsComment := bytes.HasPrefix(prevLineTrimmed, []byte{'#'}) 74 thisLineIsComment := bytes.HasPrefix(thisLineTrimmed, []byte{'#'}) 75 nextLineIsComment := bytes.HasPrefix(nextLineTrimmed, []byte{'#'}) 76 nextNextLineIsComment := bytes.HasPrefix(nextNextLineTrimmed, []byte{'#'}) 77 nextNextNextLineIsComment := bytes.HasPrefix(nextNextNextLineTrimmed, []byte{'#'}) 78 79 // Gether stats for if the lines have content 80 prevLineIsContent := !prevLineIsBlank && !prevLineIsComment 81 nextLineIsContent := !nextLineIsBlank && !nextLineIsComment 82 nextNextLineIsContent := !nextNextLineIsBlank && !nextNextLineIsComment 83 nextNextNextLineIsContent := !nextNextNextLineIsBlank && !nextNextNextLineIsComment 84 85 if thisLineIsBlank { 86 if prevLineIsContent && nextLineIsComment { 87 buf.Write(nl) 88 } else if nextLineIsComment && nextNextLineIsContent { 89 buf.Write(nl) 90 } else if prevLineIsComment && nextLineIsComment && (nextNextLineIsContent || (nextNextLineIsBlank && nextNextNextLineIsContent)) { 91 buf.Write(nl) 92 } 93 } else if thisLineIsComment { 94 if prevLineIsComment && nextLineIsContent { 95 buf.Write(nl) 96 } else if prevLineIsBlank && nextLineIsContent { 97 buf.Write(nl) 98 } else if prevLineIsContent && nextLineIsContent { 99 buf.Write(nl) 100 } 101 buf.Write(thisLineTrimmed) 102 buf.Write(nl) 103 } else { // This line has contents, format the fields 104 for i, field := range bytes.Fields(thisLineTrimmed) { 105 fieldLength := len(string(field)) 106 padCount := spaces // Space between the fields if all fields have equal length 107 if longest[i] > fieldLength { 108 padCount += longest[i] - fieldLength 109 } 110 buf.Write(field) 111 if padCount > 0 { 112 buf.Write(bytes.Repeat([]byte{' '}, padCount)) 113 } 114 } 115 buf.Write(nl) 116 } 117 } 118 // TODO: Find out why double blank lines are sometimes inserted below, when pressing ctrl-w twice, 119 // to avoid using bytes.ReplaceAll. 120 return bytes.ReplaceAll(buf.Bytes(), []byte{'\n', '\n', '\n'}, []byte{'\n', '\n'}) 121 }