Dynamic Members

This commit is contained in:
Max Howell
2019-01-22 14:05:33 -05:00
parent 44be1c45a9
commit 859164e59f
5 changed files with 41 additions and 5 deletions

View File

@@ -89,11 +89,18 @@ jobs:
- name: CocoaPods
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
Pod::Spec.new do |s|
s.name = 'Path.swift'
s.version = 'TRAVIS_TAG'
s.summary = 'Delightful, robust file-pathing functions'
s.summary = 'DESCRIPTION'
s.homepage = 'https://github.com/mxcl/Path.swift'
s.license = { :type => 'Unlicense', :file => 'LICENSE.md' }
s.author = { 'mxcl' => 'mxcl@me.com' }
@@ -108,6 +115,7 @@ jobs:
end
EOF
sed -i '' "s/TRAVIS_TAG/$TRAVIS_TAG/" Path.swift.podspec
sed -i '' "s/DESCRIPTION/$DESCRIPTION/" Path.swift.podspec
# ^^ see the Jazzy deployment for explanation
install: gem install cocoapods --pre
script: pod trunk push

View File

@@ -94,6 +94,18 @@ decoder.userInfo[.relativePath] = Path.home
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, its *lovely*.
## Initializing from user-input
The `Path` initializer returns `nil` unless fed an absolute path; thus to

View File

@@ -23,6 +23,8 @@ import Foundation
- Note: There may not be an actual filesystem entry at the path. The underlying
representation for `Path` is `String`.
*/
@dynamicMemberLookup
public struct Path: Equatable, Hashable, Comparable {
init(string: String) {
@@ -45,6 +47,12 @@ public struct Path: Equatable, Hashable, Comparable {
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.

View File

@@ -14,10 +14,10 @@ class PathTests: XCTestCase {
func testEnumeration() throws {
let tmpdir_ = try TemporaryDirectory()
let tmpdir = tmpdir_.path
try tmpdir.join("a").mkdir().join("c").touch()
try tmpdir.join("b").touch()
try tmpdir.join("c").touch()
try tmpdir.join(".d").mkdir().join("e").touch()
try tmpdir.a.mkdir().c.touch()
try tmpdir.b.touch()
try tmpdir.c.touch()
try tmpdir.join(".d").mkdir().e.touch()
var paths = Set<String>()
var dirs = 0
@@ -139,6 +139,13 @@ class PathTests: XCTestCase {
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 {
try Path.mktemp { root in
let bar = try root.join("bar").touch()

View File

@@ -6,6 +6,7 @@ extension PathTests {
("testCodable", testCodable),
("testConcatenation", testConcatenation),
("testCopyInto", testCopyInto),
("testDynamicMember", testDynamicMember),
("testEnumeration", testEnumeration),
("testEnumerationSkippingHiddenFiles", testEnumerationSkippingHiddenFiles),
("testExists", testExists),