Compare commits

...

6 Commits

Author SHA1 Message Date
Max Howell
c432f710eb Merge pull request #22 from mxcl/files()
Entry.files defaults to all files
2019-01-28 12:17:08 -05:00
Max Howell
19c0c19bb6 Entry.files defaults to all files 2019-01-28 12:04:47 -05:00
Max Howell
ee1f46954c Fixes #20
[skip ci]
2019-01-28 11:05:51 -05:00
Max Howell
2394cc1c85 Merge pull request #19 from JaapWijnen/filehandle-extensions
added extension to initialize filehandle from path
2019-01-27 16:59:44 -05:00
Jaap Wijnen
50bb319619 added extension to initialize filehandle from path 2019-01-27 22:57:19 +01:00
Max Howell
9f40068833 Badge for Swift 5 support 2019-01-26 16:15:45 -05:00
6 changed files with 68 additions and 15 deletions

View File

@@ -33,7 +33,7 @@ print(foo) // => /bar/foo
print(foo.isFile) // => true print(foo.isFile) // => true
// we support dynamic members (_use_sparingly_): // 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 // a practical example: installing a helper executable
try Bundle.resources.join("helper").copy(into: Path.home.join(".local/bin").mkdir(.p)).chmod(0o500) 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 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. does not use it. Usually you are joining variables or other `String` arguments
However when you need it, its *lovely*. or trying to describe files (and files usually have extensions). However when
you need it, its *lovely*.
## Initializing from user-input ## 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") 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: CocoaPods:
```ruby ```ruby
pod 'Path.swift' ~> '0.5.0' pod 'Path.swift', '~> 0.5'
``` ```
Carthage: 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-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 [online API documentation]: https://mxcl.github.io/Path.swift/Structs/Path.html

View File

@@ -86,3 +86,24 @@ public extension Data {
return to 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)
}
}

View File

@@ -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] { func files(withExtension ext: String) -> [Path] {
return compactMap { return compactMap {
$0.kind == .file && $0.path.extension == ext ? $0.path : nil $0.kind == .file && $0.path.extension == ext ? $0.path : nil

View File

@@ -36,7 +36,7 @@ public struct Path: Equatable, Hashable, Comparable {
self.string = string self.string = string
} }
/// Returns `nil` unless fed an absolute path /// Returns `nil` unless fed an absolute path.
public init?(_ description: String) { public init?(_ description: String) {
guard description.starts(with: "/") || description.starts(with: "~/") else { return nil } guard description.starts(with: "/") || description.starts(with: "~/") else { return nil }
self.init(string: (description as NSString).standardizingPath) self.init(string: (description as NSString).standardizingPath)
@@ -73,11 +73,16 @@ public struct Path: Equatable, Hashable, Comparable {
/** /**
Returns the filename extension of this path. Returns the filename extension of this path.
- Remark: Implemented via `NSString.pathExtension`. - Remark: Implemented via `NSString.pathExtension`.
- Note: We special case eg. `foo.tar.gz`.
*/ */
@inlinable @inlinable
public var `extension`: String { public var `extension`: String {
if string.hasSuffix(".tar.gz") {
return "tar.gz"
} else {
return (string as NSString).pathExtension return (string as NSString).pathExtension
} }
}
//MARK: Pathing //MARK: Pathing
@@ -91,7 +96,7 @@ public struct Path: Equatable, Hashable, Comparable {
- Parameter pathComponent: The string to join with this path. - Parameter pathComponent: The string to join with this path.
- Returns: A new joined path. - Returns: A new joined path.
- SeeAlso: `Path./(_:, _:)` - SeeAlso: `Path./(_:_:)`
*/ */
public func join<S>(_ pathComponent: S) -> Path where S: StringProtocol { public func join<S>(_ pathComponent: S) -> Path where S: StringProtocol {
//TODO standardizingPath does more than we want really (eg tilde expansion) //TODO standardizingPath does more than we want really (eg tilde expansion)

View File

@@ -15,20 +15,26 @@ class PathTests: XCTestCase {
let tmpdir_ = try TemporaryDirectory() let tmpdir_ = try TemporaryDirectory()
let tmpdir = tmpdir_.path let tmpdir = tmpdir_.path
try tmpdir.a.mkdir().c.touch() try tmpdir.a.mkdir().c.touch()
try tmpdir.b.touch() try tmpdir.join("b.swift").touch()
try tmpdir.c.touch() try tmpdir.c.touch()
try tmpdir.join(".d").mkdir().e.touch() try tmpdir.join(".d").mkdir().e.touch()
var paths = Set<String>() var paths = Set<String>()
let lsrv = try tmpdir.ls()
var dirs = 0 var dirs = 0
for entry in try tmpdir.ls() { for entry in lsrv {
if entry.kind == .directory { if entry.kind == .directory {
dirs += 1 dirs += 1
} }
paths.insert(entry.path.basename()) paths.insert(entry.path.basename())
} }
XCTAssertEqual(dirs, 2) 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) 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 { func testMktemp() throws {
var path: Path! var path: Path!
try Path.mktemp { try Path.mktemp {

View File

@@ -10,6 +10,7 @@ extension PathTests {
("testEnumeration", testEnumeration), ("testEnumeration", testEnumeration),
("testEnumerationSkippingHiddenFiles", testEnumerationSkippingHiddenFiles), ("testEnumerationSkippingHiddenFiles", testEnumerationSkippingHiddenFiles),
("testExists", testExists), ("testExists", testExists),
("testExtension", testExtension),
("testIsDirectory", testIsDirectory), ("testIsDirectory", testIsDirectory),
("testJoin", testJoin), ("testJoin", testJoin),
("testMkpathIfExists", testMkpathIfExists), ("testMkpathIfExists", testMkpathIfExists),