Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c432f710eb | ||
|
|
19c0c19bb6 | ||
|
|
ee1f46954c | ||
|
|
2394cc1c85 | ||
|
|
50bb319619 | ||
|
|
9f40068833 |
17
README.md
17
README.md
@@ -33,7 +33,7 @@ print(foo) // => /bar/foo
|
||||
print(foo.isFile) // => true
|
||||
|
||||
// we support dynamic members (_use_sparingly_):
|
||||
let prefs = Path.home.Library.Preferences
|
||||
let prefs = Path.home.Library.Preferences // => /Users/mxcl/Library/Preferences
|
||||
|
||||
// a practical example: installing a helper executable
|
||||
try Bundle.resources.join("helper").copy(into: Path.home.join(".local/bin").mkdir(.p)).chmod(0o500)
|
||||
@@ -107,8 +107,9 @@ let ls = Path.root.usr.bin.ls // => /usr/bin/ls
|
||||
```
|
||||
|
||||
This is less commonly useful than you would think, hence our documentation
|
||||
does not use it. Usually you are joining variables or other `String` arguments.
|
||||
However when you need it, it’s *lovely*.
|
||||
does not use it. Usually you are joining variables or other `String` arguments
|
||||
or trying to describe files (and files usually have extensions). However when
|
||||
you need it, it’s *lovely*.
|
||||
|
||||
## Initializing from user-input
|
||||
|
||||
@@ -160,9 +161,9 @@ for entry in Path.home.ls() where entry.path.mtime > yesterday {
|
||||
//…
|
||||
}
|
||||
|
||||
let dirs = Path.home.ls().directories().filter {
|
||||
//…
|
||||
}
|
||||
let dirs = Path.home.ls().directories
|
||||
|
||||
let files = Path.home.ls().files
|
||||
|
||||
let swiftFiles = Path.home.ls().files(withExtension: "swift")
|
||||
```
|
||||
@@ -220,7 +221,7 @@ package.append(.package(url: "https://github.com/mxcl/Path.swift", from: "0.5.0"
|
||||
CocoaPods:
|
||||
|
||||
```ruby
|
||||
pod 'Path.swift' ~> '0.5.0'
|
||||
pod 'Path.swift', '~> 0.5'
|
||||
```
|
||||
|
||||
Carthage:
|
||||
@@ -244,5 +245,5 @@ https://codebasesaga.com/canopy/
|
||||
|
||||
|
||||
[badge-platforms]: https://img.shields.io/badge/platforms-macOS%20%7C%20Linux%20%7C%20iOS%20%7C%20tvOS%20%7C%20watchOS-lightgrey.svg
|
||||
[badge-languages]: https://img.shields.io/badge/swift-4.2-orange.svg
|
||||
[badge-languages]: https://img.shields.io/badge/swift-4.2%20%7C%205.0-orange.svg
|
||||
[online API documentation]: https://mxcl.github.io/Path.swift/Structs/Path.html
|
||||
|
||||
@@ -86,3 +86,24 @@ public extension Data {
|
||||
return to
|
||||
}
|
||||
}
|
||||
|
||||
/// Extensions on `FileHandle` that work with `Path` rather than `String` or `URL`
|
||||
public extension FileHandle {
|
||||
/// Initializes this `FileHandle` for reading at the location of the provided path.
|
||||
@inlinable
|
||||
convenience init(forReadingAt path: Path) throws {
|
||||
try self.init(forReadingFrom: path.url)
|
||||
}
|
||||
|
||||
/// Initializes this `FileHandle` for writing at the location of the provided path.
|
||||
@inlinable
|
||||
convenience init(forWritingAt path: Path) throws {
|
||||
try self.init(forWritingTo: path.url)
|
||||
}
|
||||
|
||||
/// Initializes this `FileHandle` for reading and writing at the location of the provided path.
|
||||
@inlinable
|
||||
convenience init(forUpdatingAt path: Path) throws {
|
||||
try self.init(forUpdating: path.url)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,14 @@ public extension Array where Element == Entry {
|
||||
}
|
||||
}
|
||||
|
||||
/// Filters the list of entries to be a list of Paths that are files with the specified extension
|
||||
/// Filters the list of entries to be a list of Paths that are files.
|
||||
var files: [Path] {
|
||||
return compactMap {
|
||||
$0.kind == .file ? $0.path : nil
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
||||
@@ -36,7 +36,7 @@ public struct Path: Equatable, Hashable, Comparable {
|
||||
self.string = string
|
||||
}
|
||||
|
||||
/// Returns `nil` unless fed an absolute path
|
||||
/// Returns `nil` unless fed an absolute path.
|
||||
public init?(_ description: String) {
|
||||
guard description.starts(with: "/") || description.starts(with: "~/") else { return nil }
|
||||
self.init(string: (description as NSString).standardizingPath)
|
||||
@@ -73,11 +73,16 @@ public struct Path: Equatable, Hashable, Comparable {
|
||||
/**
|
||||
Returns the filename extension of this path.
|
||||
- Remark: Implemented via `NSString.pathExtension`.
|
||||
- Note: We special case eg. `foo.tar.gz`.
|
||||
*/
|
||||
@inlinable
|
||||
public var `extension`: String {
|
||||
if string.hasSuffix(".tar.gz") {
|
||||
return "tar.gz"
|
||||
} else {
|
||||
return (string as NSString).pathExtension
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: Pathing
|
||||
|
||||
@@ -91,7 +96,7 @@ public struct Path: Equatable, Hashable, Comparable {
|
||||
|
||||
- Parameter pathComponent: The string to join with this path.
|
||||
- Returns: A new joined path.
|
||||
- SeeAlso: `Path./(_:, _:)`
|
||||
- SeeAlso: `Path./(_:_:)`
|
||||
*/
|
||||
public func join<S>(_ pathComponent: S) -> Path where S: StringProtocol {
|
||||
//TODO standardizingPath does more than we want really (eg tilde expansion)
|
||||
|
||||
@@ -15,20 +15,26 @@ class PathTests: XCTestCase {
|
||||
let tmpdir_ = try TemporaryDirectory()
|
||||
let tmpdir = tmpdir_.path
|
||||
try tmpdir.a.mkdir().c.touch()
|
||||
try tmpdir.b.touch()
|
||||
try tmpdir.join("b.swift").touch()
|
||||
try tmpdir.c.touch()
|
||||
try tmpdir.join(".d").mkdir().e.touch()
|
||||
|
||||
var paths = Set<String>()
|
||||
let lsrv = try tmpdir.ls()
|
||||
var dirs = 0
|
||||
for entry in try tmpdir.ls() {
|
||||
for entry in lsrv {
|
||||
if entry.kind == .directory {
|
||||
dirs += 1
|
||||
}
|
||||
paths.insert(entry.path.basename())
|
||||
}
|
||||
XCTAssertEqual(dirs, 2)
|
||||
XCTAssertEqual(paths, ["a", "b", "c", ".d"])
|
||||
XCTAssertEqual(dirs, lsrv.directories.count)
|
||||
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"], Set(lsrv.files(withExtension: "swift").map{ $0.relative(to: tmpdir) }))
|
||||
XCTAssertEqual(["c"], Set(lsrv.files(withExtension: "").map{ $0.relative(to: tmpdir) }))
|
||||
XCTAssertEqual(paths, ["a", "b.swift", "c", ".d"])
|
||||
|
||||
}
|
||||
|
||||
@@ -69,6 +75,18 @@ class PathTests: XCTestCase {
|
||||
XCTAssert((Path.root/"bin").isDirectory)
|
||||
}
|
||||
|
||||
func testExtension() {
|
||||
XCTAssertEqual(Path.root.join("a.swift").extension, "swift")
|
||||
XCTAssertEqual(Path.root.join("a").extension, "")
|
||||
XCTAssertEqual(Path.root.join("a.").extension, "")
|
||||
XCTAssertEqual(Path.root.join("a..").extension, "")
|
||||
XCTAssertEqual(Path.root.join("a..swift").extension, "swift")
|
||||
XCTAssertEqual(Path.root.join("a..swift.").extension, "")
|
||||
XCTAssertEqual(Path.root.join("a.tar.gz").extension, "tar.gz")
|
||||
XCTAssertEqual(Path.root.join("a..tar.gz").extension, "tar.gz")
|
||||
XCTAssertEqual(Path.root.join("a..tar..gz").extension, "gz")
|
||||
}
|
||||
|
||||
func testMktemp() throws {
|
||||
var path: Path!
|
||||
try Path.mktemp {
|
||||
|
||||
@@ -10,6 +10,7 @@ extension PathTests {
|
||||
("testEnumeration", testEnumeration),
|
||||
("testEnumerationSkippingHiddenFiles", testEnumerationSkippingHiddenFiles),
|
||||
("testExists", testExists),
|
||||
("testExtension", testExtension),
|
||||
("testIsDirectory", testIsDirectory),
|
||||
("testJoin", testJoin),
|
||||
("testMkpathIfExists", testMkpathIfExists),
|
||||
|
||||
Reference in New Issue
Block a user