Skip to content

Commit

Permalink
Use Swift Compiler plugins to package up templates into code
Browse files Browse the repository at this point in the history
  • Loading branch information
Full Queue Developer authored and Full Queue Developer committed Oct 15, 2023
1 parent e7b183c commit 3338638
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 728 deletions.
9 changes: 9 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@
"revision" : "1c30064de9dceac00aa3fefc70a1431e425e5f28",
"version" : "1.3.0"
}
},
{
"identity" : "swift-argument-parser",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser.git",
"state" : {
"revision" : "8f4d2753f0e4778c76d5f05ad16c74f707390531",
"version" : "1.2.3"
}
}
],
"version" : 2
Expand Down
20 changes: 19 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,37 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/onevcat/Rainbow", from: "4.0.0"),
.package(url: "https://github.com/FullQueueDeveloper/Sh.git", from: "1.3.0"),
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.2.0"),
// .package(path: "PluginsPackage"),
],
targets: [
.executableTarget(
name: "spx",
dependencies: ["SPXLib"]),
.target(
name: "SPXLib",
dependencies: ["Sh", "Rainbow"]),
dependencies: ["Sh", "Rainbow", ],
plugins: [
.plugin(name: "GenerateTemplatesPlugin")
]
),
.testTarget(
name: "SPXTests",
dependencies: ["SPXLib"],
resources: [
.copy("Fixtures"),
]),
.plugin(
name: "GenerateTemplatesPlugin",
capability: .buildTool,
dependencies: [
"GenerateTemplatesTool"
]
),
.executableTarget(
name: "GenerateTemplatesTool",
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser"),
])
]
)
42 changes: 42 additions & 0 deletions Plugins/GenerateTemplatesPlugin/GenerateTemplatesPlugin.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import PackagePlugin
import Foundation

@main
struct GenerateTemplatesPlugin: BuildToolPlugin {
func createBuildCommands(context: PackagePlugin.PluginContext, target: PackagePlugin.Target) async throws -> [PackagePlugin.Command] {

let templatesDir = context.package.directory.appending(subpath: "templates")
let enumerator = FileManager.default.enumerator(atPath: templatesDir.string)

let inputFiles = paths(fromEnumerator: enumerator!).map { path in
templatesDir.appending(path)
}

let templateDirNames = try FileManager.default.contentsOfDirectory(atPath: templatesDir.string)

return [
.buildCommand(
displayName: "GenerateTemplatesPlugin",
executable: try context.tool(named: "GenerateTemplatesTool").path,
arguments: [
templatesDir.string,
context.pluginWorkDirectory.string
],
inputFiles: inputFiles,
outputFiles: [
context.pluginWorkDirectory.appending("Templates.swift"),
] + templateDirNames.map({ templateName in
context.pluginWorkDirectory.appending("\(templateName)Template.swift")
})
),
]
}

func paths(fromEnumerator enumerator: FileManager.DirectoryEnumerator) -> [String] {
var result: [String] = []
while let file = enumerator.nextObject() as? String {
result += [file]
}
return result
}
}
32 changes: 0 additions & 32 deletions SPX/Package.resolved

This file was deleted.

22 changes: 0 additions & 22 deletions SPX/Package.swift

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
import Foundation
import Sh
import SystemPackage
import System
import ArgumentParser

@main
struct GenerateMain {
struct GenerateTemplatesTool: ParsableCommand {

static func main() throws {
@Argument(help: "input dir to read templates from")
var templatesDir: String

@Argument(help: "output dir to write to")
var outputDir: String

mutating func run() throws {
let templates: [String: [ScaffoldFile]] = try detectTemplates()
try generateTemplateEnum(templates: Array(templates.keys))
try generateTemplateEnum(outputDir: outputDir, templates: Array(templates.keys))

try templates.forEach { template, files in
try writeContentsFile(name: template, files: files)
try writeContentsFile(outputDir: outputDir, name: template, files: files)
}
try sh(.terminal, "swift build")
}

static func generateTemplateEnum(templates: [String]) throws {
try FileManager.default.resetDir(atPath: "Sources/SPXLib/templates-generated/")

try sh(.terminal, "rm -fr ./**/.build")
func generateTemplateEnum(outputDir: String, templates: [String]) throws {

let path = "Sources/SPXLib/templates-generated/Templates.swift"
let path = "\(outputDir)/Templates.swift"
let contents =
"""
enum Templates: String, CaseIterable {
Expand All @@ -38,8 +40,8 @@ struct GenerateMain {
try contents.data(using: .utf8)!.write(to: path.asURL)
}

static func writeContentsFile(name: String, files: [ScaffoldFile]) throws {
let path = "Sources/SPXLib/templates-generated/-.\(name)Files.swift"
func writeContentsFile(outputDir: String, name: String, files: [ScaffoldFile]) throws {
let path = "\(outputDir)/\(name)Template.swift"
let contents =
"""
extension Templates {
Expand All @@ -59,25 +61,29 @@ struct GenerateMain {
try contents.data(using: .utf8)!.write(to: path.asURL)
}

static func detectTemplates() throws -> [String: [ScaffoldFile]] {
func detectTemplates() throws -> [String: [ScaffoldFile]] {
let templateNames = try FileManager.default
.contentsOfDirectory(atPath: "templates")
.contentsOfDirectory(atPath: templatesDir)

return try templateNames.reduce([:]) { result, next in

let enumerator = FileManager.default.enumerator(atPath: "templates/\(next)")
let enumerator = FileManager.default.enumerator(atPath: "\(templatesDir)/\(next)")
guard let enumerator = enumerator else {
struct CouldNotCreateEnumerator: Error {
let path: String
}
throw CouldNotCreateEnumerator(path: "templates/\(next)")
throw CouldNotCreateEnumerator(path: "\(templatesDir)/\(next)")
}

var files: [ScaffoldFile] = []
let rootPath = FilePath("templates/\(next)/")
let rootPath = FilePath("\(templatesDir)/\(next)/")
while let file = enumerator.nextObject() as? String {

let filePath = rootPath.appending(file)//"templates/\(next)/\(file)"

guard !filePath.isDirectory else {
continue
}
do {
let contents = try String(contentsOfFile: filePath.string)
let name = filePath.lastComponent!
Expand All @@ -102,6 +108,16 @@ struct GenerateMain {
}
}

extension FilePath {
var isDirectory: Bool {
var directory = ObjCBool(false)
guard FileManager.default.fileExists(atPath: self.string, isDirectory: &directory) else {
return false
}
return directory.boolValue
}
}

extension String {
var isDirectory: Bool {
var directory = ObjCBool(false)
Expand Down
1 change: 1 addition & 0 deletions Sources/SPXLib/SPX.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public struct SPX {
public init() {}

public func run(_ arguments: [String]) {

do {
let defaultScriptsDir = "SPX"
try self.parse(arguments: Array(arguments.dropFirst()), spxDir: defaultScriptsDir)
Expand Down

0 comments on commit 3338638

Please sign in to comment.