Command line to generate R2Font
This commit is contained in:
31
Sources/CLIToolCore/CLIToolCore.swift
Normal file
31
Sources/CLIToolCore/CLIToolCore.swift
Normal file
@ -0,0 +1,31 @@
|
||||
//
|
||||
// CLIToolCore.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 13/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)
|
||||
}
|
||||
}
|
26
Sources/FontToolCore/Extensions.swift
Normal file
26
Sources/FontToolCore/Extensions.swift
Normal file
@ -0,0 +1,26 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 13/12/2021.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension String {
|
||||
func removeCharacters(from forbiddenChars: CharacterSet) -> String {
|
||||
let passed = self.unicodeScalars.filter { !forbiddenChars.contains($0) }
|
||||
return String(String.UnicodeScalarView(passed))
|
||||
}
|
||||
|
||||
func removeCharacters(from: String) -> String {
|
||||
return removeCharacters(from: CharacterSet(charactersIn: from))
|
||||
}
|
||||
}
|
||||
|
||||
extension Sequence where Iterator.Element: Hashable {
|
||||
func unique() -> [Iterator.Element] {
|
||||
var seen: [Iterator.Element: Bool] = [:]
|
||||
return self.filter { seen.updateValue(true, forKey: $0) == nil }
|
||||
}
|
||||
}
|
59
Sources/FontToolCore/FontToolContentGenerator.swift
Normal file
59
Sources/FontToolCore/FontToolContentGenerator.swift
Normal file
@ -0,0 +1,59 @@
|
||||
//
|
||||
// FontToolContentGenerator.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 13/12/2021.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class FontToolContentGenerator {
|
||||
|
||||
static func getExtensionHeader(fontsNames: [String]) -> String {
|
||||
"""
|
||||
// Generated from FontToolCore
|
||||
// \(fontsNames.joined(separator: " "))
|
||||
|
||||
import UIKit
|
||||
|
||||
"""
|
||||
}
|
||||
|
||||
static func getFontNameEnum(fontsNames: [String]) -> String {
|
||||
var enumDefinition = "\tenum FontName: String {"
|
||||
|
||||
fontsNames.forEach {
|
||||
//debugPrint("Name: \($0.removeCharacters(from: "[]+-_"))")
|
||||
enumDefinition += "\t\tcase \($0.removeCharacters(from: "[]+-_")) = \"\($0)\"\n"
|
||||
}
|
||||
enumDefinition += "\t}\n"
|
||||
|
||||
return enumDefinition
|
||||
}
|
||||
|
||||
static func getFontMethods(fontsNames: [String], isUIFontExtension: Bool) -> String {
|
||||
var methods = "\t// MARK: - Getter\n"
|
||||
|
||||
fontsNames
|
||||
.unique()
|
||||
.forEach {
|
||||
let fontNameSanitize = $0.removeCharacters(from: "[]+-_")
|
||||
|
||||
if isUIFontExtension {
|
||||
methods += """
|
||||
\n\tstatic let \(fontNameSanitize): ((_ size: CGFloat) -> UIFont) = { size in
|
||||
\tUIFont(name: FontName.\(fontNameSanitize).rawValue, size: size)!
|
||||
\t}\n
|
||||
"""
|
||||
} else {
|
||||
methods += """
|
||||
\n\tfunc \(fontNameSanitize)(withSize size: CGFloat) -> UIFont {
|
||||
\tUIFont(name: FontName.\(fontNameSanitize).rawValue, size: size)!
|
||||
\t}\n
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
return methods
|
||||
}
|
||||
}
|
27
Sources/FontToolCore/FontToolError.swift
Normal file
27
Sources/FontToolCore/FontToolError.swift
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 13/12/2021.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
enum FontToolError: Error {
|
||||
case fcScan(String, Int32, String?)
|
||||
case inputFolderNotFound(String)
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .fcScan(let path, let code, let output):
|
||||
return """
|
||||
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 "Input folder not found: \(inputFolder)"
|
||||
}
|
||||
}
|
||||
}
|
48
Sources/FontToolCore/FontToolHelper.swift
Normal file
48
Sources/FontToolCore/FontToolHelper.swift
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// FontToolHelper.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 13/12/2021.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CLIToolCore
|
||||
|
||||
class FontToolHelper {
|
||||
static func getFontsData(fromInputFolder inputFolder: String) -> (fontsNames: [String], fontsFileNames: [String]) {
|
||||
// Get a enumerator for all files
|
||||
let fileManager = FileManager()
|
||||
|
||||
guard fileManager.fileExists(atPath: inputFolder) else {
|
||||
FontTool.exit(withError: FontToolError.fcScan(path, task.terminationStatus, task.output))
|
||||
}
|
||||
|
||||
let enumerator: FileManager.DirectoryEnumerator = fileManager.enumerator(atPath: inputFolder)!
|
||||
|
||||
// Filters font files
|
||||
let fontsFileNames: [String] = (enumerator.allObjects as! [String])
|
||||
.filter {
|
||||
if $0.hasSuffix(".ttf") || $0.hasSuffix(".otf") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
private static func getFontName(atPath path: String) -> String {
|
||||
//print("fc-scan --format %{postscriptname} \(path)")
|
||||
// Get real font name
|
||||
let task = Shell.shell("fc-scan", "--format", "%{postscriptname}", path)
|
||||
|
||||
guard let fontName = task.output, task.terminationStatus == 0 else {
|
||||
FontTool.exit(withError: FontToolError.fcScan(path, task.terminationStatus, task.output))
|
||||
}
|
||||
|
||||
return fontName
|
||||
}
|
||||
}
|
69
Sources/FontToolCore/main.swift
Normal file
69
Sources/FontToolCore/main.swift
Normal file
@ -0,0 +1,69 @@
|
||||
//
|
||||
// FontTool.swift
|
||||
//
|
||||
//
|
||||
// Created by Thibaut Schmitt on 13/12/2021.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CLIToolCore
|
||||
import ArgumentParser
|
||||
|
||||
struct FontTool: ParsableCommand {
|
||||
static let defaultExtensionName = "UIFont"
|
||||
|
||||
@Argument(help: "Input folder where fonts to generate are.")
|
||||
var inputFolder: String
|
||||
|
||||
@Option(help: "Path where to generate the extension.")
|
||||
var extensionOutputPath: String
|
||||
|
||||
@Option(help: "Extension name. If not specified, it will generate an UIFont extension")
|
||||
var extensionName: String = Self.defaultExtensionName
|
||||
|
||||
public func run() throws {
|
||||
print("[FontTool] Starting font generation")
|
||||
|
||||
let fontsData = FontToolHelper.getFontsData(fromInputFolder: inputFolder)
|
||||
|
||||
let extensionHeader = FontToolContentGenerator.getExtensionHeader(fontsNames: fontsData.fontsNames)
|
||||
let extensionDefinitionOpening = "extension \(extensionName) {\n"
|
||||
let extensionFontsNamesEnum = FontToolContentGenerator.getFontNameEnum(fontsNames: fontsData.fontsNames)
|
||||
let extensionFontsMethods = FontToolContentGenerator.getFontMethods(fontsNames: fontsData.fontsNames, isUIFontExtension: isUIFontExtension())
|
||||
let extensionDefinitionClosing = "}"
|
||||
|
||||
generateExtensionFile(extensionHeader,
|
||||
extensionDefinitionOpening,
|
||||
extensionFontsNamesEnum,
|
||||
extensionFontsMethods,
|
||||
extensionDefinitionClosing)
|
||||
|
||||
print("[FontTool] Font generated")
|
||||
}
|
||||
|
||||
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 {
|
||||
Shell.shell("touch", "\(extensionFilePath)")
|
||||
}
|
||||
|
||||
// Create extension content
|
||||
let extensionContent = args.joined(separator: "\n")
|
||||
|
||||
// Write content
|
||||
let extensionFilePathURL = URL(fileURLWithPath: extensionFilePath)
|
||||
try! extensionContent.write(to: extensionFilePathURL, atomically: true, encoding: .utf8)
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
private func isUIFontExtension() -> Bool {
|
||||
extensionName == Self.defaultExtensionName
|
||||
}
|
||||
}
|
||||
|
||||
FontTool.main()
|
1
Sources/ResgenSwift/main.swift
Normal file
1
Sources/ResgenSwift/main.swift
Normal file
@ -0,0 +1 @@
|
||||
print("Welcome ResgenSwift")
|
Reference in New Issue
Block a user