package files import ( "sort" "strings" "github.com/maruel/natural" ) // Listing is a collection of files. type Listing struct { Items []*FileInfo `json:"items"` NumDirs int `json:"numDirs"` NumFiles int `json:"numFiles"` Sorting Sorting `json:"sorting"` } // ApplySort applies the sort order using .Order and .Sort // //nolint:goconst func (l Listing) ApplySort() { // Check '.Order' to know how to sort if !l.Sorting.Asc { switch l.Sorting.By { case "name": sort.Sort(sort.Reverse(byName(l))) case "size": sort.Sort(sort.Reverse(bySize(l))) case "modified": sort.Sort(sort.Reverse(byModified(l))) default: // If not one of the above, do nothing return } } else { // If we had more Orderings we could add them here switch l.Sorting.By { case "name": sort.Sort(byName(l)) case "size": sort.Sort(bySize(l)) case "modified": sort.Sort(byModified(l)) default: sort.Sort(byName(l)) return } } } // Implement sorting for Listing type byName Listing type bySize Listing type byModified Listing // By Name func (l byName) Len() int { return len(l.Items) } func (l byName) Swap(i, j int) { l.Items[i], l.Items[j] = l.Items[j], l.Items[i] } // Treat upper and lower case equally func (l byName) Less(i, j int) bool { if l.Items[i].IsDir && !l.Items[j].IsDir { return l.Sorting.Asc } if !l.Items[i].IsDir && l.Items[j].IsDir { return !l.Sorting.Asc } return natural.Less(strings.ToLower(l.Items[j].Name), strings.ToLower(l.Items[i].Name)) } // By Size func (l bySize) Len() int { return len(l.Items) } func (l bySize) Swap(i, j int) { l.Items[i], l.Items[j] = l.Items[j], l.Items[i] } const directoryOffset = -1 << 31 // = math.MinInt32 func (l bySize) Less(i, j int) bool { iSize, jSize := l.Items[i].Size, l.Items[j].Size if l.Items[i].IsDir { iSize = directoryOffset + iSize } if l.Items[j].IsDir { jSize = directoryOffset + jSize } return iSize < jSize } // By Modified func (l byModified) Len() int { return len(l.Items) } func (l byModified) Swap(i, j int) { l.Items[i], l.Items[j] = l.Items[j], l.Items[i] } func (l byModified) Less(i, j int) bool { iModified, jModified := l.Items[i].ModTime, l.Items[j].ModTime return iModified.Sub(jModified) < 0 }