mirror of
https://github.com/samsonjs/FileOtter.git
synced 2026-04-27 14:57:41 +00:00
WIP
This commit is contained in:
parent
8227e5ee7b
commit
c74842ef76
4 changed files with 180 additions and 0 deletions
|
|
@ -11,6 +11,9 @@
|
||||||
7B5064BF2BD9F236009CEFF9 /* FileOtter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B5064B42BD9F236009CEFF9 /* FileOtter.framework */; };
|
7B5064BF2BD9F236009CEFF9 /* FileOtter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B5064B42BD9F236009CEFF9 /* FileOtter.framework */; };
|
||||||
7B5064C42BD9F236009CEFF9 /* FileOtterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5064C32BD9F236009CEFF9 /* FileOtterTests.swift */; };
|
7B5064C42BD9F236009CEFF9 /* FileOtterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5064C32BD9F236009CEFF9 /* FileOtterTests.swift */; };
|
||||||
7B5064C52BD9F236009CEFF9 /* FileOtter.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B5064B72BD9F236009CEFF9 /* FileOtter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
7B5064C52BD9F236009CEFF9 /* FileOtter.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B5064B72BD9F236009CEFF9 /* FileOtter.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
7B5064CF2BD9F2C0009CEFF9 /* Readme.md in Resources */ = {isa = PBXBuildFile; fileRef = 7B5064CE2BD9F2C0009CEFF9 /* Readme.md */; };
|
||||||
|
7B5064D12BD9F322009CEFF9 /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5064D02BD9F322009CEFF9 /* File.swift */; };
|
||||||
|
7B5064D32BD9F339009CEFF9 /* Dir.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5064D22BD9F339009CEFF9 /* Dir.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
|
@ -29,6 +32,9 @@
|
||||||
7B5064B82BD9F236009CEFF9 /* FileOtter.docc */ = {isa = PBXFileReference; lastKnownFileType = folder.documentationcatalog; path = FileOtter.docc; sourceTree = "<group>"; };
|
7B5064B82BD9F236009CEFF9 /* FileOtter.docc */ = {isa = PBXFileReference; lastKnownFileType = folder.documentationcatalog; path = FileOtter.docc; sourceTree = "<group>"; };
|
||||||
7B5064BE2BD9F236009CEFF9 /* FileOtterTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FileOtterTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
7B5064BE2BD9F236009CEFF9 /* FileOtterTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FileOtterTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
7B5064C32BD9F236009CEFF9 /* FileOtterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileOtterTests.swift; sourceTree = "<group>"; };
|
7B5064C32BD9F236009CEFF9 /* FileOtterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileOtterTests.swift; sourceTree = "<group>"; };
|
||||||
|
7B5064CE2BD9F2C0009CEFF9 /* Readme.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Readme.md; sourceTree = "<group>"; };
|
||||||
|
7B5064D02BD9F322009CEFF9 /* File.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = File.swift; sourceTree = "<group>"; };
|
||||||
|
7B5064D22BD9F339009CEFF9 /* Dir.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dir.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
|
@ -53,6 +59,7 @@
|
||||||
7B5064AA2BD9F235009CEFF9 = {
|
7B5064AA2BD9F235009CEFF9 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
7B5064CE2BD9F2C0009CEFF9 /* Readme.md */,
|
||||||
7B5064B62BD9F236009CEFF9 /* FileOtter */,
|
7B5064B62BD9F236009CEFF9 /* FileOtter */,
|
||||||
7B5064C22BD9F236009CEFF9 /* FileOtterTests */,
|
7B5064C22BD9F236009CEFF9 /* FileOtterTests */,
|
||||||
7B5064B52BD9F236009CEFF9 /* Products */,
|
7B5064B52BD9F236009CEFF9 /* Products */,
|
||||||
|
|
@ -73,6 +80,8 @@
|
||||||
children = (
|
children = (
|
||||||
7B5064B72BD9F236009CEFF9 /* FileOtter.h */,
|
7B5064B72BD9F236009CEFF9 /* FileOtter.h */,
|
||||||
7B5064B82BD9F236009CEFF9 /* FileOtter.docc */,
|
7B5064B82BD9F236009CEFF9 /* FileOtter.docc */,
|
||||||
|
7B5064D02BD9F322009CEFF9 /* File.swift */,
|
||||||
|
7B5064D22BD9F339009CEFF9 /* Dir.swift */,
|
||||||
);
|
);
|
||||||
path = FileOtter;
|
path = FileOtter;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -177,6 +186,7 @@
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
7B5064CF2BD9F2C0009CEFF9 /* Readme.md in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -195,6 +205,8 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
7B5064B92BD9F236009CEFF9 /* FileOtter.docc in Sources */,
|
7B5064B92BD9F236009CEFF9 /* FileOtter.docc in Sources */,
|
||||||
|
7B5064D12BD9F322009CEFF9 /* File.swift in Sources */,
|
||||||
|
7B5064D32BD9F339009CEFF9 /* Dir.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -423,6 +435,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = X45WPY5JFZ;
|
DEVELOPMENT_TEAM = X45WPY5JFZ;
|
||||||
|
|
@ -444,6 +457,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
||||||
|
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = X45WPY5JFZ;
|
DEVELOPMENT_TEAM = X45WPY5JFZ;
|
||||||
|
|
|
||||||
150
FileOtter/Dir.swift
Normal file
150
FileOtter/Dir.swift
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
//
|
||||||
|
// Dir.swift
|
||||||
|
// FileOtter
|
||||||
|
//
|
||||||
|
// Created by Sami Samhuri on 2024-04-24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct Dir: Equatable, Hashable, RandomAccessCollection {
|
||||||
|
public let startIndex: Int
|
||||||
|
|
||||||
|
public let endIndex: Int
|
||||||
|
|
||||||
|
public let url: URL
|
||||||
|
|
||||||
|
public init(url: URL) throws {
|
||||||
|
self.init(url: url, children: try Dir.children(url))
|
||||||
|
}
|
||||||
|
|
||||||
|
private let children: [URL]
|
||||||
|
|
||||||
|
private init(url: URL, children: [URL]) {
|
||||||
|
self.url = url
|
||||||
|
self.children = children
|
||||||
|
startIndex = children.startIndex
|
||||||
|
endIndex = children.endIndex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Well-known Directories
|
||||||
|
extension Dir {
|
||||||
|
public static var caches: URL {
|
||||||
|
URL.cachesDirectory
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var current: URL {
|
||||||
|
URL.currentDirectory()
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var documents: URL {
|
||||||
|
URL.documentsDirectory
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var home: URL {
|
||||||
|
URL.homeDirectory
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var library: URL {
|
||||||
|
URL.libraryDirectory
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var pwd: URL {
|
||||||
|
.currentDirectory()
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var getwd: URL {
|
||||||
|
.currentDirectory()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Mutations
|
||||||
|
extension Dir {
|
||||||
|
@discardableResult
|
||||||
|
public static func chdir(_ url: URL) -> Bool {
|
||||||
|
FileManager.default.changeCurrentDirectoryPath(url.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
public static func chdir<T>(_ url: URL, block: (URL) -> T) -> T {
|
||||||
|
let previousDir = pwd
|
||||||
|
FileManager.default.changeCurrentDirectoryPath(url.path)
|
||||||
|
defer {
|
||||||
|
FileManager.default.changeCurrentDirectoryPath(previousDir.path)
|
||||||
|
}
|
||||||
|
return block(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
public static func unlink(_ url: URL) -> Bool {
|
||||||
|
do {
|
||||||
|
try FileManager.default.removeItem(at: url)
|
||||||
|
return true
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
public static func rmdir(_ url: URL) -> Bool {
|
||||||
|
unlink(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
@discardableResult
|
||||||
|
public static func delete(_ url: URL) -> Bool {
|
||||||
|
unlink(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Reading Contents
|
||||||
|
extension Dir {
|
||||||
|
public static func children(_ url: URL) throws -> [URL] {
|
||||||
|
try FileManager.default
|
||||||
|
.contentsOfDirectory(at: url, includingPropertiesForKeys: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func entries(_ url: URL) throws -> [String] {
|
||||||
|
#warning("TODO: implement this ... maybe, it's dumb")
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func exists(_ url: URL) throws -> Bool {
|
||||||
|
var isDirectory: ObjCBool = false
|
||||||
|
let exists = FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory)
|
||||||
|
return exists && isDirectory.boolValue
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func isEmpty(_ url: URL) throws -> Bool {
|
||||||
|
try FileManager.default
|
||||||
|
.contentsOfDirectory(at: url, includingPropertiesForKeys: nil)
|
||||||
|
.isEmpty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Globbing
|
||||||
|
extension Dir {
|
||||||
|
public static func glob(base: URL? = nil, _ patterns: String...) -> [URL] {
|
||||||
|
_glob(base: base, patterns: patterns)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static subscript(base: URL? = nil, _ patterns: String...) -> [URL] {
|
||||||
|
_glob(base: base, patterns: patterns)
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func _glob(base: URL?, patterns: [String]) -> [URL] {
|
||||||
|
#warning("TODO: implement me")
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - RandomAccessCollection
|
||||||
|
extension Dir {
|
||||||
|
public func makeIterator() -> any IteratorProtocol<URL> {
|
||||||
|
children.makeIterator()
|
||||||
|
}
|
||||||
|
|
||||||
|
public subscript(position: Int) -> URL {
|
||||||
|
children[position]
|
||||||
|
}
|
||||||
|
}
|
||||||
10
FileOtter/File.swift
Normal file
10
FileOtter/File.swift
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
//
|
||||||
|
// File.swift
|
||||||
|
// FileOtter
|
||||||
|
//
|
||||||
|
// Created by Sami Samhuri on 2024-04-24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct File {}
|
||||||
6
Readme.md
Normal file
6
Readme.md
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
# FileOtter
|
||||||
|
|
||||||
|
A sleek way to interact with the filesystem in Swift. Heavily inspired by Ruby's `[Dir][]` and `[File][]` classes from the standard library.
|
||||||
|
|
||||||
|
[Dir]: https://docs.ruby-lang.org/en/3.3/Dir.html
|
||||||
|
[File]: https://docs.ruby-lang.org/en/3.3/File.html
|
||||||
Loading…
Reference in a new issue