2016-08-30 21:44:58 +03:00
|
|
|
/**
|
|
|
|
* Tae Won Ha - http://taewon.de - @hataewon
|
|
|
|
* See LICENSE
|
|
|
|
*/
|
|
|
|
|
|
|
|
import Foundation
|
|
|
|
|
2017-02-13 21:31:10 +03:00
|
|
|
fileprivate let workspace = NSWorkspace.shared()
|
|
|
|
fileprivate let iconsCache = NSCache<NSURL, NSImage>()
|
|
|
|
|
2016-08-30 21:44:58 +03:00
|
|
|
class FileUtils {
|
|
|
|
|
2016-09-25 18:50:33 +03:00
|
|
|
fileprivate static let keysToGet = [
|
|
|
|
URLResourceKey.isDirectoryKey,
|
|
|
|
URLResourceKey.isHiddenKey,
|
|
|
|
URLResourceKey.isAliasFileKey,
|
|
|
|
URLResourceKey.isSymbolicLinkKey
|
2016-08-30 21:44:58 +03:00
|
|
|
]
|
|
|
|
|
2016-09-25 18:50:33 +03:00
|
|
|
fileprivate static let scanOptions: FileManager.DirectoryEnumerationOptions = [
|
|
|
|
FileManager.DirectoryEnumerationOptions.skipsSubdirectoryDescendants,
|
|
|
|
FileManager.DirectoryEnumerationOptions.skipsPackageDescendants
|
2016-08-30 21:44:58 +03:00
|
|
|
]
|
|
|
|
|
2016-09-25 18:50:33 +03:00
|
|
|
fileprivate static let fileManager = FileManager.default
|
2016-10-02 13:28:47 +03:00
|
|
|
|
|
|
|
static let userHomeUrl = URL(fileURLWithPath: NSHomeDirectory(), isDirectory: true)
|
2016-08-30 21:44:58 +03:00
|
|
|
|
2016-11-24 02:08:41 +03:00
|
|
|
static func directDescendants(of url: URL) -> [URL] {
|
2016-09-25 18:50:33 +03:00
|
|
|
guard let childUrls = try? self.fileManager.contentsOfDirectory(
|
|
|
|
at: url, includingPropertiesForKeys: self.keysToGet, options: self.scanOptions
|
2016-08-30 21:44:58 +03:00
|
|
|
) else {
|
|
|
|
// FIXME error handling
|
|
|
|
return []
|
|
|
|
}
|
|
|
|
|
|
|
|
return childUrls
|
|
|
|
}
|
|
|
|
|
2016-11-24 02:08:41 +03:00
|
|
|
static func fileExists(at url: URL) -> Bool {
|
2016-09-25 18:50:33 +03:00
|
|
|
guard url.isFileURL else {
|
2016-08-30 21:44:58 +03:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2016-09-25 18:50:33 +03:00
|
|
|
let path = url.path
|
|
|
|
return self.fileManager.fileExists(atPath: path)
|
2016-08-30 21:44:58 +03:00
|
|
|
}
|
|
|
|
|
2016-11-05 17:17:43 +03:00
|
|
|
static func commonParent(of urls: [URL]) -> URL {
|
2016-08-30 21:44:58 +03:00
|
|
|
guard urls.count > 0 else {
|
2016-09-25 18:50:33 +03:00
|
|
|
return URL(fileURLWithPath: "/", isDirectory: true)
|
2016-08-30 21:44:58 +03:00
|
|
|
}
|
|
|
|
|
2016-09-25 18:50:33 +03:00
|
|
|
let pathComps = urls.map { $0.pathComponents }
|
2016-10-07 19:06:58 +03:00
|
|
|
let min = pathComps.map { $0.count }.min()!
|
|
|
|
let pathCompsOnlyMin = pathComps.map { $0[0..<min] }
|
2016-10-07 01:24:15 +03:00
|
|
|
let commonIdx = (0..<min).reversed().reduce(min - 1) { (result, idx) in
|
|
|
|
if Set(pathCompsOnlyMin.map { $0[idx] }).count > 1 {
|
|
|
|
return idx - 1
|
|
|
|
} else {
|
|
|
|
return result
|
|
|
|
}
|
2016-08-30 21:44:58 +03:00
|
|
|
}
|
|
|
|
|
2016-10-07 01:24:15 +03:00
|
|
|
let result = pathCompsOnlyMin[0]
|
|
|
|
let possibleParent = NSURL.fileURL(withPathComponents: Array(result[0...commonIdx]))!
|
|
|
|
|
2016-11-12 18:42:10 +03:00
|
|
|
return possibleParent.isDir ? possibleParent : possibleParent.parent
|
2016-08-30 21:44:58 +03:00
|
|
|
}
|
2017-02-13 21:31:10 +03:00
|
|
|
|
|
|
|
static func icon(forType type: String) -> NSImage {
|
|
|
|
return workspace.icon(forFileType: type)
|
|
|
|
}
|
|
|
|
|
|
|
|
static func icon(forUrl url: URL) -> NSImage? {
|
|
|
|
if let cached = iconsCache.object(forKey: url as NSURL) {
|
|
|
|
return cached
|
|
|
|
}
|
|
|
|
|
|
|
|
let path = url.path
|
|
|
|
let icon = workspace.icon(forFile: path)
|
|
|
|
icon.size = CGSize(width: 16, height: 16)
|
|
|
|
iconsCache.setObject(icon, forKey: url as NSURL)
|
|
|
|
|
|
|
|
return icon
|
|
|
|
}
|
2016-08-30 21:44:58 +03:00
|
|
|
}
|