Add --project-directory option to generate command to easily use relative path
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:
14
README.md
14
README.md
@ -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 `/`)
|
@ -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/*"])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)"
|
||||
]
|
||||
|
@ -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)"
|
||||
]
|
||||
|
@ -8,6 +8,6 @@
|
||||
import Foundation
|
||||
|
||||
protocol Runnable {
|
||||
func run(force: Bool)
|
||||
func run(projectDirectory: String, force: Bool)
|
||||
}
|
||||
|
||||
|
@ -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)"
|
||||
]
|
||||
|
@ -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)"
|
||||
]
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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()
|
||||
|
Reference in New Issue
Block a user