diff --git a/.gitignore b/.gitignore index efb0e2f..f129058 100644 --- a/.gitignore +++ b/.gitignore @@ -1,144 +1,9 @@ - -# ---> Objective-C -======= - -# Created by https://www.gitignore.io/api/xcode,swift,macos,cocoapods -# Edit at https://www.gitignore.io/?templates=xcode,swift,macos,cocoapods - -### CocoaPods ### -## CocoaPods GitIgnore Template - -# CocoaPods - Only use to conserve bandwidth / Save time on Pushing -# - Also handy if you have a large number of dependant pods -# - AS PER https://guides.cocoapods.org/using/using-cocoapods.html NEVER IGNORE THE LOCK FILE -Pods/ -Podfile.lock - -### macOS ### -# General .DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -### Swift ### ->>>>>>> 6473ef460d0d87bb717651119157caf8ecbdf4a9 -# Xcode -# -# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore - -## Build generated -build/ -DerivedData/ - -## Various settings -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 +/.build +/Packages xcuserdata/ - -## Other -*.moved-aside -*.xccheckout -*.xcscmblueprint -*.xcuserstate - -## Obj-C/Swift specific -*.hmap -*.ipa -*.dSYM.zip -*.dSYM - -## Playgrounds -timeline.xctimeline -playground.xcworkspace - -# Swift Package Manager -# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. -# Packages/ -# Package.pins -# Package.resolved -.build/ - -# CocoaPods -# We recommend against adding the Pods directory to your .gitignore. However -# you should judge for yourself, the pros and cons are mentioned at: -# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control -# Pods/ -# Add this line if you want to avoid checking in source code from the Xcode workspace -# *.xcworkspace - -# Carthage -# Add this line if you want to avoid checking in source code from Carthage dependencies. -# Carthage/Checkouts - -Carthage/Build - -# Accio dependency management -Dependencies/ -.accio/ - -# fastlane -# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the -# screenshots whenever they are needed. -# For more information about the recommended setup visit: -# https://docs.fastlane.tools/best-practices/source-control/#source-control - -fastlane/report.xml -fastlane/Preview.html -fastlane/screenshots/**/*.png -fastlane/test_output - -# Code Injection -# After new code Injection tools there's a generated folder /iOSInjectionProject -# https://github.com/johnno1962/injectionforxcode - -iOSInjectionProject/ - -### Xcode ### -# Xcode -# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore - -## User settings - -## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) - -## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) - -## Xcode Patch -*.xcodeproj/* -!*.xcodeproj/project.pbxproj -!*.xcodeproj/xcshareddata/ -!*.xcworkspace/contents.xcworkspacedata -/*.gcno - -### Xcode Patch ### -**/xcshareddata/WorkspaceSettings.xcsettings - -# End of https://www.gitignore.io/api/xcode,swift,macos,cocoapods \ No newline at end of file +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc +Package.resolved \ No newline at end of file diff --git a/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/SFSymbolsGenerator.xcodeproj/xcshareddata/xcschemes/SFSymbolsGenerator.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/SFSymbolsGenerator.xcscheme similarity index 83% rename from SFSymbolsGenerator.xcodeproj/xcshareddata/xcschemes/SFSymbolsGenerator.xcscheme rename to .swiftpm/xcode/xcshareddata/xcschemes/SFSymbolsGenerator.xcscheme index c1af476..9c9973d 100644 --- a/SFSymbolsGenerator.xcodeproj/xcshareddata/xcschemes/SFSymbolsGenerator.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/SFSymbolsGenerator.xcscheme @@ -14,10 +14,10 @@ buildForAnalyzing = "YES"> + ReferencedContainer = "container:"> @@ -38,16 +38,15 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" - allowLocationSimulation = "YES" - viewDebuggingEnabled = "No"> + allowLocationSimulation = "YES"> + ReferencedContainer = "container:"> @@ -61,10 +60,10 @@ runnableDebuggingMode = "0"> + ReferencedContainer = "container:"> diff --git a/Assets/Command Usage.png b/Assets/Command Usage.png new file mode 100644 index 0000000..7e936e7 Binary files /dev/null and b/Assets/Command Usage.png differ diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..2ef0e7a --- /dev/null +++ b/Package.swift @@ -0,0 +1,22 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "SFSymbolsGenerator", + platforms: [.macOS(.v13)], + dependencies: [ + .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.2.0"), + ], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + .executableTarget( + name: "SFSymbolsGenerator", + dependencies: [ + .product(name: "ArgumentParser", package: "swift-argument-parser"), + ] + ), + ] +) diff --git a/README.md b/README.md index dae639a..40c70f3 100644 --- a/README.md +++ b/README.md @@ -12,29 +12,41 @@ Simplifying SF Symbols Enumeration Generation with Swift! ## How to Use -### git clone - -1. Clone this Project -2. Use Xcode to open it -3. Command + R -4. Find outputPath in Output area, and Happy use it! - -### Terminal +![Command Usage](./Assets/Command Usage.png) 1. Download binary file from Latest Releases 2. Open Terminal.app (notes: check current path exists SFSymbolsGenerator binary file!) -3. run ```./SFSymbolsGenerator```, and find outputPath in Terminal, and Happy use it! +3. run ```./SFSymbolsGenerator ```, and Happy use it! + +#### Argument + +| Argument | Description | Required or Optional | +|------------|-----------------------------| :------------------: | +| filepath | Specify filepath of output. | **Required** | -#### Arguments +#### Flag -| Argument | Description | -|------------|---------------------| -| --use-beta | Use SF Symbols beta | +| Argument | Description | Required or Optional | +|------------|-----------------------------| :------------------: | +| --name | Specify filename of output. | **Optional** | + +#### Flag + +| Argument | Description | Required or Optional | +|------------|---------------------| :------------------: | +| --use-beta | Use SF Symbols beta | **Optional** | ##### Example ```shell -./SFSymbolsGenerator --use-beta +# Normal Usage +./SFSymbolsGenerator /Users/leoho/Desktop + +# Specify filename Usage +./SFSymbolsGenerator /Users/leoho/Desktop --name SFSymbols + +# beta version Usage +./SFSymbolsGenerator /Users/leoho/Desktop --use-beta ``` ## Thanks diff --git a/SFSymbolsGenerator.xcodeproj/project.pbxproj b/SFSymbolsGenerator.xcodeproj/project.pbxproj deleted file mode 100644 index 56bce16..0000000 --- a/SFSymbolsGenerator.xcodeproj/project.pbxproj +++ /dev/null @@ -1,348 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 56; - objects = { - -/* Begin PBXBuildFile section */ - D01233C42AC9D89900E5892E /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01233C32AC9D89900E5892E /* main.swift */; }; - D01233CD2AC9D8F800E5892E /* Typealias.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01233CC2AC9D8F800E5892E /* Typealias.swift */; }; - D01233CF2AC9D91700E5892E /* Release+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01233CE2AC9D91700E5892E /* Release+Extensions.swift */; }; - D01233D12AC9D92400E5892E /* Symbol+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01233D02AC9D92400E5892E /* Symbol+Extensions.swift */; }; - D01233D42AC9DBA100E5892E /* OutputStreamCapture.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01233D32AC9DBA100E5892E /* OutputStreamCapture.swift */; }; - D01233D72AC9E0C200E5892E /* FileWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01233D62AC9E0C200E5892E /* FileWriter.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - D01233BE2AC9D89900E5892E /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - D01233C02AC9D89900E5892E /* SFSymbolsGenerator */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SFSymbolsGenerator; sourceTree = BUILT_PRODUCTS_DIR; }; - D01233C32AC9D89900E5892E /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; - D01233CC2AC9D8F800E5892E /* Typealias.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Typealias.swift; sourceTree = ""; }; - D01233CE2AC9D91700E5892E /* Release+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Release+Extensions.swift"; sourceTree = ""; }; - D01233D02AC9D92400E5892E /* Symbol+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Symbol+Extensions.swift"; sourceTree = ""; }; - D01233D32AC9DBA100E5892E /* OutputStreamCapture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutputStreamCapture.swift; sourceTree = ""; }; - D01233D62AC9E0C200E5892E /* FileWriter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileWriter.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - D01233BD2AC9D89900E5892E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - D01233B72AC9D89900E5892E = { - isa = PBXGroup; - children = ( - D01233C22AC9D89900E5892E /* SFSymbolsGenerator */, - D01233C12AC9D89900E5892E /* Products */, - ); - sourceTree = ""; - }; - D01233C12AC9D89900E5892E /* Products */ = { - isa = PBXGroup; - children = ( - D01233C02AC9D89900E5892E /* SFSymbolsGenerator */, - ); - name = Products; - sourceTree = ""; - }; - D01233C22AC9D89900E5892E /* SFSymbolsGenerator */ = { - isa = PBXGroup; - children = ( - D01233D52AC9E0AF00E5892E /* WriteFile */, - D01233D22AC9DB8800E5892E /* TextOutputStream */, - D01233CB2AC9D8C700E5892E /* Typealias */, - D01233CA2AC9D8AC00E5892E /* Extensions */, - D01233C32AC9D89900E5892E /* main.swift */, - ); - path = SFSymbolsGenerator; - sourceTree = ""; - }; - D01233CA2AC9D8AC00E5892E /* Extensions */ = { - isa = PBXGroup; - children = ( - D01233CE2AC9D91700E5892E /* Release+Extensions.swift */, - D01233D02AC9D92400E5892E /* Symbol+Extensions.swift */, - ); - path = Extensions; - sourceTree = ""; - }; - D01233CB2AC9D8C700E5892E /* Typealias */ = { - isa = PBXGroup; - children = ( - D01233CC2AC9D8F800E5892E /* Typealias.swift */, - ); - path = Typealias; - sourceTree = ""; - }; - D01233D22AC9DB8800E5892E /* TextOutputStream */ = { - isa = PBXGroup; - children = ( - D01233D32AC9DBA100E5892E /* OutputStreamCapture.swift */, - ); - path = TextOutputStream; - sourceTree = ""; - }; - D01233D52AC9E0AF00E5892E /* WriteFile */ = { - isa = PBXGroup; - children = ( - D01233D62AC9E0C200E5892E /* FileWriter.swift */, - ); - path = WriteFile; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - D01233BF2AC9D89900E5892E /* SFSymbolsGenerator */ = { - isa = PBXNativeTarget; - buildConfigurationList = D01233C72AC9D89900E5892E /* Build configuration list for PBXNativeTarget "SFSymbolsGenerator" */; - buildPhases = ( - D01233BC2AC9D89900E5892E /* Sources */, - D01233BD2AC9D89900E5892E /* Frameworks */, - D01233BE2AC9D89900E5892E /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = SFSymbolsGenerator; - productName = SFSymbolsGenerator; - productReference = D01233C02AC9D89900E5892E /* SFSymbolsGenerator */; - productType = "com.apple.product-type.tool"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - D01233B82AC9D89900E5892E /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1500; - LastUpgradeCheck = 1500; - TargetAttributes = { - D01233BF2AC9D89900E5892E = { - CreatedOnToolsVersion = 15.0; - }; - }; - }; - buildConfigurationList = D01233BB2AC9D89900E5892E /* Build configuration list for PBXProject "SFSymbolsGenerator" */; - compatibilityVersion = "Xcode 14.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = D01233B72AC9D89900E5892E; - productRefGroup = D01233C12AC9D89900E5892E /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - D01233BF2AC9D89900E5892E /* SFSymbolsGenerator */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - D01233BC2AC9D89900E5892E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D01233CF2AC9D91700E5892E /* Release+Extensions.swift in Sources */, - D01233D72AC9E0C200E5892E /* FileWriter.swift in Sources */, - D01233CD2AC9D8F800E5892E /* Typealias.swift in Sources */, - D01233D42AC9DBA100E5892E /* OutputStreamCapture.swift in Sources */, - D01233C42AC9D89900E5892E /* main.swift in Sources */, - D01233D12AC9D92400E5892E /* Symbol+Extensions.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - D01233C52AC9D89900E5892E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MACOSX_DEPLOYMENT_TARGET = 14.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - D01233C62AC9D89900E5892E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu17; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MACOSX_DEPLOYMENT_TARGET = 14.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - }; - name = Release; - }; - D01233C82AC9D89900E5892E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 23JEQ2524P; - ENABLE_HARDENED_RUNTIME = YES; - MACOSX_DEPLOYMENT_TARGET = 13.0; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - D01233C92AC9D89900E5892E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 23JEQ2524P; - ENABLE_HARDENED_RUNTIME = YES; - MACOSX_DEPLOYMENT_TARGET = 13.0; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - D01233BB2AC9D89900E5892E /* Build configuration list for PBXProject "SFSymbolsGenerator" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D01233C52AC9D89900E5892E /* Debug */, - D01233C62AC9D89900E5892E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - D01233C72AC9D89900E5892E /* Build configuration list for PBXNativeTarget "SFSymbolsGenerator" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D01233C82AC9D89900E5892E /* Debug */, - D01233C92AC9D89900E5892E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = D01233B82AC9D89900E5892E /* Project object */; -} diff --git a/SFSymbolsGenerator/WriteFile/FileWriter.swift b/SFSymbolsGenerator/WriteFile/FileWriter.swift deleted file mode 100644 index 6361536..0000000 --- a/SFSymbolsGenerator/WriteFile/FileWriter.swift +++ /dev/null @@ -1,43 +0,0 @@ -// -// FileWriter.swift -// SFSymbolsGenerator -// -// Created by Leo Ho on 2023/10/2. -// - -import Foundation - -class FileWriter: NSObject { - - private let outputPath: String = "SFSymbols+Enum.swift" - - func write(with data: String) { - do { - let fileManager = FileManager.default - - let currentDirectory = fileManager.currentDirectoryPath - print("當前目錄:", currentDirectory) - let url = URL(fileURLWithPath: currentDirectory + "/" + outputPath) - - // 判斷指定路徑下,檔案是否存在,不存在就新增一個 - if !fileManager.fileExists(atPath: outputPath) { - fileManager.createFile(atPath: outputPath, contents: nil) - } - - let fileHandle = try FileHandle(forWritingTo: url) - - // 將字串轉換為 Data - if let data = data.data(using: .utf8) { - // 開始寫檔 - fileHandle.write(data) - - // 關閉檔案 - fileHandle.closeFile() - - print("寫入成功:\(outputPath)") - } - } catch { - print("寫入失敗,錯誤:\(error)") - } - } -} diff --git a/SFSymbolsGenerator/main.swift b/SFSymbolsGenerator/main.swift deleted file mode 100644 index 07527f3..0000000 --- a/SFSymbolsGenerator/main.swift +++ /dev/null @@ -1,129 +0,0 @@ -// -// main.swift -// SFSymbolsGenerator -// -// Created by Leo Ho on 2023/10/2. -// - -import Foundation - -enum GenerateError: Error, CustomStringConvertible { - - case unknown(Error) - - case notInstallSFSymbols - - case notInstallSFSymbolsBeta - - case propertyList(Error) - - var description: String { - switch self { - case .unknown(let error): - "Unknown Error: \(error.localizedDescription)" - case .notInstallSFSymbols: - "SF Symbols.app is not installed yet! Please go to Apple Developer Website to download!" - case .notInstallSFSymbolsBeta: - "SF Symbols beta.app is not installed yet! Please go to Apple Developer Website to download!" - case .propertyList(let error): - "PropertyList Error: \(error.localizedDescription)" - } - } -} - -func readSymbolsAndYears(from fileURL: URL) throws -> ([SymbolTuple], Releases) { - do { - let data = try Data(contentsOf: fileURL, options: .mappedIfSafe) - do { - let propertyList = try PropertyListSerialization.propertyList(from: data, - options: [], - format: nil) as! Dictionary - - let symbols = propertyList["symbols"] as! Symbols - let releases = propertyList["year_to_release"] as! Releases - - let releaseDatesFromSymbols = Set(symbols.values) - let releaseDatesFromReleases = Set(releases.keys) - - assert(releaseDatesFromReleases.isSubset(of:releaseDatesFromSymbols), - "There are symbols with releasedates that have no release versions \(releaseDatesFromReleases) < \(releaseDatesFromSymbols)") - - let sortedSymbolTuple = symbols - .sorted { - $0.value == $1.value ? $0.key < $1.key : $0.value < $1.value - } - .map { - SymbolTuple(symbol: $0.key, released: $0.value) - } - - return (sortedSymbolTuple, releases) - } catch { - throw GenerateError.propertyList(error) - } - } catch { - if fileURL.path().contains("SF%20Symbols.app") { - throw GenerateError.notInstallSFSymbols - } else if fileURL.path().contains("SF%20Symbols%20beta.app") { - throw GenerateError.notInstallSFSymbolsBeta - } else { - throw GenerateError.unknown(error) - } - } -} - -do { - var appURL: URL! - for argc in CommandLine.arguments { - switch argc { - case "--use-beta": - appURL = URL(fileURLWithPath: "/Applications/SF Symbols beta.app/Contents/Resources/Metadata/name_availability.plist") - default: - appURL = URL(fileURLWithPath: "/Applications/SF Symbols.app/Contents/Resources/Metadata/name_availability.plist") - } - } - - let (sortedSymbolTuple, releaseYears) = try readSymbolsAndYears(from: appURL) - - let outputStream = OutputStreamCapture() - - outputStream.capturePrint( -""" -import Foundation - -public enum SFSymbols: String, CaseIterable {\n -""" - ) - - for symbolTuple in sortedSymbolTuple { - outputStream.capturePrint(" " + "/// SF Symbols's name:" + symbolTuple.symbol) - outputStream.capturePrint(" @" + releaseYears[symbolTuple.released]!.availabilty + "\n case " + symbolTuple.symbol.replacementName + " = \"" + symbolTuple.symbol + "\"\n" ) - } - outputStream.capturePrint( -""" - public static var allCases: [SFSymbols] { - var allCases: [SFSymbols] = []\n -""" - ) - - for symbolTuple in sortedSymbolTuple { - outputStream.capturePrint(" if #" + releaseYears[symbolTuple.released]!.availabilty + " {\n allCases.append(SFSymbols." + symbolTuple.symbol.replacementName + ")\n }\n") - } - outputStream.capturePrint( -""" - return allCases - } -} -""" - ) - - let writer = FileWriter() - writer.write(with: outputStream.capturedOutput) -} catch (let error as GenerateError) { - switch error { - case .unknown(_), .propertyList(_): - print(error.description) - case .notInstallSFSymbols, .notInstallSFSymbolsBeta: - print("Error:\(error.description)") - } - exit(0) -} diff --git a/Sources/Error/GenerateError.swift b/Sources/Error/GenerateError.swift new file mode 100644 index 0000000..3fc8f59 --- /dev/null +++ b/Sources/Error/GenerateError.swift @@ -0,0 +1,32 @@ +// +// GenerateError.swift +// SFSymbolsGenerator +// +// Created by Leo Ho on 2023/10/27. +// + +import Foundation + +enum GenerateError: Error, CustomStringConvertible { + + case unknown(Error) + + case notInstallSFSymbols + + case notInstallSFSymbolsBeta + + case propertyList(Error) + + var description: String { + switch self { + case .unknown(let error): + "Unknown Error: \(error.localizedDescription)" + case .notInstallSFSymbols: + "SF Symbols.app is not installed yet! Please go to Apple Developer Website to download!" + case .notInstallSFSymbolsBeta: + "SF Symbols beta.app is not installed yet! Please go to Apple Developer Website to download!" + case .propertyList(let error): + "PropertyList Error: \(error.localizedDescription)" + } + } +} diff --git a/SFSymbolsGenerator/Extensions/Release+Extensions.swift b/Sources/Extensions/Release+Extensions.swift similarity index 88% rename from SFSymbolsGenerator/Extensions/Release+Extensions.swift rename to Sources/Extensions/Release+Extensions.swift index 6716578..0f4628f 100644 --- a/SFSymbolsGenerator/Extensions/Release+Extensions.swift +++ b/Sources/Extensions/Release+Extensions.swift @@ -2,7 +2,7 @@ // Release+Extensions.swift // SFSymbolsGenerator // -// Created by Leo Ho on 2023/10/2. +// Created by Leo Ho on 2023/10/27. // import Foundation diff --git a/SFSymbolsGenerator/Extensions/Symbol+Extensions.swift b/Sources/Extensions/Symbol+Extensions.swift similarity index 94% rename from SFSymbolsGenerator/Extensions/Symbol+Extensions.swift rename to Sources/Extensions/Symbol+Extensions.swift index a04a2cc..2a10eb9 100644 --- a/SFSymbolsGenerator/Extensions/Symbol+Extensions.swift +++ b/Sources/Extensions/Symbol+Extensions.swift @@ -2,7 +2,7 @@ // Symbol+Extensions.swift // SFSymbolsGenerator // -// Created by Leo Ho on 2023/10/2. +// Created by Leo Ho on 2023/10/27. // import Foundation diff --git a/Sources/SFSymbolsGenerator.swift b/Sources/SFSymbolsGenerator.swift new file mode 100644 index 0000000..ff8eb80 --- /dev/null +++ b/Sources/SFSymbolsGenerator.swift @@ -0,0 +1,128 @@ +// The Swift Programming Language +// https://docs.swift.org/swift-book +// +// Swift Argument Parser +// https://swiftpackageindex.com/apple/swift-argument-parser/documentation + +import Foundation + +import ArgumentParser + +@main +struct SFSymbolsGenerator: ParsableCommand { + + static let configuration = CommandConfiguration(abstract: "Simplifying SF Symbols Enumeration Generation with Swift!", + version: "0.0.1") + + @Argument( + help: "[Required] Specify filepath of output. Example: /Users//Desktop" + ) + var filepath: String + + @Option( + name: .customLong("name"), + help: "[Optional] Specify filename of output. Example: SFSymbols+Enum" + ) + var filename: String = "SFSymbols+Enum" + + @Flag( + name: [.customLong("use-beta")], + help: "Whether use beta version of SF Symbols or not." + ) + var isUseBeta: Bool = false + + mutating func run() throws { + do { + var appURL: URL! + if isUseBeta { + appURL = URL(fileURLWithPath: "/Applications/SF Symbols beta.app/Contents/Resources/Metadata/name_availability.plist") + } else { + appURL = URL(fileURLWithPath: "/Applications/SF Symbols.app/Contents/Resources/Metadata/name_availability.plist") + } + + let (sortedSymbolTuple, releaseYears) = try readSymbolsAndYears(from: appURL) + + let outputStream = OutputStreamCapture() + + outputStream.capturePrint( + """ + import Foundation + + public enum SFSymbols: String, CaseIterable {\n + """ + ) + + for symbolTuple in sortedSymbolTuple { + outputStream.capturePrint(" " + "/// SF Symbols's name:" + symbolTuple.symbol) + outputStream.capturePrint(" @" + releaseYears[symbolTuple.released]!.availabilty + "\n case " + symbolTuple.symbol.replacementName + " = \"" + symbolTuple.symbol + "\"\n" ) + } + outputStream.capturePrint( + """ + public static var allCases: [SFSymbols] { + var allCases: [SFSymbols] = []\n + """ + ) + + for symbolTuple in sortedSymbolTuple { + outputStream.capturePrint(" if #" + releaseYears[symbolTuple.released]!.availabilty + " {\n allCases.append(SFSymbols." + symbolTuple.symbol.replacementName + ")\n }\n") + } + outputStream.capturePrint( + """ + return allCases + } + } + """ + ) + + let writer = FileWriter() + writer.write(with: outputStream.capturedOutput, and: filename, to: filepath) + } catch (let error as GenerateError) { + switch error { + case .unknown(_), .propertyList(_): + print(error.description) + case .notInstallSFSymbols, .notInstallSFSymbolsBeta: + print("Error:\(error.description)") + } + } + } + + private func readSymbolsAndYears(from fileURL: URL) throws -> ([SymbolTuple], Releases) { + do { + let data = try Data(contentsOf: fileURL, options: .mappedIfSafe) + do { + let propertyList = try PropertyListSerialization.propertyList(from: data, + options: [], + format: nil) as! Dictionary + + let symbols = propertyList["symbols"] as! Symbols + let releases = propertyList["year_to_release"] as! Releases + + let releaseDatesFromSymbols = Set(symbols.values) + let releaseDatesFromReleases = Set(releases.keys) + + assert(releaseDatesFromReleases.isSubset(of:releaseDatesFromSymbols), + "There are symbols with releasedates that have no release versions \(releaseDatesFromReleases) < \(releaseDatesFromSymbols)") + + let sortedSymbolTuple = symbols + .sorted { + $0.value == $1.value ? $0.key < $1.key : $0.value < $1.value + } + .map { + SymbolTuple(symbol: $0.key, released: $0.value) + } + + return (sortedSymbolTuple, releases) + } catch { + throw GenerateError.propertyList(error) + } + } catch { + if fileURL.path().contains("SF%20Symbols.app") { + throw GenerateError.notInstallSFSymbols + } else if fileURL.path().contains("SF%20Symbols%20beta.app") { + throw GenerateError.notInstallSFSymbolsBeta + } else { + throw GenerateError.unknown(error) + } + } + } +} diff --git a/SFSymbolsGenerator/TextOutputStream/OutputStreamCapture.swift b/Sources/TextOutputStream/OutputStreamCapture.swift similarity index 84% rename from SFSymbolsGenerator/TextOutputStream/OutputStreamCapture.swift rename to Sources/TextOutputStream/OutputStreamCapture.swift index 1ca5e20..eb54645 100644 --- a/SFSymbolsGenerator/TextOutputStream/OutputStreamCapture.swift +++ b/Sources/TextOutputStream/OutputStreamCapture.swift @@ -2,7 +2,7 @@ // OutputStreamCapture.swift // SFSymbolsGenerator // -// Created by Leo Ho on 2023/10/2. +// Created by Leo Ho on 2023/10/27. // import Foundation @@ -11,7 +11,7 @@ class OutputStreamCapture { var capturedOutput: String = "" - func capturePrint(_ items: Any..., + func capturePrint(_ items: Any..., separator: String = " ", terminator: String = "\n") { let output = items.map { "\($0)" }.joined(separator: separator) + terminator diff --git a/SFSymbolsGenerator/Typealias/Typealias.swift b/Sources/Typealias/Typealias.swift similarity index 89% rename from SFSymbolsGenerator/Typealias/Typealias.swift rename to Sources/Typealias/Typealias.swift index 00c1f0d..fd25090 100644 --- a/SFSymbolsGenerator/Typealias/Typealias.swift +++ b/Sources/Typealias/Typealias.swift @@ -2,7 +2,7 @@ // Typealias.swift // SFSymbolsGenerator // -// Created by Leo Ho on 2023/10/2. +// Created by Leo Ho on 2023/10/27. // import Foundation diff --git a/Sources/WriteFile/FileWriter.swift b/Sources/WriteFile/FileWriter.swift new file mode 100644 index 0000000..3213694 --- /dev/null +++ b/Sources/WriteFile/FileWriter.swift @@ -0,0 +1,81 @@ +// +// FileWriter.swift +// SFSymbolsGenerator +// +// Created by Leo Ho on 2023/10/27. +// + +import Foundation + +class FileWriter: NSObject { + + private let fileManager = FileManager.default + + /// 檔案寫入 + /// - Parameters: + /// - data: 要寫入的檔案 + /// - filename: 輸出的檔案名稱 + /// - filepath: 輸出的檔案路徑 + func write(with data: String, and filename: String, to filepath: String) { + let type = ".swift" + let file = filename + type + do { + let currentDirectory = fileManager.currentDirectoryPath + let tempPath = currentDirectory + "/" + filename + type + let tempURL = URL(fileURLWithPath: tempPath) + + // 判斷指定路徑下,檔案是否存在,不存在就新增一個,存在就進行複寫 + if !fileManager.fileExists(atPath: file) { + fileManager.createFile(atPath: file, contents: nil) + } + + let fileHandle = try FileHandle(forWritingTo: tempURL) + + // 將字串轉換為 Data + if let data = data.data(using: .utf8) { + // 開始寫檔 + fileHandle.write(data) + + // 關閉檔案 + fileHandle.closeFile() + + #if DEBUG + print("成功:\(file)") + #else + print("Success: \(file)") + #endif + + let destinationPath = filepath + "/" + file // 目標要儲存的路徑 + #if DEBUG + print(destinationPath) + #endif + if !fileManager.fileExists(atPath: destinationPath) { + // 不存在的話... + #if DEBUG + print("指定的路徑下不存在檔案") + #endif + try fileManager.moveItem(atPath: tempPath, toPath: destinationPath) + } else { + // 存在的話... + #if DEBUG + print("指定的路徑下存在檔案") + #endif + try fileManager.removeItem(atPath: destinationPath) + #if DEBUG + print("先移除舊檔案成功") + #endif + fileManager.createFile(atPath: destinationPath, contents: data) + #if DEBUG + print("再建立新檔案成功") + #endif + } + } + } catch { + #if DEBUG + print("錯誤:\(error)") + #else + print("Error: \(error)") + #endif + } + } +}