157 lines
6.6 KiB
Swift
157 lines
6.6 KiB
Swift
//
|
|
// main.swift
|
|
//
|
|
//
|
|
// Created by Thibaut Schmitt on 20/12/2021.
|
|
//
|
|
|
|
import Foundation
|
|
import CLIToolCore
|
|
import ArgumentParser
|
|
|
|
enum ColorStyle: String, Decodable {
|
|
case light
|
|
case all
|
|
}
|
|
|
|
struct ColorTool: ParsableCommand {
|
|
static let defaultExtensionName = "UIColor"
|
|
static let assetsColorsFolderName = "Colors"
|
|
|
|
@OptionGroup var options: ColorToolOptions
|
|
|
|
var colorStyle: ColorStyle { ColorStyle(rawValue: options.style) ?? .all }
|
|
var extensionFileName: String { "\(options.extensionName)+\(options.extensionSuffix).swift" }
|
|
var extensionFilePath: String { "\(options.extensionOutputPath)/\(extensionFileName)" }
|
|
|
|
public func run() throws {
|
|
print("[ColorTool] Starting colors generation")
|
|
|
|
print("[ColorTool] Will use inputFile \(options.inputFile) to generate \(colorStyle) colors in xcassets \(options.xcassetsPath)")
|
|
print("[ColorTool] Extension will be \(extensionFilePath)")
|
|
|
|
// Check requirements
|
|
let fileManager = FileManager()
|
|
guard fileManager.fileExists(atPath: options.xcassetsPath) else {
|
|
let error = ColorToolError.fileNotExists(options.xcassetsPath)
|
|
print(error.localizedDescription)
|
|
ColorTool.exit(withError: error)
|
|
}
|
|
guard fileManager.fileExists(atPath: options.inputFile) else {
|
|
let error = ColorToolError.fileNotExists(options.inputFile)
|
|
print(error.localizedDescription)
|
|
ColorTool.exit(withError: error)
|
|
}
|
|
|
|
// Check if needed to regenerate
|
|
guard GeneratorChecker.shouldGenerate(force: options.forceGeneration, inputFilePath: options.inputFile, extensionFilePath: extensionFilePath) else {
|
|
print("[ColorTool] Colors are already up to date :) ")
|
|
return
|
|
}
|
|
print("[ColorTool] Will generate colors")
|
|
|
|
// Delete current colors
|
|
Shell.shell("rm", "-rf", "\(options.xcassetsPath)/Colors/*")
|
|
|
|
// Get colors
|
|
let colorsToGen = getColorsGen()
|
|
|
|
// Generate all colors in xcassets
|
|
let colorAssetHelper = ColorXcassetHelper(xcassetsPath: options.xcassetsPath, colors: colorsToGen)
|
|
colorAssetHelper.generateXcassetColors()
|
|
|
|
// Generate extension
|
|
let extensionGenerator = ColorExtensionGenerator(colors: colorsToGen,
|
|
extensionClassname: options.extensionName,
|
|
isUIColorExtension: isUIColorExtension())
|
|
let extensionHeader = extensionGenerator.getHeader()
|
|
let extensionProperties = extensionGenerator.getProperties()
|
|
let extensionFooter = extensionGenerator.getFooter()
|
|
|
|
generateExtensionFile(extensionHeader, extensionProperties, extensionFooter)
|
|
|
|
print("[ColorTool] Colors generated")
|
|
}
|
|
|
|
private func generateExtensionFile(_ args: String...) {
|
|
// Create file if not exists
|
|
let fileManager = FileManager()
|
|
if fileManager.fileExists(atPath: extensionFilePath) == false {
|
|
Shell.shell("touch", "\(extensionFilePath)")
|
|
}
|
|
|
|
// Create extension content
|
|
let extensionContent = args.joined(separator: "\n")
|
|
|
|
// Write content
|
|
let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
|
|
do {
|
|
try extensionContent.write(to: extensionFilePathURL, atomically: true, encoding: .utf8)
|
|
} catch (let error) {
|
|
let error = ColorToolError.writeExtension(extensionFilePath, error.localizedDescription)
|
|
print(error.localizedDescription)
|
|
ColorTool.exit(withError: error)
|
|
}
|
|
}
|
|
|
|
private func getColorsGen() -> [GenColor] {
|
|
// Get content of input file
|
|
let inputFileContent = try! String(contentsOfFile: options.inputFile, encoding: .utf8)
|
|
let colorsByLines = inputFileContent.components(separatedBy: CharacterSet.newlines)
|
|
|
|
// Iterate on each line of input file
|
|
return colorsByLines.enumerated().compactMap { lineNumber, colorLine in
|
|
// Required format:
|
|
// colorName="#RGB/#ARGB", colorName "#RGB/#ARGB", colorName "#RGB/#ARGB" "#RGB/#ARGB"
|
|
let colorLineCleanedUp = colorLine
|
|
.removeTrailingWhitespace()
|
|
.replacingOccurrences(of: "=", with: "") // Keep compat with current file format
|
|
|
|
guard colorLineCleanedUp.hasPrefix("#") == false, colorLineCleanedUp.isEmpty == false else {
|
|
print("[ColorTool] ⚠️ 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)
|
|
print(error.localizedDescription)
|
|
ColorTool.exit(withError: error)
|
|
}
|
|
|
|
switch colorStyle {
|
|
case .light:
|
|
return GenColor(name: String(colorContent[0]), light: String(colorContent[1]), dark: String(colorContent[1]))
|
|
|
|
case .all:
|
|
if colorContent.count == 3 {
|
|
return GenColor(name: String(colorContent[0]), light: String(colorContent[1]), dark: String(colorContent[2]))
|
|
}
|
|
return GenColor(name: String(colorContent[0]), light: String(colorContent[1]), dark: String(colorContent[1]))
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Helpers
|
|
|
|
private func isUIColorExtension() -> Bool {
|
|
options.extensionName == Self.defaultExtensionName
|
|
}
|
|
}
|
|
|
|
ColorTool.main()
|
|
|
|
/*
|
|
Command samples:
|
|
|
|
1. UIColor extension without suffix
|
|
swift run -c release ColorToolCore -f ./SampleFiles/Colors/sampleColors1.txt --style all --xcassets-path "./SampleFiles/Colors/colors.xcassets" --extension-output-path "./SampleFiles/Colors/Generated/" --extension-name "UIColor"
|
|
|
|
2. UIColor extension with custom suffix
|
|
swift run -c release ColorToolCore -f ./SampleFiles/Colors/sampleColors1.txt --style all --xcassets-path "./SampleFiles/Colors/colors.xcassets" --extension-output-path "./SampleFiles/Colors/Generated/" --extension-name "UIColor" --extension-suffix "SampleApp"
|
|
|
|
3. Custom extension with only light theme colors (R2Color)
|
|
swift run -c release ColorToolCore -f ./SampleFiles/Colors/sampleColors1.txt --style light --xcassets-path "./SampleFiles/Colors/colors.xcassets" --extension-output-path "./SampleFiles/Colors/Generated/" --extension-name "R2Color"
|
|
*/
|