Dynamic Members
This commit is contained in:
10
.travis.yml
10
.travis.yml
@@ -89,11 +89,18 @@ jobs:
|
|||||||
|
|
||||||
- name: CocoaPods
|
- name: CocoaPods
|
||||||
before_install: |
|
before_install: |
|
||||||
|
DESCRIPTION=$(swift - <<EOF
|
||||||
|
import Foundation
|
||||||
|
struct Response: Decodable { let description: String }
|
||||||
|
let url = URL(string: "https://api.github.com/repos/mxcl/Path.swift")!
|
||||||
|
let data = try Data(contentsOf: url)
|
||||||
|
print(try JSONDecoder().decode(Response.self, from: data).description)
|
||||||
|
EOF)
|
||||||
cat <<\ \ EOF> Path.swift.podspec
|
cat <<\ \ EOF> Path.swift.podspec
|
||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = 'Path.swift'
|
s.name = 'Path.swift'
|
||||||
s.version = 'TRAVIS_TAG'
|
s.version = 'TRAVIS_TAG'
|
||||||
s.summary = 'Delightful, robust file-pathing functions'
|
s.summary = 'DESCRIPTION'
|
||||||
s.homepage = 'https://github.com/mxcl/Path.swift'
|
s.homepage = 'https://github.com/mxcl/Path.swift'
|
||||||
s.license = { :type => 'Unlicense', :file => 'LICENSE.md' }
|
s.license = { :type => 'Unlicense', :file => 'LICENSE.md' }
|
||||||
s.author = { 'mxcl' => 'mxcl@me.com' }
|
s.author = { 'mxcl' => 'mxcl@me.com' }
|
||||||
@@ -108,6 +115,7 @@ jobs:
|
|||||||
end
|
end
|
||||||
EOF
|
EOF
|
||||||
sed -i '' "s/TRAVIS_TAG/$TRAVIS_TAG/" Path.swift.podspec
|
sed -i '' "s/TRAVIS_TAG/$TRAVIS_TAG/" Path.swift.podspec
|
||||||
|
sed -i '' "s/DESCRIPTION/$DESCRIPTION/" Path.swift.podspec
|
||||||
# ^^ see the Jazzy deployment for explanation
|
# ^^ see the Jazzy deployment for explanation
|
||||||
install: gem install cocoapods --pre
|
install: gem install cocoapods --pre
|
||||||
script: pod trunk push
|
script: pod trunk push
|
||||||
|
|||||||
12
README.md
12
README.md
@@ -94,6 +94,18 @@ decoder.userInfo[.relativePath] = Path.home
|
|||||||
decoder.decode(from: data)
|
decoder.decode(from: data)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Dynamic members
|
||||||
|
|
||||||
|
We support `@dynamicMemberLookup`:
|
||||||
|
|
||||||
|
```swift
|
||||||
|
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*.
|
||||||
|
|
||||||
## Initializing from user-input
|
## Initializing from user-input
|
||||||
|
|
||||||
The `Path` initializer returns `nil` unless fed an absolute path; thus to
|
The `Path` initializer returns `nil` unless fed an absolute path; thus to
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import Foundation
|
|||||||
- Note: There may not be an actual filesystem entry at the path. The underlying
|
- Note: There may not be an actual filesystem entry at the path. The underlying
|
||||||
representation for `Path` is `String`.
|
representation for `Path` is `String`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@dynamicMemberLookup
|
||||||
public struct Path: Equatable, Hashable, Comparable {
|
public struct Path: Equatable, Hashable, Comparable {
|
||||||
|
|
||||||
init(string: String) {
|
init(string: String) {
|
||||||
@@ -45,6 +47,12 @@ public struct Path: Equatable, Hashable, Comparable {
|
|||||||
return URL(fileURLWithPath: string)
|
return URL(fileURLWithPath: string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Facilitates constructing paths for static strings
|
||||||
|
public subscript(dynamicMember pathComponent: String) -> Path {
|
||||||
|
let str = (string as NSString).appendingPathComponent(pathComponent)
|
||||||
|
return Path(string: str)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the parent directory for this path.
|
Returns the parent directory for this path.
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ class PathTests: XCTestCase {
|
|||||||
func testEnumeration() throws {
|
func testEnumeration() throws {
|
||||||
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.a.mkdir().c.touch()
|
||||||
try tmpdir.join("b").touch()
|
try tmpdir.b.touch()
|
||||||
try tmpdir.join("c").touch()
|
try tmpdir.c.touch()
|
||||||
try tmpdir.join(".d").mkdir().join("e").touch()
|
try tmpdir.join(".d").mkdir().e.touch()
|
||||||
|
|
||||||
var paths = Set<String>()
|
var paths = Set<String>()
|
||||||
var dirs = 0
|
var dirs = 0
|
||||||
@@ -139,6 +139,13 @@ class PathTests: XCTestCase {
|
|||||||
XCTAssertEqual(Path.root/"a/foo"/"../../../bar", Path.root/"bar")
|
XCTAssertEqual(Path.root/"a/foo"/"../../../bar", Path.root/"bar")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testDynamicMember() {
|
||||||
|
XCTAssertEqual(Path.root.Documents, Path.root/"Documents")
|
||||||
|
|
||||||
|
let a = Path.home.foo
|
||||||
|
XCTAssertEqual(a.Documents, Path.home/"foo/Documents")
|
||||||
|
}
|
||||||
|
|
||||||
func testCopyInto() throws {
|
func testCopyInto() throws {
|
||||||
try Path.mktemp { root in
|
try Path.mktemp { root in
|
||||||
let bar = try root.join("bar").touch()
|
let bar = try root.join("bar").touch()
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ extension PathTests {
|
|||||||
("testCodable", testCodable),
|
("testCodable", testCodable),
|
||||||
("testConcatenation", testConcatenation),
|
("testConcatenation", testConcatenation),
|
||||||
("testCopyInto", testCopyInto),
|
("testCopyInto", testCopyInto),
|
||||||
|
("testDynamicMember", testDynamicMember),
|
||||||
("testEnumeration", testEnumeration),
|
("testEnumeration", testEnumeration),
|
||||||
("testEnumerationSkippingHiddenFiles", testEnumerationSkippingHiddenFiles),
|
("testEnumerationSkippingHiddenFiles", testEnumerationSkippingHiddenFiles),
|
||||||
("testExists", testExists),
|
("testExists", testExists),
|
||||||
|
|||||||
Reference in New Issue
Block a user