From 780efc8817ab4a174ed71415224110573a94902c Mon Sep 17 00:00:00 2001 From: Thibaut Schmitt Date: Wed, 22 Dec 2021 10:28:38 +0100 Subject: [PATCH] Add checker class to check if generation of font are required + Split CLIToolCore in multiple file (one by class) --- ...R2Color+Font.swift => R2Color+Color.swift} | 2 +- ...UIColor+Font.swift => UIColor+Color.swift} | 0 ...App.swift => UIColor+ColorSampleApp.swift} | 0 SampleFiles/Fonts/Generated/R2Font+Font.swift | 63 +++++++++++++++++++ SampleFiles/Fonts/Generated/UIFont+Font.swift | 63 +++++++++++++++++++ ...IToolCore.swift => GeneratorChecker.swift} | 27 +------- Sources/CLIToolCore/Shell.swift | 31 +++++++++ Sources/ColorToolCore/main.swift | 2 +- .../FontToolContentGenerator.swift | 2 +- Sources/FontToolCore/FontToolHelper.swift | 10 +-- .../FontToolCore/GeneratorFontChecker.swift | 49 +++++++++++++++ Sources/FontToolCore/main.swift | 42 ++++++++++--- 12 files changed, 251 insertions(+), 40 deletions(-) rename SampleFiles/Colors/Generated/{R2Color+Font.swift => R2Color+Color.swift} (88%) rename SampleFiles/Colors/Generated/{UIColor+Font.swift => UIColor+Color.swift} (100%) rename SampleFiles/Colors/Generated/{UIColor+FontSampleApp.swift => UIColor+ColorSampleApp.swift} (100%) create mode 100644 SampleFiles/Fonts/Generated/R2Font+Font.swift create mode 100644 SampleFiles/Fonts/Generated/UIFont+Font.swift rename Sources/CLIToolCore/{CLIToolCore.swift => GeneratorChecker.swift} (64%) create mode 100644 Sources/CLIToolCore/Shell.swift create mode 100644 Sources/FontToolCore/GeneratorFontChecker.swift diff --git a/SampleFiles/Colors/Generated/R2Color+Font.swift b/SampleFiles/Colors/Generated/R2Color+Color.swift similarity index 88% rename from SampleFiles/Colors/Generated/R2Color+Font.swift rename to SampleFiles/Colors/Generated/R2Color+Color.swift index 516ec44..1d10e7b 100644 --- a/SampleFiles/Colors/Generated/R2Color+Font.swift +++ b/SampleFiles/Colors/Generated/R2Color+Color.swift @@ -1,4 +1,4 @@ -// Generated from ColorToolCore at 2021-12-20 15:27:15 +0000 +// Generated from ColorToolCore at 2021-12-20 15:34:55 +0000 import UIKit diff --git a/SampleFiles/Colors/Generated/UIColor+Font.swift b/SampleFiles/Colors/Generated/UIColor+Color.swift similarity index 100% rename from SampleFiles/Colors/Generated/UIColor+Font.swift rename to SampleFiles/Colors/Generated/UIColor+Color.swift diff --git a/SampleFiles/Colors/Generated/UIColor+FontSampleApp.swift b/SampleFiles/Colors/Generated/UIColor+ColorSampleApp.swift similarity index 100% rename from SampleFiles/Colors/Generated/UIColor+FontSampleApp.swift rename to SampleFiles/Colors/Generated/UIColor+ColorSampleApp.swift diff --git a/SampleFiles/Fonts/Generated/R2Font+Font.swift b/SampleFiles/Fonts/Generated/R2Font+Font.swift new file mode 100644 index 0000000..5891e12 --- /dev/null +++ b/SampleFiles/Fonts/Generated/R2Font+Font.swift @@ -0,0 +1,63 @@ +// Lato/Lato-Italic.ttf Lato/Lato-LightItalic.ttf Lato/Lato-Thin.ttf Lato/Lato-Bold.ttf Lato/Lato-Black.ttf Lato/Lato-Regular.ttf Lato/Lato-BlackItalic.ttf Lato/Lato-BoldItalic.ttf Lato/Lato-Light.ttf Lato/Lato-ThinItalic.ttf +// Generated from FontToolCore + +import UIKit + +extension R2Font { + + enum FontName: String { + case LatoItalic = "Lato-Italic" + case LatoLightItalic = "Lato-LightItalic" + case LatoHairline = "Lato-Hairline" + case LatoBold = "Lato-Bold" + case LatoBlack = "Lato-Black" + case LatoRegular = "Lato-Regular" + case LatoBlackItalic = "Lato-BlackItalic" + case LatoBoldItalic = "Lato-BoldItalic" + case LatoLight = "Lato-Light" + case LatoHairlineItalic = "Lato-HairlineItalic" + } + + // MARK: - Getter + + func LatoItalic(withSize size: CGFloat) -> UIFont { + UIFont(name: FontName.LatoItalic.rawValue, size: size)! + } + + func LatoLightItalic(withSize size: CGFloat) -> UIFont { + UIFont(name: FontName.LatoLightItalic.rawValue, size: size)! + } + + func LatoHairline(withSize size: CGFloat) -> UIFont { + UIFont(name: FontName.LatoHairline.rawValue, size: size)! + } + + func LatoBold(withSize size: CGFloat) -> UIFont { + UIFont(name: FontName.LatoBold.rawValue, size: size)! + } + + func LatoBlack(withSize size: CGFloat) -> UIFont { + UIFont(name: FontName.LatoBlack.rawValue, size: size)! + } + + func LatoRegular(withSize size: CGFloat) -> UIFont { + UIFont(name: FontName.LatoRegular.rawValue, size: size)! + } + + func LatoBlackItalic(withSize size: CGFloat) -> UIFont { + UIFont(name: FontName.LatoBlackItalic.rawValue, size: size)! + } + + func LatoBoldItalic(withSize size: CGFloat) -> UIFont { + UIFont(name: FontName.LatoBoldItalic.rawValue, size: size)! + } + + func LatoLight(withSize size: CGFloat) -> UIFont { + UIFont(name: FontName.LatoLight.rawValue, size: size)! + } + + func LatoHairlineItalic(withSize size: CGFloat) -> UIFont { + UIFont(name: FontName.LatoHairlineItalic.rawValue, size: size)! + } + +} \ No newline at end of file diff --git a/SampleFiles/Fonts/Generated/UIFont+Font.swift b/SampleFiles/Fonts/Generated/UIFont+Font.swift new file mode 100644 index 0000000..627da99 --- /dev/null +++ b/SampleFiles/Fonts/Generated/UIFont+Font.swift @@ -0,0 +1,63 @@ +// Lato/Lato-Italic.ttf Lato/Lato-LightItalic.ttf Lato/Lato-Thin.ttf Lato/Lato-Bold.ttf Lato/Lato-Black.ttf Lato/Lato-Regular.ttf Lato/Lato-BlackItalic.ttf Lato/Lato-BoldItalic.ttf Lato/Lato-Light.ttf Lato/Lato-ThinItalic.ttf +// Generated from FontToolCore + +import UIKit + +extension UIFont { + + enum FontName: String { + case LatoItalic = "Lato-Italic" + case LatoLightItalic = "Lato-LightItalic" + case LatoHairline = "Lato-Hairline" + case LatoBold = "Lato-Bold" + case LatoBlack = "Lato-Black" + case LatoRegular = "Lato-Regular" + case LatoBlackItalic = "Lato-BlackItalic" + case LatoBoldItalic = "Lato-BoldItalic" + case LatoLight = "Lato-Light" + case LatoHairlineItalic = "Lato-HairlineItalic" + } + + // MARK: - Getter + + static let LatoItalic: ((_ size: CGFloat) -> UIFont) = { size in + UIFont(name: FontName.LatoItalic.rawValue, size: size)! + } + + static let LatoLightItalic: ((_ size: CGFloat) -> UIFont) = { size in + UIFont(name: FontName.LatoLightItalic.rawValue, size: size)! + } + + static let LatoHairline: ((_ size: CGFloat) -> UIFont) = { size in + UIFont(name: FontName.LatoHairline.rawValue, size: size)! + } + + static let LatoBold: ((_ size: CGFloat) -> UIFont) = { size in + UIFont(name: FontName.LatoBold.rawValue, size: size)! + } + + static let LatoBlack: ((_ size: CGFloat) -> UIFont) = { size in + UIFont(name: FontName.LatoBlack.rawValue, size: size)! + } + + static let LatoRegular: ((_ size: CGFloat) -> UIFont) = { size in + UIFont(name: FontName.LatoRegular.rawValue, size: size)! + } + + static let LatoBlackItalic: ((_ size: CGFloat) -> UIFont) = { size in + UIFont(name: FontName.LatoBlackItalic.rawValue, size: size)! + } + + static let LatoBoldItalic: ((_ size: CGFloat) -> UIFont) = { size in + UIFont(name: FontName.LatoBoldItalic.rawValue, size: size)! + } + + static let LatoLight: ((_ size: CGFloat) -> UIFont) = { size in + UIFont(name: FontName.LatoLight.rawValue, size: size)! + } + + static let LatoHairlineItalic: ((_ size: CGFloat) -> UIFont) = { size in + UIFont(name: FontName.LatoHairlineItalic.rawValue, size: size)! + } + +} \ No newline at end of file diff --git a/Sources/CLIToolCore/CLIToolCore.swift b/Sources/CLIToolCore/GeneratorChecker.swift similarity index 64% rename from Sources/CLIToolCore/CLIToolCore.swift rename to Sources/CLIToolCore/GeneratorChecker.swift index ab5f5c3..858f7af 100644 --- a/Sources/CLIToolCore/CLIToolCore.swift +++ b/Sources/CLIToolCore/GeneratorChecker.swift @@ -1,35 +1,12 @@ // -// CLIToolCore.swift +// GeneratorChecker.swift // // -// Created by Thibaut Schmitt on 13/12/2021. +// Created by Thibaut Schmitt on 22/12/2021. // import Foundation -public class Shell { - - @discardableResult - public static func shell(_ args: String...) -> (terminationStatus: Int32, output: String?) { - let task = Process() - task.launchPath = "/usr/bin/env" - task.arguments = args - - let pipe = Pipe() - task.standardOutput = pipe - task.launch() - task.waitUntilExit() - - let data = pipe.fileHandleForReading.readDataToEndOfFile() - - guard let output: String = String(data: data, encoding: .utf8) else { - return (terminationStatus: task.terminationStatus, output: nil) - } - - return (terminationStatus: task.terminationStatus, output: output) - } -} - public class GeneratorChecker { /// Return `true` if inputFile is newer than extensionFile, otherwise `false` diff --git a/Sources/CLIToolCore/Shell.swift b/Sources/CLIToolCore/Shell.swift new file mode 100644 index 0000000..40ffbbe --- /dev/null +++ b/Sources/CLIToolCore/Shell.swift @@ -0,0 +1,31 @@ +// +// File.swift +// +// +// Created by Thibaut Schmitt on 22/12/2021. +// + +import Foundation + +public class Shell { + + @discardableResult + public static func shell(_ args: String...) -> (terminationStatus: Int32, output: String?) { + let task = Process() + task.launchPath = "/usr/bin/env" + task.arguments = args + + let pipe = Pipe() + task.standardOutput = pipe + task.launch() + task.waitUntilExit() + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + + guard let output: String = String(data: data, encoding: .utf8) else { + return (terminationStatus: task.terminationStatus, output: nil) + } + + return (terminationStatus: task.terminationStatus, output: output) + } +} diff --git a/Sources/ColorToolCore/main.swift b/Sources/ColorToolCore/main.swift index 624b3e6..9757119 100644 --- a/Sources/ColorToolCore/main.swift +++ b/Sources/ColorToolCore/main.swift @@ -40,7 +40,7 @@ struct ColorTool: ParsableCommand { var extensionSuffix: String = "" var colorStyle: ColorStyle { ColorStyle(rawValue: style) ?? .all } - var extensionFileName: String { "\(extensionName)+Font\(extensionSuffix).swift" } + var extensionFileName: String { "\(extensionName)+Color\(extensionSuffix).swift" } var extensionFilePath: String { "\(extensionOutputPath)/\(extensionFileName)" } public func run() throws { diff --git a/Sources/FontToolCore/FontToolContentGenerator.swift b/Sources/FontToolCore/FontToolContentGenerator.swift index b937ef4..bdba759 100644 --- a/Sources/FontToolCore/FontToolContentGenerator.swift +++ b/Sources/FontToolCore/FontToolContentGenerator.swift @@ -11,8 +11,8 @@ class FontToolContentGenerator { static func getExtensionHeader(fontsNames: [String]) -> String { """ - // Generated from FontToolCore // \(fontsNames.joined(separator: " ")) + // Generated from FontToolCore import UIKit diff --git a/Sources/FontToolCore/FontToolHelper.swift b/Sources/FontToolCore/FontToolHelper.swift index bca755a..7b1fddf 100644 --- a/Sources/FontToolCore/FontToolHelper.swift +++ b/Sources/FontToolCore/FontToolHelper.swift @@ -9,7 +9,7 @@ import Foundation import CLIToolCore class FontToolHelper { - static func getFontsData(fromInputFolder inputFolder: String) -> (fontsNames: [String], fontsFileNames: [String]) { + static func getFontsFilenames(fromInputFolder inputFolder: String) -> [String] { // Get a enumerator for all files let fileManager = FileManager() @@ -28,10 +28,12 @@ class FontToolHelper { return false } + return fontsFileNames + } + + static func getFontsNames(fontsFileNames: [String]) -> [String] { // Get font name (font name and font file name can be different) - let fontsNames = fontsFileNames.compactMap { getFontName(atPath: "\(inputFolder)/\($0)") } - - return (fontsNames: fontsNames, fontsFileNames: fontsFileNames) + fontsFileNames.compactMap { getFontName(atPath: $0) } } private static func getFontName(atPath path: String) -> String { diff --git a/Sources/FontToolCore/GeneratorFontChecker.swift b/Sources/FontToolCore/GeneratorFontChecker.swift new file mode 100644 index 0000000..78f11c8 --- /dev/null +++ b/Sources/FontToolCore/GeneratorFontChecker.swift @@ -0,0 +1,49 @@ +// +// GeneratorFontCheck.swift +// +// +// Created by Thibaut Schmitt on 22/12/2021. +// + +import Foundation + +class GeneratorFontChecker { + + /// Will check if first line contains exactly all font filenames and nothinf more + static func shouldGenerate(force: Bool, inputFilenames: [String], extensionFilePath: String) -> Bool { + guard force == false else { + return true + } + + let fileManager = FileManager() + guard fileManager.fileExists(atPath: extensionFilePath) else { + return true + } + + let extensionFileContent = try! String(contentsOfFile: extensionFilePath, encoding: .utf8) + + guard let extensionComparableLine = extensionFileContent.components(separatedBy: .newlines).first else { + // First line to compare unavailable -> force generation + return true + } + + let extensionFontNames: [String] = extensionComparableLine + .split(separator: " ") + .dropFirst() + .map { String($0) } + + // If count is different, some fonts has been added or removed + if inputFilenames.count != extensionFontNames.count { + return true + } + + // Same number of elements, check if all fonts to generate has been already generated in extension + for inputFile in inputFilenames { + if extensionFontNames.contains(inputFile) == false { + return true + } + } + + return false + } +} diff --git a/Sources/FontToolCore/main.swift b/Sources/FontToolCore/main.swift index eedaf85..7447583 100644 --- a/Sources/FontToolCore/main.swift +++ b/Sources/FontToolCore/main.swift @@ -17,6 +17,9 @@ import ArgumentParser struct FontTool: ParsableCommand { static let defaultExtensionName = "UIFont" + @Flag(name: .customShort("f"), help: "Should force generation") + var forceGeneration = false + @Argument(help: "Input folder where fonts to generate are.") var inputFolder: String @@ -26,15 +29,31 @@ struct FontTool: ParsableCommand { @Option(help: "Extension name. If not specified, it will generate an UIFont extension") var extensionName: String = Self.defaultExtensionName + var extensionFileName: String { "\(extensionName)+Font.swift" } + var extensionFilePath: String { "\(extensionOutputPath)/\(extensionFileName)" } + public func run() throws { print("[FontTool] Starting fonts generation") - let fontsData = FontToolHelper.getFontsData(fromInputFolder: inputFolder) - let extensionHeader = FontToolContentGenerator.getExtensionHeader(fontsNames: fontsData.fontsNames) + let fontsFilenames = FontToolHelper.getFontsFilenames(fromInputFolder: inputFolder) + + // Check if needed to regenerate + guard GeneratorFontChecker.shouldGenerate(force: forceGeneration, inputFilenames: fontsFilenames, extensionFilePath: extensionFilePath) else { + print("[FontTool] Fonts are already up to date :) ") + return + } + print("[FontTool] Will generate fonts") + + let fontsFilesnamesWithPath = fontsFilenames.map { "\(inputFolder)/\($0)" } + let fontsNames = FontToolHelper.getFontsNames(fontsFileNames: fontsFilesnamesWithPath) + + // Adding fontsFilenames to header (ex: path/to/font.ttf) to make check of regeneration faster + let extensionHeader = FontToolContentGenerator.getExtensionHeader(fontsNames: fontsFilenames) + let extensionDefinitionOpening = "extension \(extensionName) {\n" - let extensionFontsNamesEnum = FontToolContentGenerator.getFontNameEnum(fontsNames: fontsData.fontsNames) - let extensionFontsMethods = FontToolContentGenerator.getFontMethods(fontsNames: fontsData.fontsNames, isUIFontExtension: isUIFontExtension()) + let extensionFontsNamesEnum = FontToolContentGenerator.getFontNameEnum(fontsNames: fontsNames) + let extensionFontsMethods = FontToolContentGenerator.getFontMethods(fontsNames: fontsNames, isUIFontExtension: isUIFontExtension()) let extensionDefinitionClosing = "}" generateExtensionFile(extensionHeader, @@ -44,15 +63,12 @@ struct FontTool: ParsableCommand { extensionDefinitionClosing) print("Info.plist information:") - print("\(generatePlistUIAppFonts(fontsNames: fontsData.fontsNames))") + print("\(generatePlistUIAppFonts(fontsNames: fontsNames))") print("[FontTool] Fonts generated") } private func generateExtensionFile(_ args: String...) { - // Create output path - let extensionFilePath = "\(extensionOutputPath)/\(extensionName)+Font.swift" - // Create file if not exists let fileManager = FileManager() if fileManager.fileExists(atPath: extensionFilePath) == false { @@ -86,3 +102,13 @@ struct FontTool: ParsableCommand { } FontTool.main() + +/* + + 1. R2Font extension + swift run -c release FontToolCore ./SampleFiles/Fonts --extension-output-path ./SampleFiles/Fonts/Generated --extension-name R2Font + + 1. UIFont defualt extension (will gen static property) + swift run -c release FontToolCore ./SampleFiles/Fonts --extension-output-path ./SampleFiles/Fonts/Generated + + */