Skip to content

Commit 2c93567

Browse files
authored
naturally orders files and folders #1714 (#1774)
1 parent c1c3abb commit 2c93567

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

CodeEdit/Utils/Extensions/Array/Array+SortURLs.swift

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,39 @@ extension Array where Element == URL {
1818
/// Sorts the elements in alphabetical order.
1919
/// - Parameter foldersOnTop: if set to `true` folders will always be on top of files.
2020
/// - Returns: A sorted array of `URL`
21-
func sortItems(foldersOnTop: Bool) -> Self {
22-
var alphabetically = sorted { $0.lastPathComponent < $1.lastPathComponent }
21+
func sortItems(foldersOnTop: Bool) -> [URL] {
22+
return self.sorted { lhs, rhs in
23+
let lhsIsDir = (try? lhs.resourceValues(forKeys: [.isDirectoryKey]).isDirectory) ?? false
24+
let rhsIsDir = (try? rhs.resourceValues(forKeys: [.isDirectoryKey]).isDirectory) ?? false
2325

24-
if foldersOnTop {
25-
var foldersOnTop = alphabetically.filter { $0.isFolder }
26-
alphabetically.removeAll { $0.isFolder }
26+
if foldersOnTop {
27+
if lhsIsDir != rhsIsDir {
28+
return lhsIsDir
29+
}
30+
}
2731

28-
foldersOnTop.append(contentsOf: alphabetically)
32+
return compareNaturally(lhs.lastPathComponent, rhs.lastPathComponent)
33+
}
34+
}
2935

30-
return foldersOnTop
31-
} else {
32-
return alphabetically
36+
/// Compare two strings using natural sorting.
37+
/// - Parameters:
38+
/// - lhs: The left-hand string.
39+
/// - rhs: The right-hand string.
40+
/// - Returns: `true` if `lhs` should be ordered before `rhs`.
41+
private func compareNaturally(_ lhs: String, _ rhs: String) -> Bool {
42+
let lhsComponents = lhs.components(separatedBy: CharacterSet.decimalDigits.inverted)
43+
let rhsComponents = rhs.components(separatedBy: CharacterSet.decimalDigits.inverted)
44+
45+
for (lhsPart, rhsPart) in zip(lhsComponents, rhsComponents) where lhsPart != rhsPart {
46+
if let lhsNum = Int(lhsPart), let rhsNum = Int(rhsPart) {
47+
return lhsNum < rhsNum
48+
} else {
49+
return lhsPart < rhsPart
50+
}
3351
}
52+
53+
return lhs < rhs
3454
}
3555
}
3656

0 commit comments

Comments
 (0)