Remove Entry since it is barely worthwhile sugar
This commit is contained in:
17
README.md
17
README.md
@@ -151,24 +151,25 @@ the name thus implies its behavior, ie. that it is not recursive and doesn’t
|
|||||||
list hidden files.
|
list hidden files.
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
for entry in Path.home.ls() {
|
for path in Path.home.ls() {
|
||||||
print(entry.path)
|
|
||||||
print(entry.kind) // .directory or .file
|
|
||||||
}
|
|
||||||
|
|
||||||
for entry in Path.home.ls() where entry.kind == .file {
|
|
||||||
//…
|
//…
|
||||||
}
|
}
|
||||||
|
|
||||||
for entry in Path.home.ls() where entry.path.mtime > yesterday {
|
for path in Path.home.ls() where path.isFile {
|
||||||
|
//…
|
||||||
|
}
|
||||||
|
|
||||||
|
for path in Path.home.ls() where path.mtime > yesterday {
|
||||||
//…
|
//…
|
||||||
}
|
}
|
||||||
|
|
||||||
let dirs = Path.home.ls().directories
|
let dirs = Path.home.ls().directories
|
||||||
|
// ^^ directories that *exist*
|
||||||
|
|
||||||
let files = Path.home.ls().files
|
let files = Path.home.ls().files
|
||||||
|
// ^^ files that both *exist* and are *not* directories
|
||||||
|
|
||||||
let swiftFiles = Path.home.ls().files(withExtension: "swift")
|
let swiftFiles = Path.home.ls().files.filter{ $0.extension == "swift" }
|
||||||
```
|
```
|
||||||
|
|
||||||
We provide `find()` for recursive listing:
|
We provide `find()` for recursive listing:
|
||||||
|
|||||||
@@ -1,24 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public extension Path {
|
public extension Path {
|
||||||
/**
|
|
||||||
A file entry from a directory listing.
|
|
||||||
- SeeAlso: `ls()`
|
|
||||||
*/
|
|
||||||
struct Entry {
|
|
||||||
/// The kind of this directory entry.
|
|
||||||
public enum Kind {
|
|
||||||
/// The path is a file.
|
|
||||||
case file
|
|
||||||
/// The path is a directory.
|
|
||||||
case directory
|
|
||||||
}
|
|
||||||
/// The kind of this entry.
|
|
||||||
public let kind: Kind
|
|
||||||
/// The path of this entry.
|
|
||||||
public let path: Path
|
|
||||||
}
|
|
||||||
|
|
||||||
class Finder {
|
class Finder {
|
||||||
fileprivate init(path: Path) {
|
fileprivate init(path: Path) {
|
||||||
self.path = path
|
self.path = path
|
||||||
@@ -110,7 +92,7 @@ public extension Pathish {
|
|||||||
- Parameter options: Configure the listing.
|
- Parameter options: Configure the listing.
|
||||||
- Important: On Linux the listing is always `ls -a`
|
- Important: On Linux the listing is always `ls -a`
|
||||||
*/
|
*/
|
||||||
func ls(_ options: ListDirectoryOptions? = nil) -> [Path.Entry] {
|
func ls(_ options: ListDirectoryOptions? = nil) -> [Path] {
|
||||||
guard let urls = try? FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil) else {
|
guard let urls = try? FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil) else {
|
||||||
fputs("warning: could not list: \(self)\n", stderr)
|
fputs("warning: could not list: \(self)\n", stderr)
|
||||||
return []
|
return []
|
||||||
@@ -119,7 +101,7 @@ public extension Pathish {
|
|||||||
guard let path = Path(url.path) else { return nil }
|
guard let path = Path(url.path) else { return nil }
|
||||||
if options != .a, path.basename().hasPrefix(".") { return nil }
|
if options != .a, path.basename().hasPrefix(".") { return nil }
|
||||||
// ^^ we don’t use the Foundation `skipHiddenFiles` because it considers weird things hidden and we are mirroring `ls`
|
// ^^ we don’t use the Foundation `skipHiddenFiles` because it considers weird things hidden and we are mirroring `ls`
|
||||||
return .init(kind: path.isDirectory ? .directory : .file, path: path)
|
return path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,26 +110,20 @@ public extension Pathish {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience functions for the array return value of `Path.ls()`
|
/// Convenience functions for the arraies of `Path`
|
||||||
public extension Array where Element == Path.Entry {
|
public extension Array where Element == Path {
|
||||||
/// Filters the list of entries to be a list of Paths that are directories.
|
/// Filters the list of entries to be a list of Paths that are directories. Symlinks to directories are not returned.
|
||||||
var directories: [Path] {
|
var directories: [Path] {
|
||||||
return compactMap {
|
return filter {
|
||||||
$0.kind == .directory ? $0.path : nil
|
$0.isDirectory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Filters the list of entries to be a list of Paths that are files.
|
/// Filters the list of entries to be a list of Paths that exist and are *not* directories. Thus expect symlinks, etc.
|
||||||
|
/// - Note: symlinks that point to files that do not exist are *not* returned.
|
||||||
var files: [Path] {
|
var files: [Path] {
|
||||||
return compactMap {
|
return filter {
|
||||||
$0.kind == .file ? $0.path : nil
|
$0.exists && !$0.isDirectory
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Filters the list of entries to be a list of Paths that are files with the specified extension.
|
|
||||||
func files(withExtension ext: String) -> [Path] {
|
|
||||||
return compactMap {
|
|
||||||
$0.kind == .file && $0.path.extension == ext ? $0.path : nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,24 +28,23 @@ class PathTests: XCTestCase {
|
|||||||
var paths = Set<String>()
|
var paths = Set<String>()
|
||||||
let lsrv = tmpdir.ls(.a)
|
let lsrv = tmpdir.ls(.a)
|
||||||
var dirs = 0
|
var dirs = 0
|
||||||
for entry in lsrv {
|
for path in lsrv {
|
||||||
if entry.kind == .directory {
|
if path.isDirectory {
|
||||||
dirs += 1
|
dirs += 1
|
||||||
}
|
}
|
||||||
paths.insert(entry.path.basename())
|
paths.insert(path.basename())
|
||||||
}
|
}
|
||||||
XCTAssertEqual(dirs, 2)
|
XCTAssertEqual(dirs, 2)
|
||||||
XCTAssertEqual(dirs, lsrv.directories.count)
|
XCTAssertEqual(dirs, lsrv.directories.count)
|
||||||
XCTAssertEqual(["a", ".d"], Set(lsrv.directories.map{ $0.relative(to: tmpdir) }))
|
XCTAssertEqual(["a", ".d"], Set(lsrv.directories.map{ $0.relative(to: tmpdir) }))
|
||||||
XCTAssertEqual(["b.swift", "c"], Set(lsrv.files.map{ $0.relative(to: tmpdir) }))
|
XCTAssertEqual(["b.swift", "c"], Set(lsrv.files.map{ $0.relative(to: tmpdir) }))
|
||||||
XCTAssertEqual(["b.swift"], Set(lsrv.files(withExtension: "swift").map{ $0.relative(to: tmpdir) }))
|
XCTAssertEqual(["b.swift"], Set(lsrv.files.filter{ $0.extension == "swift" }.map{ $0.relative(to: tmpdir) }))
|
||||||
XCTAssertEqual(["c"], Set(lsrv.files(withExtension: "").map{ $0.relative(to: tmpdir) }))
|
XCTAssertEqual(["c"], Set(lsrv.files.filter{ $0.extension == "" }.map{ $0.relative(to: tmpdir) }))
|
||||||
XCTAssertEqual(paths, ["a", "b.swift", "c", ".d"])
|
XCTAssertEqual(paths, ["a", "b.swift", "c", ".d"])
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testEnumerationSkippingHiddenFiles() throws {
|
func testEnumerationSkippingHiddenFiles() throws {
|
||||||
#if !os(Linux)
|
|
||||||
let tmpdir_ = try TemporaryDirectory()
|
let tmpdir_ = try TemporaryDirectory()
|
||||||
let tmpdir = tmpdir_.path
|
let tmpdir = tmpdir_.path
|
||||||
try tmpdir.join("a").mkdir().join("c").touch()
|
try tmpdir.join("a").mkdir().join("c").touch()
|
||||||
@@ -55,15 +54,14 @@ class PathTests: XCTestCase {
|
|||||||
|
|
||||||
var paths = Set<String>()
|
var paths = Set<String>()
|
||||||
var dirs = 0
|
var dirs = 0
|
||||||
for entry in tmpdir.ls() {
|
for path in tmpdir.ls() {
|
||||||
if entry.kind == .directory {
|
if path.isDirectory {
|
||||||
dirs += 1
|
dirs += 1
|
||||||
}
|
}
|
||||||
paths.insert(entry.path.basename())
|
paths.insert(path.basename())
|
||||||
}
|
}
|
||||||
XCTAssertEqual(dirs, 1)
|
XCTAssertEqual(dirs, 1)
|
||||||
XCTAssertEqual(paths, ["a", "b", "c"])
|
XCTAssertEqual(paths, ["a", "b", "c"])
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testRelativeTo() {
|
func testRelativeTo() {
|
||||||
|
|||||||
Reference in New Issue
Block a user