|
| 1 | +# Path.swift |
| 2 | + |
| 3 | +A file-system pathing library focused on developer experience and robust |
| 4 | +end‐results. |
| 5 | + |
| 6 | +```swift |
| 7 | +// convenient static members |
| 8 | +let home = Path.home |
| 9 | + |
| 10 | +// pleasant joining syntax |
| 11 | +let docs = Path.home/"Documents" |
| 12 | + |
| 13 | +// paths are *always* absolute thus avoiding common bugs |
| 14 | +let path = Path(userInput) ?? Path.cwd/userInput |
| 15 | + |
| 16 | +// chainable syntax so you have less boilerplate |
| 17 | +try Path.home.join("foo").mkpath().join("bar").chmod(0o555) |
| 18 | + |
| 19 | +// easy file-management |
| 20 | +try Path.root.join("foo").copy(to: Path.root.join("bar")) |
| 21 | + |
| 22 | +// careful API to avoid common bugs |
| 23 | +try Path.root.join("foo").copy(into: Path.root.mkdir("bar")) |
| 24 | +// ^^ other libraries would make the `to:` form handle both these cases |
| 25 | +// but that can easily lead to bugs where you accidentally write files that |
| 26 | +// were meant to be directory destinations |
| 27 | +``` |
| 28 | + |
| 29 | +Paths are just string representations, there *may not* be a real file there. |
| 30 | + |
| 31 | +# Support mxcl |
| 32 | + |
| 33 | +Hi, I’m Max Howell and I have written a lot of open source software, and |
| 34 | +probably you already use some of it (Homebrew anyone?). Please help me so I |
| 35 | +can continue to make tools and software you need and love. I appreciate it x. |
| 36 | + |
| 37 | +<a href="https://www.patreon.com/mxcl"> |
| 38 | + <img src="https://c5.patreon.com/external/logo/[email protected]" width="160"> |
| 39 | +</a> |
| 40 | + |
| 41 | +## Codable |
| 42 | + |
| 43 | +We support `Codable` as you would expect: |
| 44 | + |
| 45 | +```swift |
| 46 | +try JSONEncoder().encode([Path.home, Path.home/"foo"]) |
| 47 | +``` |
| 48 | + |
| 49 | +```json |
| 50 | +[ |
| 51 | + "/Users/mxcl", |
| 52 | + "/Users/mxcl/foo", |
| 53 | +] |
| 54 | +``` |
| 55 | + |
| 56 | +However, often you want to encode relative paths: |
| 57 | + |
| 58 | +```swift |
| 59 | +let encoder = JSONEncoder() |
| 60 | +encoder.userInfo[.relativePath] = Path.home |
| 61 | +encoder.encode([Path.home, Path.home/"foo"]) |
| 62 | +``` |
| 63 | + |
| 64 | +```json |
| 65 | +[ |
| 66 | + "", |
| 67 | + "foo", |
| 68 | +] |
| 69 | +``` |
| 70 | + |
| 71 | +**Note** make sure you decode with this key set *also*, otherwise we `fatal` |
| 72 | +(unless the paths are absolute obv.) |
| 73 | + |
| 74 | +```swift |
| 75 | +let decoder = JSONDecoder() |
| 76 | +decoder.userInfo[.relativePath] = Path.home |
| 77 | +decoder.decode(from: data) |
| 78 | +``` |
| 79 | + |
| 80 | +## Initializing from user-input |
| 81 | + |
| 82 | +The `Path` initializer returns `nil` unless fed an absolute path; thus to |
| 83 | +initialize from user-input that may contain a relative path use this form: |
| 84 | + |
| 85 | +```swift |
| 86 | +let path = Path(userInput) ?? Path.cwd/userInput |
| 87 | +``` |
| 88 | + |
| 89 | +This is explicit, not hiding anything that code-review may miss and preventing |
| 90 | +common bugs like accidentally creating `Path` objects from strings you did not |
| 91 | +expect to be relative. |
| 92 | + |
| 93 | +## Extensions |
| 94 | + |
| 95 | +We have some extensions to Apple APIs: |
| 96 | + |
| 97 | +```swift |
| 98 | +let bashProfile = try String(contentsOf: Path.home/".bash_profile") |
| 99 | +let history = try Data(contentsOf: Path.home/".history") |
| 100 | + |
| 101 | +bashProfile += "\n\nfoo" |
| 102 | + |
| 103 | +try bashProfile.write(to: Path.home/".bash_profile") |
| 104 | + |
| 105 | +try Bundle.main.resources!.join("foo").copy(to: .home) |
| 106 | +// ^^ `-> Path?` because the underlying `Bundle` function is `-> String?` |
| 107 | +``` |
| 108 | + |
| 109 | +## Directory listings |
| 110 | + |
| 111 | +We provide `ls()`, called because it behaves like the Terminal `ls` function, |
| 112 | +the name thus implies its behavior, ie. that it is not recursive. |
| 113 | + |
| 114 | +```swift |
| 115 | +for path in Path.home.ls() { |
| 116 | + print(path.path) |
| 117 | + print(path.kind) // .directory or .file |
| 118 | +} |
| 119 | + |
| 120 | +for path in Path.home.ls() where path.kind == .file { |
| 121 | + //… |
| 122 | +} |
| 123 | + |
| 124 | +for path in Path.home.ls() where path.mtime > yesterday { |
| 125 | + //… |
| 126 | +} |
| 127 | + |
| 128 | +let dirs = Path.home.ls().directories().filter { |
| 129 | + //… |
| 130 | +} |
| 131 | + |
| 132 | +let swiftFiles = Path.home.ls().files(withExtension: "swift") |
| 133 | +``` |
| 134 | + |
| 135 | +# Installation |
| 136 | + |
| 137 | +SwiftPM only: |
| 138 | + |
| 139 | +```swift |
| 140 | +package.append(.package(url: "https://github.com/mxcl/Path.swift", from: "0.0.0")) |
| 141 | +``` |
| 142 | + |
| 143 | +### Get push notifications for new releases |
| 144 | + |
| 145 | +https://codebasesaga.com/canopy/ |
0 commit comments