v1.0 #1

Merged
t.schmitt merged 10 commits from v1.0 into master 2022-10-17 11:24:27 +02:00
61 changed files with 1238 additions and 400 deletions
Showing only changes of commit e9bc779da6 - Show all commits

View File

@ -246,4 +246,18 @@ tags: []
...
```
### Usage
If you **don't** install ResgenSwift:
```sh
swift run -c release ResgenSwift generate path/to/configuration.yml --project-directory ${PROJECT_DIR}
```
If you install ResgenSwift:
```sh
resgen-swift generate path/to/configuration.yml --project-directory ${PROJECT_DIR}
```
> ⚠️ Every path in `configuration.yml` will be prepended by content of `--project-directory` if they are relative path (not starting with `/`)

View File

@ -92,7 +92,7 @@ struct Colors: ParsableCommand {
// MARK: - Helpers
private func deleteCurrentColors() {
Shell.shell("rm", "-rf", "\(options.xcassetsPath)/Colors/*")
Shell.shell(["rm", "-rf", "\(options.xcassetsPath)/Colors/*"])
}
}

View File

@ -17,7 +17,7 @@ struct ColorExtensionGenerator {
// Create file if not exists
let fileManager = FileManager()
if fileManager.fileExists(atPath: extensionFilePath) == false {
Shell.shell("touch", "\(extensionFilePath)")
Shell.shell(["touch", "\(extensionFilePath)"])
}
// Create extension content

View File

@ -20,11 +20,12 @@ struct ColorXcassetHelper {
private static func generateColorSetAssets(from color: ParsedColor, to xcassetsPath: String) {
// Create ColorSet
let colorSetPath = "\(xcassetsPath)/Colors/\(color.name).colorset"
Shell.shell("mkdir", "-p", "\(colorSetPath)")
Shell.shell(["mkdir",
"-p", "\(colorSetPath)"])
// Create Contents.json in ColorSet
let contentsJsonPath = "\(colorSetPath)/Contents.json"
Shell.shell("touch", "\(contentsJsonPath)")
Shell.shell(["touch", "\(contentsJsonPath)"])
// Write content in Contents.json
let contentsJsonPathURL = URL(fileURLWithPath: contentsJsonPath)

View File

@ -60,7 +60,7 @@ class FontsToolHelper {
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)
let task = Shell.shell(["fc-scan", "--format", "%{postscriptname}", path])
guard let fontName = task.output, task.terminationStatus == 0 else {
let error = FontsToolError.fcScan(path, task.terminationStatus, task.output)

View File

@ -14,7 +14,7 @@ class FontExtensionGenerator {
// Check file if not exists
let fileManager = FileManager()
if fileManager.fileExists(atPath: extensionFilePath) == false {
Shell.shell("touch", "\(extensionFilePath)")
Shell.shell(["touch", "\(extensionFilePath)"])
}
// Create extension content

View File

@ -0,0 +1,18 @@
//
// StringExtensions.swift
//
//
// Created by Thibaut Schmitt on 31/08/2022.
//
import Foundation
extension String {
func prependIfRelativePath(_ prependPath: String) -> String {
if self.hasPrefix("/") {
return self
}
return prependPath + self
}
}

View File

@ -40,13 +40,17 @@ struct Generate: ParsableCommand {
print(" - \(configuration.strings.count) strings configuration")
print(" - \(configuration.tags.count) tags configuration")
print()
print("Input file: \(configuration.colors.first?.inputFile ?? "no input file")")
// Execute commands
configuration.runnableConfigurations
.forEach {
$0.run(force: options.forceGeneration)
$0.run(projectDirectory: options.projectDirectory,
force: options.forceGeneration)
print("\n")
}
print("[\(Self.toolName)] Resgen ended")
}
}

View File

@ -16,4 +16,13 @@ struct GenerateOptions: ParsableArguments {
@Argument(help: "Configuration file.", transform: { $0.replaceTiltWithHomeDirectoryPath() })
var configurationFile: String
@Option(help: "Project directory. It will be added to every relative path (path that does not start with `/`",
transform: {
if $0.last == "/" {
return $0
}
return $0 + "/"
})
var projectDirectory: String
}

View File

@ -1,5 +1,5 @@
//
// ColorsConfiguration+ShellCommandable.swift
// ColorsConfiguration+Runnable.swift
//
//
// Created by Thibaut Schmitt on 30/08/2022.
@ -8,7 +8,7 @@
import Foundation
extension ColorsConfiguration: Runnable {
func run(force: Bool) {
func run(projectDirectory: String, force: Bool) {
var args = [String]()
if force {
@ -16,13 +16,13 @@ extension ColorsConfiguration: Runnable {
}
args += [
inputFile,
inputFile.prependIfRelativePath(projectDirectory),
"--style",
style,
"--xcassets-path",
xcassetsPath,
xcassetsPath.prependIfRelativePath(projectDirectory),
"--extension-output-path",
extensionOutputPath,
extensionOutputPath.prependIfRelativePath(projectDirectory),
"--static-members",
"\(staticMembersOptions)"
]
@ -39,7 +39,8 @@ extension ColorsConfiguration: Runnable {
extensionSuffix
]
}
Colors.main(args)
print("Colors args:")
dump(args)
//Colors.main(args)
}
}

View File

@ -1,5 +1,5 @@
//
// FontsConfiguration+ShellCommandable.swift
// FontsConfiguration+Runnable.swift
//
//
// Created by Thibaut Schmitt on 30/08/2022.
@ -8,7 +8,7 @@
import Foundation
extension FontsConfiguration: Runnable {
func run(force: Bool) {
func run(projectDirectory: String, force: Bool) {
var args = [String]()
if force {
@ -18,7 +18,7 @@ extension FontsConfiguration: Runnable {
args += [
inputFile,
"--extension-output-path",
extensionOutputPath,
extensionOutputPath.prependIfRelativePath(projectDirectory),
"--static-members",
"\(staticMembersOptions)"
]

View File

@ -1,5 +1,5 @@
//
// ImagesConfiguration+ShellCommandable.swift
// ImagesConfiguration+Runnable.swift
//
//
// Created by Thibaut Schmitt on 30/08/2022.
@ -8,7 +8,7 @@
import Foundation
extension ImagesConfiguration: Runnable {
func run(force: Bool) {
func run(projectDirectory: String, force: Bool) {
var args = [String]()
if force {
@ -16,11 +16,11 @@ extension ImagesConfiguration: Runnable {
}
args += [
inputFile,
inputFile.prependIfRelativePath(projectDirectory),
"--xcassets-path",
xcassetsPath,
xcassetsPath.prependIfRelativePath(projectDirectory),
"--extension-output-path",
extensionOutputPath,
extensionOutputPath.prependIfRelativePath(projectDirectory),
"--static-members",
"\(staticMembersOptions)"
]

View File

@ -8,6 +8,6 @@
import Foundation
protocol Runnable {
func run(force: Bool)
func run(projectDirectory: String, force: Bool)
}

View File

@ -1,5 +1,5 @@
//
// StringsConfiguration+ShellCommandable.swift
// StringsConfiguration+Runnable.swift
//
//
// Created by Thibaut Schmitt on 30/08/2022.
@ -8,7 +8,7 @@
import Foundation
extension StringsConfiguration: Runnable {
func run(force: Bool) {
func run(projectDirectory: String, force: Bool) {
var args = [String]()
if force {
@ -16,15 +16,15 @@ extension StringsConfiguration: Runnable {
}
args += [
inputFile,
inputFile.prependIfRelativePath(projectDirectory),
"--output-path",
outputPath,
outputPath.prependIfRelativePath(projectDirectory),
"--langs",
langs,
"--default-lang",
defaultLang,
"--extension-output-path",
extensionOutputPath,
extensionOutputPath.prependIfRelativePath(projectDirectory),
"--static-members",
"\(staticMembersOptions)"
]

View File

@ -1,5 +1,5 @@
//
// TagsConfiguration+ShellCommandable.swift
// TagsConfiguration+Runnable.swift
//
//
// Created by Thibaut Schmitt on 30/08/2022.
@ -8,7 +8,7 @@
import Foundation
extension TagsConfiguration: Runnable {
func run(force: Bool) {
func run(projectDirectory: String, force: Bool) {
var args = [String]()
if force {
@ -16,11 +16,11 @@ extension TagsConfiguration: Runnable {
}
args += [
inputFile,
inputFile.prependIfRelativePath(projectDirectory),
"--lang",
lang,
"--extension-output-path",
extensionOutputPath,
extensionOutputPath.prependIfRelativePath(projectDirectory),
"--static-members",
"\(staticMembersOptions)"
]

View File

@ -34,7 +34,7 @@ class ImageExtensionGenerator {
// Create file if not exists
let fileManager = FileManager()
if fileManager.fileExists(atPath: extensionFilePath) == false {
Shell.shell("touch", "\(extensionFilePath)")
Shell.shell(["touch", "\(extensionFilePath)"])
}
// Generate extension
@ -47,7 +47,7 @@ class ImageExtensionGenerator {
// Create file if not exists
let fileManager = FileManager()
if fileManager.fileExists(atPath: extensionFilePath) == false {
Shell.shell("touch", "\(extensionFilePath)")
Shell.shell(["touch", "\(extensionFilePath)"])
}
// Create extension content

View File

@ -55,7 +55,7 @@ class XcassetsGenerator {
// Create imageset folder
let imagesetName = "\(parsedImage.name).imageset"
let imagesetPath = "\(xcassetsPath)/\(imagesetName)"
Shell.shell("mkdir", "-p", imagesetPath)
Shell.shell(["mkdir", "-p", imagesetPath])
// Store managed images path
generatedAssetsPaths.append(imagesetName)
@ -96,16 +96,22 @@ class XcassetsGenerator {
// convert path/to/image.png -resize 200x300 path/to/output.png
// convert path/to/image.png -resize 200x path/to/output.png
// convert path/to/image.png -resize x300 path/to/output.png
Shell.shell("convert", "\(imageData.path)", "-resize", "\(convertArguments.x1.width ?? "")x\(convertArguments.x1.height ?? "")", output1x)
Shell.shell("convert", "\(imageData.path)", "-resize", "\(convertArguments.x2.width ?? "")x\(convertArguments.x2.height ?? "")", output2x)
Shell.shell("convert", "\(imageData.path)", "-resize", "\(convertArguments.x3.width ?? "")x\(convertArguments.x3.height ?? "")", output3x)
Shell.shell(["convert", "\(imageData.path)",
"-resize", "\(convertArguments.x1.width ?? "")x\(convertArguments.x1.height ?? "")",
output1x])
Shell.shell(["convert", "\(imageData.path)",
"-resize", "\(convertArguments.x2.width ?? "")x\(convertArguments.x2.height ?? "")",
output2x])
Shell.shell(["convert", "\(imageData.path)",
"-resize", "\(convertArguments.x3.width ?? "")x\(convertArguments.x3.height ?? "")",
output3x])
}
// Write Content.json
let imagesetContentJson = parsedImage.contentJson
let contentJsonFilePath = "\(imagesetPath)/Contents.json"
if fileManager.fileExists(atPath: contentJsonFilePath) == false {
Shell.shell("touch", "\(contentJsonFilePath)")
Shell.shell(["touch", "\(contentJsonFilePath)"])
}
let contentJsonFilePathURL = URL(fileURLWithPath: contentJsonFilePath)
@ -160,8 +166,8 @@ class XcassetsGenerator {
}
// Info unavailable -> do not bypass
let taskWidth = Shell.shell("identify", "-format", "%w", xcassetImagePath)
let taskHeight = Shell.shell("identify", "-format", "%h", xcassetImagePath)
let taskWidth = Shell.shell(["identify", "-format", "%w", xcassetImagePath])
let taskHeight = Shell.shell(["identify", "-format", "%h", xcassetImagePath])
guard taskWidth.terminationStatus == 0,
taskHeight.terminationStatus == 0 else {
return false

View File

@ -95,7 +95,7 @@ struct Images: ParsableCommand {
@discardableResult
static func getSvgConverterPath() -> String {
let taskSvgConverter = Shell.shell("which", "rsvg-convert")
let taskSvgConverter = Shell.shell(["which", "rsvg-convert"])
if taskSvgConverter.terminationStatus == 0 {
return taskSvgConverter.output!.removeCharacters(from: CharacterSet.whitespacesAndNewlines)
}

View File

@ -118,7 +118,7 @@ class StringsFileGenerator {
// Create file if not exists
let fileManager = FileManager()
if fileManager.fileExists(atPath: extensionFilePath) == false {
Shell.shell("touch", "\(extensionFilePath)")
Shell.shell(["touch", "\(extensionFilePath)"])
}
// Create extension content

View File

@ -38,7 +38,7 @@ class TagsGenerator {
// Create file if not exists
let fileManager = FileManager()
if fileManager.fileExists(atPath: extensionFilePath) == false {
Shell.shell("touch", "\(extensionFilePath)")
Shell.shell(["touch", "\(extensionFilePath)"])
}
// Create extension content

View File

@ -40,20 +40,20 @@ struct Twine: ParsableCommand {
// Generate strings files (lproj files)
for lang in options.langs {
Shell.shell(Self.twineExecutable,
Shell.shell([Self.twineExecutable,
"generate-localization-file", options.inputFile,
"--lang", "\(lang)",
"\(options.outputPath)/\(lang).lproj/\(options.inputFilenameWithoutExt).strings",
"--tags=ios,iosonly,iosOnly")
"--tags=ios,iosonly,iosOnly"])
}
// Generate extension
Shell.shell(Self.twineExecutable,
Shell.shell([Self.twineExecutable,
"generate-localization-file", options.inputFile,
"--format", "apple-swift",
"--lang", "\(options.defaultLang)",
options.extensionFilePath,
"--tags=ios,iosonly,iosOnly")
"--tags=ios,iosonly,iosOnly"])
print("[\(Self.toolName)] Strings generated")
}

View File

@ -9,32 +9,48 @@ import Foundation
public class Shell {
@discardableResult
public static func shell(launchPath: String = "/usr/bin/env", _ args: String...) -> (terminationStatus: Int32, output: String?) {
let task = Process()
task.launchPath = launchPath
task.arguments = args
let pipe = Pipe()
task.standardOutput = pipe
try? task.run()
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 static var environment: [String: String] {
ProcessInfo.processInfo.environment
}
// @discardableResult
// public static func shell(launchPath: String = "/usr/bin/env", _ args: String...) -> (terminationStatus: Int32, output: String?) {
// let task = Process()
// task.launchPath = launchPath
// task.arguments = args
//
// var currentEnv = ProcessInfo.processInfo.environment
// for (key, value) in environment {
// currentEnv[key] = value
// }
// task.environment = currentEnv
//
// let pipe = Pipe()
// task.standardOutput = pipe
// try? task.run()
// 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)
// }
@discardableResult
public static func shell(launchPath: String = "/usr/bin/env", _ args: [String]) -> (terminationStatus: Int32, output: String?) {
let task = Process()
task.launchPath = launchPath
task.arguments = args
var currentEnv = ProcessInfo.processInfo.environment
for (key, value) in environment {
currentEnv[key] = value
}
task.environment = currentEnv
let pipe = Pipe()
task.standardOutput = pipe
task.launch()