| 
									
										
										
										
											2019-01-05 22:44:33 +00:00
										 |  |  | package files | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"sort" | 
					
						
							| 
									
										
										
										
											2019-02-03 14:50:08 +00:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2019-01-05 22:44:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"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
 | 
					
						
							| 
									
										
										
										
											2020-05-31 23:12:36 +00:00
										 |  |  | //nolint:goconst
 | 
					
						
							| 
									
										
										
										
											2019-01-05 22:44:33 +00:00
										 |  |  | func (l Listing) ApplySort() { | 
					
						
							|  |  |  | 	// Check '.Order' to know how to sort
 | 
					
						
							| 
									
										
										
										
											2020-05-31 23:12:36 +00:00
										 |  |  | 	// TODO: use enum
 | 
					
						
							| 
									
										
										
										
											2019-01-05 22:44:33 +00:00
										 |  |  | 	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 { | 
					
						
							| 
									
										
										
										
											2020-01-05 18:28:17 +00:00
										 |  |  | 		return l.Sorting.Asc | 
					
						
							| 
									
										
										
										
											2019-01-05 22:44:33 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !l.Items[i].IsDir && l.Items[j].IsDir { | 
					
						
							| 
									
										
										
										
											2020-01-05 18:28:17 +00:00
										 |  |  | 		return !l.Sorting.Asc | 
					
						
							| 
									
										
										
										
											2019-01-05 22:44:33 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-03 14:50:08 +00:00
										 |  |  | 	return natural.Less(strings.ToLower(l.Items[j].Name), strings.ToLower(l.Items[i].Name)) | 
					
						
							| 
									
										
										
										
											2019-01-05 22:44:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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 | 
					
						
							|  |  |  | } |