Refactor in one unique command with subcommand + add a new command to generate ressources from a configuration file
Some checks failed
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
Some checks failed
gitea-openium/resgen.swift/pipeline/head There was a failure building this commit
This commit is contained in:
@ -160,6 +160,20 @@
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "ColorTool"
|
||||
BuildableName = "ColorTool"
|
||||
BlueprintName = "ColorTool"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
|
@ -34,6 +34,34 @@
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "ToolCore"
|
||||
BuildableName = "ToolCore"
|
||||
BlueprintName = "ToolCore"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "ResgenSwift_ResgenSwift"
|
||||
BuildableName = "ResgenSwift_ResgenSwift"
|
||||
BlueprintName = "ResgenSwift_ResgenSwift"
|
||||
ReferencedContainer = "container:">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
|
@ -9,6 +9,15 @@
|
||||
"revision": "e1465042f195f374b94f915ba8ca49de24300a0d",
|
||||
"version": "1.0.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "Yams",
|
||||
"repositoryURL": "https://github.com/jpsim/Yams.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "01835dc202670b5bb90d07f3eae41867e9ed29f6",
|
||||
"version": "5.0.1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1,56 +1,67 @@
|
||||
// swift-tools-version:5.3
|
||||
// swift-tools-version:5.6
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "ResgenSwift",
|
||||
platforms: [.macOS(.v10_12)],
|
||||
platforms: [.macOS(.v12)],
|
||||
dependencies: [
|
||||
// Dependencies declare other packages that this package depends on.
|
||||
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0")
|
||||
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0"),
|
||||
.package(url: "https://github.com/jpsim/Yams.git", from: "5.0.1")
|
||||
],
|
||||
targets: [
|
||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||
// Targets can depend on other targets in this package, and on products in packages this package depends on.
|
||||
.target(
|
||||
.executableTarget(
|
||||
name: "ResgenSwift",
|
||||
dependencies: ["FontTool", "ColorTool", "Strings", "Imagium"]
|
||||
),
|
||||
.target(
|
||||
name: "FontTool",
|
||||
dependencies: [
|
||||
"ToolCore",
|
||||
.product(name: "ArgumentParser", package: "swift-argument-parser")
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "ColorTool",
|
||||
dependencies: [
|
||||
"ToolCore",
|
||||
.product(name: "ArgumentParser", package: "swift-argument-parser")
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "Strings",
|
||||
dependencies: [
|
||||
"ToolCore",
|
||||
.product(name: "ArgumentParser", package: "swift-argument-parser")
|
||||
],
|
||||
sources: ["."] // Force include all subdirectories
|
||||
),
|
||||
.target(
|
||||
name: "Imagium",
|
||||
dependencies: [
|
||||
"ToolCore",
|
||||
.product(name: "ArgumentParser", package: "swift-argument-parser")
|
||||
.product(name: "ArgumentParser", package: "swift-argument-parser"),
|
||||
"Yams"
|
||||
]
|
||||
),
|
||||
|
||||
// .executableTarget(
|
||||
// name: "FontTool",
|
||||
// dependencies: [
|
||||
// "ToolCore",
|
||||
// .product(name: "ArgumentParser", package: "swift-argument-parser")
|
||||
// ]
|
||||
// ),
|
||||
//
|
||||
// .executableTarget(
|
||||
// name: "ColorTool",
|
||||
// dependencies: [
|
||||
// "ToolCore",
|
||||
// .product(name: "ArgumentParser", package: "swift-argument-parser")
|
||||
// ]
|
||||
// ),
|
||||
//
|
||||
// .executableTarget(
|
||||
// name: "Strings",
|
||||
// dependencies: [
|
||||
// "ToolCore",
|
||||
// .product(name: "ArgumentParser", package: "swift-argument-parser")
|
||||
// ],
|
||||
// sources: ["."] // Force include all subdirectories
|
||||
// ),
|
||||
//
|
||||
// .executableTarget(
|
||||
// name: "Imagium",
|
||||
// dependencies: [
|
||||
// "ToolCore",
|
||||
// .product(name: "ArgumentParser", package: "swift-argument-parser")
|
||||
// ]
|
||||
// ),
|
||||
|
||||
// Helper targets
|
||||
.target(name: "ToolCore"),
|
||||
|
||||
// Test targets
|
||||
.testTarget(
|
||||
name: "ResgenSwiftTests",
|
||||
dependencies: ["ResgenSwift"]),
|
||||
// .testTarget(
|
||||
// name: "ResgenSwiftTests",
|
||||
// dependencies: ["ResgenSwift"]),
|
||||
]
|
||||
)
|
||||
|
@ -121,7 +121,7 @@ swift run -c release Strings tags $FORCE_FLAG "./Tags/tags.txt" \
|
||||
5. `--extension-name` *(optional)* : name of class to add the extension
|
||||
6. `--extension-suffix` *(optional)* : additional text which is added to filename (ex: `AppTags+GreatApp.swift`)
|
||||
|
||||
> ⚠️ If extension name is not set or is `Tags`, it will generate static property on `Tags`. This class may not exists in your project, just create an empty class named `Tags` is necessary.
|
||||
> ⚠️ If extension name is not set or is `Tags`, it will generate static property on `Tags`. `Tags` is a typealias of `String`.
|
||||
|
||||
# Images
|
||||
|
||||
|
@ -1,35 +0,0 @@
|
||||
//
|
||||
// ColorToolError.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 20/12/2021.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum ColorToolError: Error {
|
||||
case badFormat(String)
|
||||
case writeAsset(String)
|
||||
case writeExtension(String, String)
|
||||
case fileNotExists(String)
|
||||
case badColorDefinition(String, String)
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .badFormat(let info):
|
||||
return "error:[ColorTool] Bad line format: \(info). Accepted format are: colorName=\"#RGB/#ARGB\"; colorName \"#RGB/#ARGB\"; colorName \"#RGB/#ARGB\" \"#RGB/#ARGB\""
|
||||
|
||||
case .writeAsset(let info):
|
||||
return "error:[ColorTool] An error occured while writing color in Xcasset: \(info)"
|
||||
|
||||
case .writeExtension(let filename, let info):
|
||||
return "error:[ColorTool] An error occured while writing extension in \(filename): \(info)"
|
||||
|
||||
case .fileNotExists(let filename):
|
||||
return "error:[ColorTool] File \(filename) does not exists"
|
||||
|
||||
case .badColorDefinition(let lightColor, let darkColor):
|
||||
return "error:[ColorTool]One of these two colors has invalid synthax: -\(lightColor)- or -\(darkColor)-"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
//
|
||||
// ImagiumError.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 24/01/2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum ImagiumError: Error {
|
||||
case inputFolderNotFound(String)
|
||||
case fileNotExists(String)
|
||||
case unknownImageExtension(String)
|
||||
case getFileAttributed(String, String)
|
||||
case rsvgConvertNotFound
|
||||
case writeFile(String, String)
|
||||
case unknown(String)
|
||||
|
||||
var localizedDescription: String {
|
||||
switch self {
|
||||
case .inputFolderNotFound(let inputFolder):
|
||||
return " error:[\(Imagium.toolName)] Input folder not found: \(inputFolder)"
|
||||
|
||||
case .fileNotExists(let filename):
|
||||
return " error:[\(Imagium.toolName)] File \(filename) does not exists"
|
||||
|
||||
case .unknownImageExtension(let filename):
|
||||
return " error:[\(Imagium.toolName)] File \(filename) have an unhandled file extension. Cannot generate image."
|
||||
|
||||
case .getFileAttributed(let filename, let errorDescription):
|
||||
return " error:[\(Imagium.toolName)] Getting file attributes of \(filename) failed with error: \(errorDescription)"
|
||||
|
||||
case .rsvgConvertNotFound:
|
||||
return " error:[\(Imagium.toolName)] Can't find rsvg-convert (can be installed with 'brew remove imagemagick && brew install imagemagick --with-librsvg')"
|
||||
|
||||
case .writeFile(let subErrorDescription, let filename):
|
||||
return " error:[\(Imagium.toolName)] An error occured while writing content to \(filename): \(subErrorDescription)"
|
||||
|
||||
case .unknown(let errorDescription):
|
||||
return " error:[\(Imagium.toolName)] Unknown error: \(errorDescription)"
|
||||
}
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ import ToolCore
|
||||
import Foundation
|
||||
import ArgumentParser
|
||||
|
||||
struct ColorTool: ParsableCommand {
|
||||
struct Colors: ParsableCommand {
|
||||
|
||||
// MARK: - CommandConfiguration
|
||||
|
||||
@ -20,7 +20,7 @@ struct ColorTool: ParsableCommand {
|
||||
|
||||
// MARK: - Static
|
||||
|
||||
static let toolName = "ColorTool"
|
||||
static let toolName = "Color"
|
||||
static let defaultExtensionName = "UIColor"
|
||||
static let assetsColorsFolderName = "Colors"
|
||||
|
||||
@ -39,7 +39,7 @@ struct ColorTool: ParsableCommand {
|
||||
|
||||
// MARK: - Command options
|
||||
|
||||
@OptionGroup var options: ColorToolOptions
|
||||
@OptionGroup var options: ColorsToolOptions
|
||||
|
||||
// MARK: - Run
|
||||
|
||||
@ -79,16 +79,16 @@ struct ColorTool: ParsableCommand {
|
||||
|
||||
// Check if input file exists
|
||||
guard fileManager.fileExists(atPath: options.inputFile) else {
|
||||
let error = ColorToolError.fileNotExists(options.inputFile)
|
||||
let error = ColorsToolError.fileNotExists(options.inputFile)
|
||||
print(error.localizedDescription)
|
||||
ColorTool.exit(withError: error)
|
||||
Colors.exit(withError: error)
|
||||
}
|
||||
|
||||
// Check if xcassets file exists
|
||||
guard fileManager.fileExists(atPath: options.xcassetsPath) else {
|
||||
let error = ColorToolError.fileNotExists(options.xcassetsPath)
|
||||
let error = ColorsToolError.fileNotExists(options.xcassetsPath)
|
||||
print(error.localizedDescription)
|
||||
ColorTool.exit(withError: error)
|
||||
Colors.exit(withError: error)
|
||||
}
|
||||
|
||||
// Check if needed to regenerate
|
||||
@ -107,8 +107,6 @@ struct ColorTool: ParsableCommand {
|
||||
}
|
||||
}
|
||||
|
||||
ColorTool.main()
|
||||
|
||||
/*
|
||||
Command samples:
|
||||
|
35
Sources/ResgenSwift/Colors/ColorsToolError.swift
Normal file
35
Sources/ResgenSwift/Colors/ColorsToolError.swift
Normal file
@ -0,0 +1,35 @@
|
||||
//
|
||||
// ColorsToolError.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 20/12/2021.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum ColorsToolError: Error {
|
||||
case badFormat(String)
|
||||
case writeAsset(String)
|
||||
case writeExtension(String, String)
|
||||
case fileNotExists(String)
|
||||
case badColorDefinition(String, String)
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .badFormat(let info):
|
||||
return "error:[\(Colors.toolName)] Bad line format: \(info). Accepted format are: colorName=\"#RGB/#ARGB\"; colorName \"#RGB/#ARGB\"; colorName \"#RGB/#ARGB\" \"#RGB/#ARGB\""
|
||||
|
||||
case .writeAsset(let info):
|
||||
return "error:[\(Colors.toolName)] An error occured while writing color in Xcasset: \(info)"
|
||||
|
||||
case .writeExtension(let filename, let info):
|
||||
return "error:[\(Colors.toolName)] An error occured while writing extension in \(filename): \(info)"
|
||||
|
||||
case .fileNotExists(let filename):
|
||||
return "error:[\(Colors.toolName)] File \(filename) does not exists"
|
||||
|
||||
case .badColorDefinition(let lightColor, let darkColor):
|
||||
return "error:[\(Colors.toolName)]One of these two colors has invalid synthax: -\(lightColor)- or -\(darkColor)-"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// ColorToolOptions.swift
|
||||
// ColorsToolOptions.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 17/01/2022.
|
||||
@ -8,7 +8,7 @@
|
||||
import Foundation
|
||||
import ArgumentParser
|
||||
|
||||
struct ColorToolOptions: ParsableArguments {
|
||||
struct ColorsToolOptions: ParsableArguments {
|
||||
@Flag(name: [.customShort("f"), .customShort("F")], help: "Should force generation")
|
||||
var forceGeneration = false
|
||||
|
||||
@ -25,13 +25,13 @@ struct ColorToolOptions: ParsableArguments {
|
||||
var extensionOutputPath: String
|
||||
|
||||
@Option(help: "Extension name. If not specified, it will generate an UIColor extension. Using default extension name will generate static property.")
|
||||
var extensionName: String = ColorTool.defaultExtensionName
|
||||
var extensionName: String = Colors.defaultExtensionName
|
||||
|
||||
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+ColorsMyApp.swift")
|
||||
var extensionSuffix: String = ""
|
||||
}
|
||||
|
||||
extension ColorToolOptions {
|
||||
extension ColorsToolOptions {
|
||||
var colorStyle: ColorStyle {
|
||||
ColorStyle(rawValue: style) ?? .all
|
||||
}
|
@ -33,15 +33,15 @@ struct ColorExtensionGenerator {
|
||||
do {
|
||||
try extensionContent.write(to: extensionFilePathURL, atomically: true, encoding: .utf8)
|
||||
} catch (let error) {
|
||||
let error = ColorToolError.writeExtension(extensionFilePath, error.localizedDescription)
|
||||
let error = ColorsToolError.writeExtension(extensionFilePath, error.localizedDescription)
|
||||
print(error.localizedDescription)
|
||||
ColorTool.exit(withError: error)
|
||||
Colors.exit(withError: error)
|
||||
}
|
||||
}
|
||||
|
||||
private static func getHeader(extensionClassname: String) -> String {
|
||||
"""
|
||||
// Generated by ResgenSwift.\(ColorTool.toolName) \(ResgenSwiftVersion)
|
||||
// Generated by ResgenSwift.\(Colors.toolName) \(ResgenSwiftVersion)
|
||||
|
||||
import UIKit
|
||||
|
@ -31,9 +31,9 @@ struct ColorXcassetHelper {
|
||||
do {
|
||||
try color.contentsJSON().write(to: contentsJsonPathURL, atomically: true, encoding: .utf8)
|
||||
} catch (let error) {
|
||||
let error = ColorToolError.writeAsset(error.localizedDescription)
|
||||
let error = ColorsToolError.writeAsset(error.localizedDescription)
|
||||
print(error.localizedDescription)
|
||||
ColorTool.exit(withError: error)
|
||||
Colors.exit(withError: error)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// File.swift
|
||||
// ColorStyle.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 29/08/2022.
|
@ -25,9 +25,9 @@ struct ParsedColor {
|
||||
}
|
||||
|
||||
guard allComponents.contains(true) == false else {
|
||||
let error = ColorToolError.badColorDefinition(light, dark)
|
||||
let error = ColorsToolError.badColorDefinition(light, dark)
|
||||
print(error.localizedDescription)
|
||||
ColorTool.exit(withError: error)
|
||||
Colors.exit(withError: error)
|
||||
}
|
||||
|
||||
return """
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// File.swift
|
||||
// ColorFileParser.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 29/08/2022.
|
||||
@ -22,16 +22,16 @@ class ColorFileParser {
|
||||
.replacingOccurrences(of: "=", with: "") // Keep compat with current file format
|
||||
|
||||
guard colorLineCleanedUp.hasPrefix("#") == false, colorLineCleanedUp.isEmpty == false else {
|
||||
print("[\(ColorTool.toolName)] ⚠️ BadFormat or empty line (line number: \(lineNumber + 1)). Skip this line")
|
||||
print("[\(Colors.toolName)] ⚠️ BadFormat or empty line (line number: \(lineNumber + 1)). Skip this line")
|
||||
return nil
|
||||
}
|
||||
|
||||
let colorContent = colorLineCleanedUp.split(separator: " ")
|
||||
|
||||
guard colorContent.count >= 2 else {
|
||||
let error = ColorToolError.badFormat(colorLine)
|
||||
let error = ColorsToolError.badFormat(colorLine)
|
||||
print(error.localizedDescription)
|
||||
ColorTool.exit(withError: error)
|
||||
Colors.exit(withError: error)
|
||||
}
|
||||
|
||||
switch colorStyle {
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// FontOptions.swift
|
||||
// FontsOptions.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 17/01/2022.
|
||||
@ -8,7 +8,7 @@
|
||||
import Foundation
|
||||
import ArgumentParser
|
||||
|
||||
struct FontOptions: ParsableArguments {
|
||||
struct FontsOptions: ParsableArguments {
|
||||
@Flag(name: [.customShort("f"), .customShort("F")], help: "Should force generation")
|
||||
var forceGeneration = false
|
||||
|
||||
@ -19,8 +19,25 @@ struct FontOptions: ParsableArguments {
|
||||
var extensionOutputPath: String
|
||||
|
||||
@Option(help: "Extension name. If not specified, it will generate an UIFont extension. Using default extension name will generate static property.")
|
||||
var extensionName: String = FontTool.defaultExtensionName
|
||||
var extensionName: String = Fonts.defaultExtensionName
|
||||
|
||||
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+FontsMyApp.swift")
|
||||
var extensionSuffix: String = ""
|
||||
}
|
||||
|
||||
extension FontsOptions {
|
||||
var extensionFileName: String {
|
||||
if extensionSuffix.isEmpty == false {
|
||||
return "\(extensionName)+\(extensionSuffix).swift"
|
||||
}
|
||||
return "\(extensionName).swift"
|
||||
}
|
||||
|
||||
var extensionFilePath: String {
|
||||
"\(extensionOutputPath)/\(extensionFileName)"
|
||||
}
|
||||
|
||||
var generateStaticVariable: Bool {
|
||||
extensionName == Fonts.defaultExtensionName
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// FontTool.swift
|
||||
// Fonts.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 13/12/2021.
|
||||
@ -9,7 +9,7 @@ import ToolCore
|
||||
import Foundation
|
||||
import ArgumentParser
|
||||
|
||||
struct FontTool: ParsableCommand {
|
||||
struct Fonts: ParsableCommand {
|
||||
|
||||
// MARK: - CommandConfiguration
|
||||
|
||||
@ -20,7 +20,7 @@ struct FontTool: ParsableCommand {
|
||||
|
||||
// MARK: - Static
|
||||
|
||||
static let toolName = "FontTool"
|
||||
static let toolName = "Fonts"
|
||||
static let defaultExtensionName = "UIFont"
|
||||
|
||||
// MARK: - Properties
|
||||
@ -38,7 +38,7 @@ struct FontTool: ParsableCommand {
|
||||
|
||||
// MARK: - Command Options
|
||||
|
||||
@OptionGroup var options: FontOptions
|
||||
@OptionGroup var options: FontsOptions
|
||||
|
||||
// MARK: - Run
|
||||
|
||||
@ -55,7 +55,7 @@ struct FontTool: ParsableCommand {
|
||||
|
||||
// Get real font names
|
||||
let inputFolder = URL(fileURLWithPath: options.inputFile).deletingLastPathComponent().relativePath
|
||||
let fontsNames = FontToolHelper.getFontPostScriptName(for: fontsToGenerate,
|
||||
let fontsNames = FontsToolHelper.getFontPostScriptName(for: fontsToGenerate,
|
||||
inputFolder: inputFolder)
|
||||
|
||||
// Generate extension
|
||||
@ -77,9 +77,9 @@ struct FontTool: ParsableCommand {
|
||||
|
||||
// Check input file exists
|
||||
guard fileManager.fileExists(atPath: options.inputFile) else {
|
||||
let error = FontToolError.fileNotExists(options.inputFile)
|
||||
let error = FontsToolError.fileNotExists(options.inputFile)
|
||||
print(error.localizedDescription)
|
||||
FontTool.exit(withError: error)
|
||||
Fonts.exit(withError: error)
|
||||
}
|
||||
|
||||
// Check if needed to regenerate
|
||||
@ -91,5 +91,3 @@ struct FontTool: ParsableCommand {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
FontTool.main()
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// FontToolError.swift
|
||||
// FontsToolError.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 13/12/2021.
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
enum FontToolError: Error {
|
||||
enum FontsToolError: Error {
|
||||
case fcScan(String, Int32, String?)
|
||||
case inputFolderNotFound(String)
|
||||
case fileNotExists(String)
|
||||
@ -16,16 +16,16 @@ enum FontToolError: Error {
|
||||
var localizedDescription: String {
|
||||
switch self {
|
||||
case .fcScan(let path, let code, let output):
|
||||
return "error:[\(FontTool.toolName)] Error while getting fontName (fc-scan --format %{postscriptname} \(path). fc-scan exit with \(code) and output is: \(output ?? "no output")"
|
||||
return "error:[\(Fonts.toolName)] Error while getting fontName (fc-scan --format %{postscriptname} \(path). fc-scan exit with \(code) and output is: \(output ?? "no output")"
|
||||
|
||||
case .inputFolderNotFound(let inputFolder):
|
||||
return " error:[\(FontTool.toolName)] Input folder not found: \(inputFolder)"
|
||||
return " error:[\(Fonts.toolName)] Input folder not found: \(inputFolder)"
|
||||
|
||||
case .fileNotExists(let filename):
|
||||
return " error:[\(FontTool.toolName)] File \(filename) does not exists"
|
||||
return " error:[\(Fonts.toolName)] File \(filename) does not exists"
|
||||
|
||||
case .writeExtension(let filename, let info):
|
||||
return "error:[\(FontTool.toolName)] An error occured while writing extension in \(filename): \(info)"
|
||||
return "error:[\(Fonts.toolName)] An error occured while writing extension in \(filename): \(info)"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// FontToolHelper.swift
|
||||
// FontsToolHelper.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 13/12/2021.
|
||||
@ -8,7 +8,7 @@
|
||||
import Foundation
|
||||
import ToolCore
|
||||
|
||||
class FontToolHelper {
|
||||
class FontsToolHelper {
|
||||
|
||||
static func getFontPostScriptName(for fonts: [String], inputFolder: String) -> [FontName] {
|
||||
let fontsFilenames = Self.getFontsFilenames(fromInputFolder: inputFolder)
|
||||
@ -38,9 +38,9 @@ class FontToolHelper {
|
||||
// Get a enumerator for all files
|
||||
let fileManager = FileManager()
|
||||
guard fileManager.fileExists(atPath: inputFolder) else {
|
||||
let error = FontToolError.inputFolderNotFound(inputFolder)
|
||||
let error = FontsToolError.inputFolderNotFound(inputFolder)
|
||||
print(error.localizedDescription)
|
||||
FontTool.exit(withError: error)
|
||||
Fonts.exit(withError: error)
|
||||
}
|
||||
|
||||
let enumerator: FileManager.DirectoryEnumerator = fileManager.enumerator(atPath: inputFolder)!
|
||||
@ -63,9 +63,9 @@ class FontToolHelper {
|
||||
let task = Shell.shell("fc-scan", "--format", "%{postscriptname}", path)
|
||||
|
||||
guard let fontName = task.output, task.terminationStatus == 0 else {
|
||||
let error = FontToolError.fcScan(path, task.terminationStatus, task.output)
|
||||
let error = FontsToolError.fcScan(path, task.terminationStatus, task.output)
|
||||
print(error.localizedDescription)
|
||||
FontTool.exit(withError: error)
|
||||
Fonts.exit(withError: error)
|
||||
}
|
||||
|
||||
return fontName
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// File.swift
|
||||
// FontPlistGenerator.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 29/08/2022.
|
@ -31,15 +31,15 @@ class FontExtensionGenerator {
|
||||
do {
|
||||
try extensionContent.write(to: extensionFilePathURL, atomically: true, encoding: .utf8)
|
||||
} catch (let error) {
|
||||
let error = FontToolError.writeExtension(extensionFilePath, error.localizedDescription)
|
||||
let error = FontsToolError.writeExtension(extensionFilePath, error.localizedDescription)
|
||||
print(error.localizedDescription)
|
||||
FontTool.exit(withError: error)
|
||||
Fonts.exit(withError: error)
|
||||
}
|
||||
}
|
||||
|
||||
private static func getHeader(extensionClassname: String) -> String {
|
||||
"""
|
||||
// Generated by ResgenSwift.\(FontTool.toolName) \(ResgenSwiftVersion)
|
||||
// Generated by ResgenSwift.\(Fonts.toolName) \(ResgenSwiftVersion)
|
||||
|
||||
import UIKit
|
||||
|
||||
@ -48,18 +48,18 @@ class FontExtensionGenerator {
|
||||
}
|
||||
|
||||
private static func getFontNameEnum(fontsNames: [String]) -> String {
|
||||
var enumDefinition = "\tenum FontName: String {\n"
|
||||
var enumDefinition = " enum FontName: String {\n"
|
||||
|
||||
fontsNames.forEach {
|
||||
enumDefinition += "\t\tcase \($0.removeCharacters(from: "[]+-_")) = \"\($0)\"\n"
|
||||
enumDefinition += " case \($0.removeCharacters(from: "[]+-_")) = \"\($0)\"\n"
|
||||
}
|
||||
enumDefinition += "\t}\n"
|
||||
enumDefinition += " }\n"
|
||||
|
||||
return enumDefinition
|
||||
}
|
||||
|
||||
private static func getFontMethods(fontsNames: [FontName], staticVar: Bool) -> String {
|
||||
let pragma = "\t// MARK: - Getter"
|
||||
let pragma = " // MARK: - Getter"
|
||||
|
||||
var propertiesOrMethods: [String] = fontsNames
|
||||
.unique()
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// File.swift
|
||||
// FontName.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 29/08/2022.
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// File.swift
|
||||
// FontFileParser.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 29/08/2022.
|
51
Sources/ResgenSwift/Generate/Generate.swift
Normal file
51
Sources/ResgenSwift/Generate/Generate.swift
Normal file
@ -0,0 +1,51 @@
|
||||
//
|
||||
// Generate.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 30/08/2022.
|
||||
//
|
||||
|
||||
import ToolCore
|
||||
import Foundation
|
||||
import ArgumentParser
|
||||
|
||||
struct Generate: ParsableCommand {
|
||||
|
||||
// MARK: - CommandConfiguration
|
||||
|
||||
static var configuration = CommandConfiguration(
|
||||
abstract: "A utility to generate ressources based on a configuration file",
|
||||
version: ResgenSwiftVersion
|
||||
)
|
||||
|
||||
// MARK: - Static
|
||||
|
||||
static let toolName = "Generate"
|
||||
|
||||
// MARK: - Command Options
|
||||
|
||||
@OptionGroup var options: GenerateOptions
|
||||
|
||||
// MARK: - Run
|
||||
|
||||
public func run() throws {
|
||||
print("[\(Self.toolName)] Starting Resgen with configuration: \(options.configurationFile)")
|
||||
|
||||
// Parse
|
||||
let configuration = ConfigurationFileParser.parse(options.configurationFile)
|
||||
print("Found configurations :")
|
||||
print(" - \(configuration.colors.count) colors configuration")
|
||||
print(" - \(configuration.fonts.count) fonts configuration")
|
||||
print(" - \(configuration.images.count) images configuration")
|
||||
print(" - \(configuration.strings.count) strings configuration")
|
||||
print(" - \(configuration.tags.count) tags configuration")
|
||||
print()
|
||||
// Execute commands
|
||||
configuration.runnableConfigurations
|
||||
.forEach {
|
||||
$0.run(force: options.forceGeneration)
|
||||
}
|
||||
|
||||
print("[\(Self.toolName)] Resgen ended")
|
||||
}
|
||||
}
|
30
Sources/ResgenSwift/Generate/GenerateError.swift
Normal file
30
Sources/ResgenSwift/Generate/GenerateError.swift
Normal file
@ -0,0 +1,30 @@
|
||||
//
|
||||
// ResgenSwiftError.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 30/08/2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum GenerateError: Error {
|
||||
case fileNotExists(String)
|
||||
case invalidConfigurationFile(String)
|
||||
case commandError([String], String)
|
||||
|
||||
var localizedDescription: String {
|
||||
switch self {
|
||||
case .fileNotExists(let filename):
|
||||
return " error:[\(Generate.toolName)] File \(filename) does not exists"
|
||||
|
||||
case .invalidConfigurationFile(let filename):
|
||||
return " error:[\(Generate.toolName)] File \(filename) is not a valid configuration file"
|
||||
|
||||
case .commandError(let command, let terminationStatus):
|
||||
let readableCommand = command
|
||||
.map { $0 }
|
||||
.joined(separator: " ")
|
||||
return "error:[\(Generate.toolName)] An error occured while running command '\(readableCommand)'. Command terminate with status code: \(terminationStatus)"
|
||||
}
|
||||
}
|
||||
}
|
19
Sources/ResgenSwift/Generate/GenerateOptions.swift
Normal file
19
Sources/ResgenSwift/Generate/GenerateOptions.swift
Normal file
@ -0,0 +1,19 @@
|
||||
//
|
||||
// GenerateOptions.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 30/08/2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
import Foundation
|
||||
import ArgumentParser
|
||||
|
||||
struct GenerateOptions: ParsableArguments {
|
||||
@Flag(name: [.customShort("f"), .customShort("F")], help: "Should force generation")
|
||||
var forceGeneration = false
|
||||
|
||||
@Argument(help: "Configuration file.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
|
||||
var configurationFile: String
|
||||
}
|
140
Sources/ResgenSwift/Generate/Model/ConfigurationFile.swift
Normal file
140
Sources/ResgenSwift/Generate/Model/ConfigurationFile.swift
Normal file
@ -0,0 +1,140 @@
|
||||
//
|
||||
// ConfigurationFile.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 30/08/2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct ConfigurationFile: Codable, CustomDebugStringConvertible {
|
||||
var colors: [ColorsConfiguration]
|
||||
var fonts: [FontsConfiguration]
|
||||
var images: [ImagesConfiguration]
|
||||
var strings: [StringsConfiguration]
|
||||
var tags: [TagsConfiguration]
|
||||
|
||||
var runnableConfigurations: [Runnable] {
|
||||
let runnables: [[Runnable]] = [colors, fonts, images, strings, tags]
|
||||
return Array(runnables.joined())
|
||||
}
|
||||
|
||||
var debugDescription: String {
|
||||
"""
|
||||
\(colors)
|
||||
-----------
|
||||
-----------
|
||||
\(fonts)
|
||||
-----------
|
||||
-----------
|
||||
\(images)
|
||||
-----------
|
||||
-----------
|
||||
\(strings)
|
||||
-----------
|
||||
-----------
|
||||
\(tags)
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct ColorsConfiguration: Codable, CustomDebugStringConvertible {
|
||||
let inputFile: String
|
||||
let style: String
|
||||
let xcassetsPath: String
|
||||
let extensionOutputPath: String
|
||||
let extensionName: String?
|
||||
let extensionSuffix: String?
|
||||
|
||||
var debugDescription: String {
|
||||
"""
|
||||
Colors configuration:
|
||||
- Input file: \(inputFile)
|
||||
- Style: \(style)
|
||||
- Xcassets path: \(xcassetsPath)
|
||||
- Extension output path: \(extensionOutputPath)
|
||||
- Extension name: \(extensionName ?? "-")
|
||||
- Extension suffix: \(extensionSuffix ?? "-")
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
struct FontsConfiguration: Codable, CustomDebugStringConvertible {
|
||||
let inputFile: String
|
||||
let extensionOutputPath: String
|
||||
let extensionName: String?
|
||||
let extensionSuffix: String?
|
||||
|
||||
var debugDescription: String {
|
||||
"""
|
||||
Fonts configuration:
|
||||
- Input file: \(inputFile)
|
||||
- Extension output path: \(extensionOutputPath)
|
||||
- Extension name: \(extensionName ?? "-")
|
||||
- Extension suffix: \(extensionSuffix ?? "-")
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
struct ImagesConfiguration: Codable, CustomDebugStringConvertible {
|
||||
let inputFile: String
|
||||
let xcassetsPath: String
|
||||
let extensionOutputPath: String
|
||||
let extensionName: String?
|
||||
let extensionSuffix: String?
|
||||
|
||||
var debugDescription: String {
|
||||
"""
|
||||
Images configuration:
|
||||
- Input file: \(inputFile)
|
||||
- Xcassets path: \(xcassetsPath)
|
||||
- Extension output path: \(extensionOutputPath)
|
||||
- Extension name: \(extensionName ?? "-")
|
||||
- Extension suffix: \(extensionSuffix ?? "-")
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
struct StringsConfiguration: Codable, CustomDebugStringConvertible {
|
||||
let inputFile: String
|
||||
let outputPath: String
|
||||
let langs: String
|
||||
let defaultLang: String
|
||||
let extensionOutputPath: String
|
||||
let extensionName: String?
|
||||
let extensionSuffix: String?
|
||||
|
||||
var debugDescription: String {
|
||||
"""
|
||||
Strings configuration:
|
||||
- Input file: \(inputFile)
|
||||
- Output path: \(outputPath)
|
||||
- Langs: \(langs)
|
||||
- Default lang: \(defaultLang)
|
||||
- Extension output path: \(extensionOutputPath)
|
||||
- Extension name: \(extensionName ?? "-")
|
||||
- Extension suffix: \(extensionSuffix ?? "-")
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
struct TagsConfiguration: Codable, CustomDebugStringConvertible {
|
||||
let inputFile: String
|
||||
let lang: String
|
||||
let extensionOutputPath: String
|
||||
let extensionName: String?
|
||||
let extensionSuffix: String?
|
||||
|
||||
var debugDescription: String {
|
||||
"""
|
||||
Tags configuration:
|
||||
- Input file: \(inputFile)
|
||||
- Lang: \(lang)
|
||||
- Extension output path: \(extensionOutputPath)
|
||||
- Extension name: \(extensionName ?? "-")
|
||||
- Extension suffix: \(extensionSuffix ?? "-")
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
//
|
||||
// ConfigurationFileParser.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 30/08/2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Yams
|
||||
|
||||
class ConfigurationFileParser {
|
||||
static func parse(_ configurationFile: String) -> ConfigurationFile {
|
||||
guard let data = FileManager().contents(atPath: configurationFile) else {
|
||||
let error = GenerateError.fileNotExists(configurationFile)
|
||||
print(error.localizedDescription)
|
||||
Generate.exit(withError: error)
|
||||
}
|
||||
|
||||
guard let configuration = try? YAMLDecoder().decode(ConfigurationFile.self, from: data) else {
|
||||
let error = GenerateError.invalidConfigurationFile(configurationFile)
|
||||
print(error.localizedDescription)
|
||||
Generate.exit(withError: error)
|
||||
}
|
||||
|
||||
return configuration
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
//
|
||||
// ColorsConfiguration+ShellCommandable.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 30/08/2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension ColorsConfiguration: Runnable {
|
||||
func run(force: Bool) {
|
||||
var args = [String]()
|
||||
|
||||
if force {
|
||||
args += ["-f"]
|
||||
}
|
||||
|
||||
args += [
|
||||
inputFile,
|
||||
"--style",
|
||||
style,
|
||||
"--xcassets-path",
|
||||
xcassetsPath,
|
||||
"--extension-output-path",
|
||||
extensionOutputPath
|
||||
]
|
||||
|
||||
if let extensionName = extensionName {
|
||||
args += [
|
||||
"--extension-name",
|
||||
extensionName
|
||||
]
|
||||
}
|
||||
if let extensionSuffix = extensionSuffix {
|
||||
args += [
|
||||
"--extension-suffix",
|
||||
extensionSuffix
|
||||
]
|
||||
}
|
||||
|
||||
Colors.main(args)
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
//
|
||||
// FontsConfiguration+ShellCommandable.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 30/08/2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension FontsConfiguration: Runnable {
|
||||
func run(force: Bool) {
|
||||
var args = [String]()
|
||||
|
||||
if force {
|
||||
args += ["-f"]
|
||||
}
|
||||
|
||||
args += [
|
||||
inputFile,
|
||||
"--extension-output-path",
|
||||
extensionOutputPath
|
||||
]
|
||||
|
||||
if let extensionName = extensionName {
|
||||
args += [
|
||||
"--extension-name",
|
||||
extensionName
|
||||
]
|
||||
}
|
||||
|
||||
if let extensionSuffix = extensionSuffix {
|
||||
args += [
|
||||
"--extension-suffix",
|
||||
extensionSuffix
|
||||
]
|
||||
}
|
||||
|
||||
Fonts.main(args)
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
//
|
||||
// ImagesConfiguration+ShellCommandable.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 30/08/2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension ImagesConfiguration: Runnable {
|
||||
func run(force: Bool) {
|
||||
var args = [String]()
|
||||
|
||||
if force {
|
||||
args += ["-f"]
|
||||
}
|
||||
|
||||
args += [
|
||||
inputFile,
|
||||
"--xcassets-path",
|
||||
xcassetsPath,
|
||||
"--extension-output-path",
|
||||
extensionOutputPath
|
||||
]
|
||||
|
||||
if let extensionName = extensionName {
|
||||
args += [
|
||||
"--extension-name",
|
||||
extensionName
|
||||
]
|
||||
}
|
||||
if let extensionSuffix = extensionSuffix {
|
||||
args += [
|
||||
"--extension-suffix",
|
||||
extensionSuffix
|
||||
]
|
||||
}
|
||||
|
||||
Images.main(args)
|
||||
}
|
||||
}
|
13
Sources/ResgenSwift/Generate/ShellCommandable/Runnable.swift
Normal file
13
Sources/ResgenSwift/Generate/ShellCommandable/Runnable.swift
Normal file
@ -0,0 +1,13 @@
|
||||
//
|
||||
// ShellCommandable.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 30/08/2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol Runnable {
|
||||
func run(force: Bool)
|
||||
}
|
||||
|
@ -0,0 +1,46 @@
|
||||
//
|
||||
// StringsConfiguration+ShellCommandable.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 30/08/2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension StringsConfiguration: Runnable {
|
||||
func run(force: Bool) {
|
||||
var args = [String]()
|
||||
|
||||
if force {
|
||||
args += ["-f"]
|
||||
}
|
||||
|
||||
args += [
|
||||
inputFile,
|
||||
"--output-path",
|
||||
outputPath,
|
||||
"--langs",
|
||||
langs,
|
||||
"--default-lang",
|
||||
defaultLang,
|
||||
"--extension-output-path",
|
||||
extensionOutputPath
|
||||
]
|
||||
|
||||
if let extensionName = extensionName {
|
||||
args += [
|
||||
"--extension-name",
|
||||
extensionName
|
||||
]
|
||||
}
|
||||
|
||||
if let extensionSuffix = extensionSuffix {
|
||||
args += [
|
||||
"--extension-suffix",
|
||||
extensionSuffix
|
||||
]
|
||||
}
|
||||
|
||||
Stringium.main(args)
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
//
|
||||
// TagsConfiguration+ShellCommandable.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 30/08/2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension TagsConfiguration: Runnable {
|
||||
func run(force: Bool) {
|
||||
var args = [String]()
|
||||
|
||||
if force {
|
||||
args += ["-f"]
|
||||
}
|
||||
|
||||
args += [
|
||||
inputFile,
|
||||
"--lang",
|
||||
lang,
|
||||
"--extension-output-path",
|
||||
extensionOutputPath
|
||||
]
|
||||
|
||||
if let extensionName = extensionName {
|
||||
args += [
|
||||
"--extension-name",
|
||||
extensionName
|
||||
]
|
||||
}
|
||||
if let extensionSuffix = extensionSuffix {
|
||||
args += [
|
||||
"--extension-suffix",
|
||||
extensionSuffix
|
||||
]
|
||||
}
|
||||
|
||||
Tags.main(args)
|
||||
}
|
||||
}
|
@ -11,9 +11,9 @@ extension FileManager {
|
||||
func getAllRegularFileIn(directory: String) -> [String] {
|
||||
var files = [String]()
|
||||
guard let enumerator = self.enumerator(at: URL(string: directory)!, includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles, .skipsPackageDescendants]) else {
|
||||
let error = ImagiumError.unknown("Cannot enumerate file in \(directory)")
|
||||
let error = ImagesError.unknown("Cannot enumerate file in \(directory)")
|
||||
print(error.localizedDescription)
|
||||
Imagium.exit(withError: error)
|
||||
Images.exit(withError: error)
|
||||
}
|
||||
|
||||
for case let fileURL as URL in enumerator {
|
||||
@ -23,9 +23,9 @@ extension FileManager {
|
||||
files.append(fileURL.relativePath)
|
||||
}
|
||||
} catch {
|
||||
let error = ImagiumError.getFileAttributed(fileURL.relativePath, error.localizedDescription)
|
||||
let error = ImagesError.getFileAttributed(fileURL.relativePath, error.localizedDescription)
|
||||
print(error.localizedDescription)
|
||||
Imagium.exit(withError: error)
|
||||
Images.exit(withError: error)
|
||||
}
|
||||
}
|
||||
return files
|
||||
@ -34,9 +34,9 @@ extension FileManager {
|
||||
func getAllImageSetFolderIn(directory: String) -> [String] {
|
||||
var files = [String]()
|
||||
guard let enumerator = self.enumerator(at: URL(string: directory)!, includingPropertiesForKeys: [.isDirectoryKey], options: [.skipsHiddenFiles, .skipsPackageDescendants]) else {
|
||||
let error = ImagiumError.unknown("Cannot enumerate imageset directory in \(directory)")
|
||||
let error = ImagesError.unknown("Cannot enumerate imageset directory in \(directory)")
|
||||
print(error.localizedDescription)
|
||||
Imagium.exit(withError: error)
|
||||
Images.exit(withError: error)
|
||||
}
|
||||
|
||||
for case let fileURL as URL in enumerator {
|
||||
@ -46,9 +46,9 @@ extension FileManager {
|
||||
files.append(fileURL.lastPathComponent)
|
||||
}
|
||||
} catch {
|
||||
let error = ImagiumError.getFileAttributed(fileURL.relativePath, error.localizedDescription)
|
||||
let error = ImagesError.getFileAttributed(fileURL.relativePath, error.localizedDescription)
|
||||
print(error.localizedDescription)
|
||||
Imagium.exit(withError: error)
|
||||
Images.exit(withError: error)
|
||||
}
|
||||
}
|
||||
return files
|
@ -58,9 +58,9 @@ class ImageExtensionGenerator {
|
||||
do {
|
||||
try extensionContent.write(to: extensionFilePathURL, atomically: true, encoding: .utf8)
|
||||
} catch (let error) {
|
||||
let error = ImagiumError.writeFile(extensionFilePath, error.localizedDescription)
|
||||
let error = ImagesError.writeFile(extensionFilePath, error.localizedDescription)
|
||||
print(error.localizedDescription)
|
||||
Imagium.exit(withError: error)
|
||||
Images.exit(withError: error)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// File.swift
|
||||
// XcassetsGenerator.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 24/01/2022.
|
||||
@ -24,7 +24,7 @@ class XcassetsGenerator {
|
||||
|
||||
func generateXcassets(inputPath: String, imagesToGenerate: [ParsedImage], xcassetsPath: String) {
|
||||
let fileManager = FileManager()
|
||||
let svgConverter = Imagium.getSvgConverterPath()
|
||||
let svgConverter = Images.getSvgConverterPath()
|
||||
let allSubFiles = fileManager.getAllRegularFileIn(directory: inputPath)
|
||||
|
||||
var generatedAssetsPaths = [String]()
|
||||
@ -47,9 +47,9 @@ class XcassetsGenerator {
|
||||
return (subfile, "jepg")
|
||||
}
|
||||
}
|
||||
let error = ImagiumError.unknownImageExtension(parsedImage.name)
|
||||
let error = ImagesError.unknownImageExtension(parsedImage.name)
|
||||
print(error.localizedDescription)
|
||||
Imagium.exit(withError: error)
|
||||
Images.exit(withError: error)
|
||||
}()
|
||||
|
||||
// Create imageset folder
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Imagium.swift
|
||||
// Images.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 24/01/2022.
|
||||
@ -9,7 +9,7 @@ import ToolCore
|
||||
import Foundation
|
||||
import ArgumentParser
|
||||
|
||||
struct Imagium: ParsableCommand {
|
||||
struct Images: ParsableCommand {
|
||||
|
||||
// MARK: - CommandConfiguration
|
||||
|
||||
@ -20,7 +20,7 @@ struct Imagium: ParsableCommand {
|
||||
|
||||
// MARK: - Static
|
||||
|
||||
static let toolName = "Imagium"
|
||||
static let toolName = "Images"
|
||||
static let defaultExtensionName = "UIImage"
|
||||
|
||||
// MARK: - Properties
|
||||
@ -35,7 +35,7 @@ struct Imagium: ParsableCommand {
|
||||
|
||||
// MARK: - Command Options
|
||||
|
||||
@OptionGroup var options: ImagiumOptions
|
||||
@OptionGroup var options: ImagesOptions
|
||||
|
||||
// MARK: - Run
|
||||
|
||||
@ -81,13 +81,13 @@ struct Imagium: ParsableCommand {
|
||||
|
||||
// Input file
|
||||
guard fileManager.fileExists(atPath: options.inputFile) else {
|
||||
let error = ImagiumError.fileNotExists(options.inputFile)
|
||||
let error = ImagesError.fileNotExists(options.inputFile)
|
||||
print(error.localizedDescription)
|
||||
Imagium.exit(withError: error)
|
||||
Images.exit(withError: error)
|
||||
}
|
||||
|
||||
// RSVG-Converter
|
||||
_ = Imagium.getSvgConverterPath()
|
||||
_ = Images.getSvgConverterPath()
|
||||
|
||||
// Check if needed to regenerate
|
||||
guard GeneratorChecker.shouldGenerate(force: options.forceExecution, inputFilePath: options.inputFile, extensionFilePath: extensionFilePath) else {
|
||||
@ -107,10 +107,8 @@ struct Imagium: ParsableCommand {
|
||||
return taskSvgConverter.output!.removeCharacters(from: CharacterSet.whitespacesAndNewlines)
|
||||
}
|
||||
|
||||
let error = ImagiumError.rsvgConvertNotFound
|
||||
let error = ImagesError.rsvgConvertNotFound
|
||||
print(error.localizedDescription)
|
||||
Imagium.exit(withError: error)
|
||||
Images.exit(withError: error)
|
||||
}
|
||||
}
|
||||
|
||||
Imagium.main()
|
43
Sources/ResgenSwift/Images/ImagesError.swift
Normal file
43
Sources/ResgenSwift/Images/ImagesError.swift
Normal file
@ -0,0 +1,43 @@
|
||||
//
|
||||
// ImagesError.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 24/01/2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum ImagesError: Error {
|
||||
case inputFolderNotFound(String)
|
||||
case fileNotExists(String)
|
||||
case unknownImageExtension(String)
|
||||
case getFileAttributed(String, String)
|
||||
case rsvgConvertNotFound
|
||||
case writeFile(String, String)
|
||||
case unknown(String)
|
||||
|
||||
var localizedDescription: String {
|
||||
switch self {
|
||||
case .inputFolderNotFound(let inputFolder):
|
||||
return " error:[\(Images.toolName)] Input folder not found: \(inputFolder)"
|
||||
|
||||
case .fileNotExists(let filename):
|
||||
return " error:[\(Images.toolName)] File \(filename) does not exists"
|
||||
|
||||
case .unknownImageExtension(let filename):
|
||||
return " error:[\(Images.toolName)] File \(filename) have an unhandled file extension. Cannot generate image."
|
||||
|
||||
case .getFileAttributed(let filename, let errorDescription):
|
||||
return " error:[\(Images.toolName)] Getting file attributes of \(filename) failed with error: \(errorDescription)"
|
||||
|
||||
case .rsvgConvertNotFound:
|
||||
return " error:[\(Images.toolName)] Can't find rsvg-convert (can be installed with 'brew remove imagemagick && brew install imagemagick --with-librsvg')"
|
||||
|
||||
case .writeFile(let subErrorDescription, let filename):
|
||||
return " error:[\(Images.toolName)] An error occured while writing content to \(filename): \(subErrorDescription)"
|
||||
|
||||
case .unknown(let errorDescription):
|
||||
return " error:[\(Images.toolName)] Unknown error: \(errorDescription)"
|
||||
}
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
import Foundation
|
||||
import ArgumentParser
|
||||
|
||||
struct ImagiumOptions: ParsableArguments {
|
||||
struct ImagesOptions: ParsableArguments {
|
||||
@Flag(name: .customShort("f"), help: "Should force script execution")
|
||||
var forceExecution = false
|
||||
|
||||
@ -25,7 +25,7 @@ struct ImagiumOptions: ParsableArguments {
|
||||
var extensionOutputPath: String
|
||||
|
||||
@Option(help: "Extension name. If not specified, it will generate an UIImage extension. Using default extension name will generate static property.")
|
||||
var extensionName: String = Imagium.defaultExtensionName
|
||||
var extensionName: String = Images.defaultExtensionName
|
||||
|
||||
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+Image{extensionSuffix}.swift")
|
||||
var extensionSuffix: String = ""
|
@ -11,7 +11,7 @@ import CoreVideo
|
||||
|
||||
class TagsGenerator {
|
||||
static func writeExtensionFiles(sections: [Section], lang: String, tags: [String], staticVar: Bool, extensionName: String, extensionFilePath: String) {
|
||||
let extensionHeader = Self.getHeader(extensionClassname: extensionName)
|
||||
let extensionHeader = Self.getHeader(extensionClassname: extensionName, staticVar: staticVar)
|
||||
let extensionFooter = Self.getFooter()
|
||||
|
||||
let extensionContent: String = {
|
||||
@ -22,7 +22,7 @@ class TagsGenerator {
|
||||
return // Go to next section
|
||||
}
|
||||
|
||||
content += "\n\t// MARK: - \(section.name)"
|
||||
content += "\n // MARK: - \(section.name)"
|
||||
section.definitions.forEach { definition in
|
||||
if staticVar {
|
||||
content += "\n\n\(definition.getStaticProperty(forLang: lang))"
|
||||
@ -55,21 +55,19 @@ class TagsGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private static func getHeader(extensionClassname: String) -> String {
|
||||
"""
|
||||
// Generated by ResgenSwift.Strings.Tags \(ResgenSwiftVersion)
|
||||
private static func getHeader(extensionClassname: String, staticVar: Bool) -> String {
|
||||
"""
|
||||
// Generated by ResgenSwift.Strings.Tags \(ResgenSwiftVersion)
|
||||
|
||||
// typelias Tags = String
|
||||
\(staticVar ? "typelias Tags = String\n\n" : "")import UIKit
|
||||
|
||||
import UIKit
|
||||
|
||||
extension \(extensionClassname) {
|
||||
"""
|
||||
extension \(extensionClassname) {
|
||||
"""
|
||||
}
|
||||
|
||||
private static func getFooter() -> String {
|
||||
"""
|
||||
}
|
||||
"""
|
||||
"""
|
||||
}
|
||||
"""
|
||||
}
|
||||
}
|
@ -27,8 +27,8 @@ struct Stringium: ParsableCommand {
|
||||
// MARK: - Properties
|
||||
|
||||
var extensionFileName: String {
|
||||
if options.extensionSuffix.isEmpty == false {
|
||||
return "\(options.extensionName)+\(options.extensionSuffix).swift"
|
||||
if let extensionSuffix = options.extensionSuffix {
|
||||
return "\(options.extensionName)+\(extensionSuffix).swift"
|
||||
}
|
||||
return "\(options.extensionName).swift"
|
||||
}
|
||||
@ -47,8 +47,6 @@ struct Stringium: ParsableCommand {
|
||||
|
||||
// MARK: - Command options
|
||||
|
||||
// The `@OptionGroup` attribute includes the flags, options, and
|
||||
// arguments defined by another `ParsableArguments` type.
|
||||
@OptionGroup var options: StringiumOptions
|
||||
|
||||
// MARK: - Run
|
@ -34,7 +34,7 @@ struct StringiumOptions: ParsableArguments {
|
||||
var extensionName: String = Stringium.defaultExtensionName
|
||||
|
||||
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+{extensionSuffix}.swift")
|
||||
var extensionSuffix: String = ""
|
||||
var extensionSuffix: String?
|
||||
}
|
||||
|
||||
extension StringiumOptions {
|
@ -26,5 +26,5 @@ struct Strings: ParsableCommand {
|
||||
)
|
||||
}
|
||||
|
||||
Strings.main()
|
||||
//Strings.main()
|
||||
|
@ -28,8 +28,8 @@ struct Tags: ParsableCommand {
|
||||
// MARK: - Properties
|
||||
|
||||
var extensionFileName: String {
|
||||
if options.extensionSuffix.isEmpty == false {
|
||||
return "\(options.extensionName)+\(options.extensionSuffix).swift"
|
||||
if let extensionSuffix = options.extensionSuffix {
|
||||
return "\(options.extensionName)+\(extensionSuffix).swift"
|
||||
}
|
||||
return "\(options.extensionName).swift"
|
||||
}
|
||||
@ -40,8 +40,6 @@ struct Tags: ParsableCommand {
|
||||
|
||||
// MARK: - Command Options
|
||||
|
||||
// The `@OptionGroup` attribute includes the flags, options, and
|
||||
// arguments defined by another `ParsableArguments` type.
|
||||
@OptionGroup var options: TagsOptions
|
||||
|
||||
// MARK: - Run
|
@ -25,5 +25,5 @@ struct TagsOptions: ParsableArguments {
|
||||
var extensionName: String = Tags.defaultExtensionName
|
||||
|
||||
@Option(help: "Extension suffix. Ex: MyApp, it will generate {extensionName}+Tag{extensionSuffix}.swift")
|
||||
var extensionSuffix: String = ""
|
||||
var extensionSuffix: String?
|
||||
}
|
@ -33,8 +33,6 @@ struct Twine: ParsableCommand {
|
||||
|
||||
// MARK: - Command Options
|
||||
|
||||
// The `@OptionGroup` attribute includes the flags, options, and
|
||||
// arguments defined by another `ParsableArguments` type.
|
||||
@OptionGroup var options: TwineOptions
|
||||
|
||||
// MARK: - Run
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// File.swift
|
||||
// TwineOptions.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 10/01/2022.
|
@ -1 +1,35 @@
|
||||
print("Welcome ResgenSwift")
|
||||
//
|
||||
// ResgenSwift.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 13/12/2021.
|
||||
//
|
||||
|
||||
import ToolCore
|
||||
import Foundation
|
||||
import ArgumentParser
|
||||
|
||||
struct ResgenSwift: ParsableCommand {
|
||||
|
||||
static var configuration = CommandConfiguration(
|
||||
abstract: "A utility for generate ressources.",
|
||||
version: ResgenSwiftVersion,
|
||||
|
||||
// Pass an array to `subcommands` to set up a nested tree of subcommands.
|
||||
// With language support for type-level introspection, this could be
|
||||
// provided by automatically finding nested `ParsableCommand` types.
|
||||
subcommands: [
|
||||
Colors.self,
|
||||
Fonts.self,
|
||||
Images.self,
|
||||
Strings.self,
|
||||
Generate.self
|
||||
]
|
||||
|
||||
// A default subcommand, when provided, is automatically selected if a
|
||||
// subcommand is not given on the command line.
|
||||
//defaultSubcommand: Twine.self
|
||||
)
|
||||
}
|
||||
|
||||
ResgenSwift.main()
|
||||
|
@ -10,14 +10,14 @@ import Foundation
|
||||
public class Shell {
|
||||
|
||||
@discardableResult
|
||||
public static func shell(_ args: String...) -> (terminationStatus: Int32, output: String?) {
|
||||
public static func shell(launchPath: String = "/usr/bin/env", _ args: String...) -> (terminationStatus: Int32, output: String?) {
|
||||
let task = Process()
|
||||
task.launchPath = "/usr/bin/env"
|
||||
task.launchPath = launchPath
|
||||
task.arguments = args
|
||||
|
||||
let pipe = Pipe()
|
||||
task.standardOutput = pipe
|
||||
task.launch()
|
||||
try? task.run()
|
||||
task.waitUntilExit()
|
||||
|
||||
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||
@ -30,9 +30,9 @@ public class Shell {
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public static func shell(_ args: [String]) -> (terminationStatus: Int32, output: String?) {
|
||||
public static func shell(launchPath: String = "/usr/bin/env", _ args: [String]) -> (terminationStatus: Int32, output: String?) {
|
||||
let task = Process()
|
||||
task.launchPath = "/usr/bin/env"
|
||||
task.launchPath = launchPath
|
||||
task.arguments = args
|
||||
|
||||
let pipe = Pipe()
|
||||
|
Reference in New Issue
Block a user