feat: Adds generate commands that call to pandoc to generate pdf, latex, and html files from a project.
This commit is contained in:
@@ -9,9 +9,13 @@ struct Application: AsyncParsableCommand {
|
||||
static let configuration = CommandConfiguration(
|
||||
commandName: Constants.appName,
|
||||
abstract: createAbstract("A utility for working with ansible hpa playbook."),
|
||||
version: VERSION,
|
||||
version: VERSION ?? "0.0.0",
|
||||
subcommands: [
|
||||
BuildCommand.self, CreateCommand.self, VaultCommand.self, UtilsCommand.self
|
||||
BuildCommand.self,
|
||||
CreateCommand.self,
|
||||
GenerateCommand.self,
|
||||
VaultCommand.self,
|
||||
UtilsCommand.self
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import ArgumentParser
|
||||
import CliClient
|
||||
import Dependencies
|
||||
import Foundation
|
||||
|
||||
struct BuildCommand: AsyncParsableCommand {
|
||||
|
||||
@@ -9,16 +10,23 @@ struct BuildCommand: AsyncParsableCommand {
|
||||
static let configuration = CommandConfiguration.playbook(
|
||||
commandName: commandName,
|
||||
abstract: "Build a home performance assesment project.",
|
||||
examples: (label: "Build Project", example: "\(commandName) /path/to/project")
|
||||
examples: (
|
||||
label: "Build project when in the project directory.",
|
||||
example: "\(commandName)"
|
||||
),
|
||||
(
|
||||
label: "Build project from outside the project directory.",
|
||||
example: "\(commandName) --project-directory /path/to/project"
|
||||
)
|
||||
)
|
||||
|
||||
@OptionGroup var globals: GlobalOptions
|
||||
|
||||
@Argument(
|
||||
@Option(
|
||||
help: "Path to the project directory.",
|
||||
completion: .directory
|
||||
)
|
||||
var projectDir: String
|
||||
var projectDirectory: String?
|
||||
|
||||
@Argument(
|
||||
help: "Extra arguments / options passed to the playbook."
|
||||
@@ -27,19 +35,21 @@ struct BuildCommand: AsyncParsableCommand {
|
||||
|
||||
mutating func run() async throws {
|
||||
try await _run()
|
||||
|
||||
// try await runPlaybook(
|
||||
// commandName: Self.commandName,
|
||||
// globals: globals,
|
||||
// extraArgs: extraArgs,
|
||||
// "--tags", "build-project",
|
||||
// "--extra-vars", "project_dir=\(projectDir)"
|
||||
// )
|
||||
}
|
||||
|
||||
private func _run() async throws {
|
||||
@Dependency(\.cliClient) var cliClient
|
||||
|
||||
let projectDir: String
|
||||
if projectDirectory == nil {
|
||||
guard let pwd = ProcessInfo.processInfo.environment["PWD"] else {
|
||||
throw ProjectDirectoryNotSupplied()
|
||||
}
|
||||
projectDir = pwd
|
||||
} else {
|
||||
projectDir = projectDirectory!
|
||||
}
|
||||
|
||||
try await cliClient.runPlaybookCommand(
|
||||
globals.playbookOptions(
|
||||
arguments: [
|
||||
@@ -52,3 +62,5 @@ struct BuildCommand: AsyncParsableCommand {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct ProjectDirectoryNotSupplied: Error {}
|
||||
|
||||
14
Sources/hpa/GenerateCommands/GenerateCommand.swift
Normal file
14
Sources/hpa/GenerateCommands/GenerateCommand.swift
Normal file
@@ -0,0 +1,14 @@
|
||||
import ArgumentParser
|
||||
|
||||
struct GenerateCommand: AsyncParsableCommand {
|
||||
static let commandName = "generate"
|
||||
|
||||
static let configuration = CommandConfiguration(
|
||||
commandName: commandName,
|
||||
subcommands: [
|
||||
GeneratePdfCommand.self,
|
||||
GenerateLatexCommand.self,
|
||||
GenerateHtmlCommand.self
|
||||
]
|
||||
)
|
||||
}
|
||||
24
Sources/hpa/GenerateCommands/GenerateHtmlCommand.swift
Normal file
24
Sources/hpa/GenerateCommands/GenerateHtmlCommand.swift
Normal file
@@ -0,0 +1,24 @@
|
||||
import ArgumentParser
|
||||
import CliClient
|
||||
import Dependencies
|
||||
|
||||
// TODO: Need to add a step to build prior to generating file.
|
||||
struct GenerateHtmlCommand: AsyncParsableCommand {
|
||||
static let commandName = "html"
|
||||
|
||||
static let configuration = CommandConfiguration(
|
||||
commandName: commandName
|
||||
)
|
||||
|
||||
@OptionGroup var globals: GenerateOptions
|
||||
|
||||
mutating func run() async throws {
|
||||
@Dependency(\.cliClient) var cliClient
|
||||
|
||||
try await cliClient.runPandocCommand(
|
||||
globals.pandocOptions(.html),
|
||||
logging: globals.loggingOptions(commandName: Self.commandName)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
23
Sources/hpa/GenerateCommands/GenerateLatexCommand.swift
Normal file
23
Sources/hpa/GenerateCommands/GenerateLatexCommand.swift
Normal file
@@ -0,0 +1,23 @@
|
||||
import ArgumentParser
|
||||
import CliClient
|
||||
import Dependencies
|
||||
|
||||
// TODO: Need to add a step to build prior to generating file.
|
||||
struct GenerateLatexCommand: AsyncParsableCommand {
|
||||
static let commandName = "latex"
|
||||
|
||||
static let configuration = CommandConfiguration(
|
||||
commandName: commandName
|
||||
)
|
||||
|
||||
@OptionGroup var globals: GenerateOptions
|
||||
|
||||
mutating func run() async throws {
|
||||
@Dependency(\.cliClient) var cliClient
|
||||
|
||||
try await cliClient.runPandocCommand(
|
||||
globals.pandocOptions(.latex),
|
||||
logging: globals.loggingOptions(commandName: Self.commandName)
|
||||
)
|
||||
}
|
||||
}
|
||||
87
Sources/hpa/GenerateCommands/GenerateOptions.swift
Normal file
87
Sources/hpa/GenerateCommands/GenerateOptions.swift
Normal file
@@ -0,0 +1,87 @@
|
||||
import ArgumentParser
|
||||
import CliClient
|
||||
|
||||
@dynamicMemberLookup
|
||||
struct GenerateOptions: ParsableArguments {
|
||||
|
||||
@OptionGroup var basic: BasicGlobalOptions
|
||||
|
||||
@Option(
|
||||
name: [.short, .customLong("file")],
|
||||
help: "Files used to generate the output, can be specified multiple times.",
|
||||
completion: .file()
|
||||
)
|
||||
var files: [String] = []
|
||||
|
||||
@Option(
|
||||
name: [.customShort("H"), .long],
|
||||
help: "Files to include in the header, can be specified multiple times.",
|
||||
completion: .file()
|
||||
)
|
||||
var includeInHeader: [String] = []
|
||||
|
||||
@Flag(
|
||||
help: "Do not build the project prior to generating the output."
|
||||
)
|
||||
var noBuild: Bool = false
|
||||
|
||||
@Option(
|
||||
name: .shortAndLong,
|
||||
help: "The project directory.",
|
||||
completion: .directory
|
||||
)
|
||||
var projectDirectory: String?
|
||||
|
||||
@Option(
|
||||
name: .shortAndLong,
|
||||
help: "The output directory",
|
||||
completion: .directory
|
||||
)
|
||||
var outputDirectory: String?
|
||||
|
||||
@Option(
|
||||
name: [.customShort("n"), .customLong("name")],
|
||||
help: "Name of the output file."
|
||||
)
|
||||
var outputFileName: String?
|
||||
|
||||
// NOTE: This must be last, both here and in the commands, so if the commands have options of their
|
||||
// own, they must be declared ahead of using the global options.
|
||||
|
||||
@Argument(
|
||||
help: "Extra arguments / options to pass to the underlying pandoc command."
|
||||
)
|
||||
var extraOptions: [String] = []
|
||||
|
||||
subscript<T>(dynamicMember keyPath: WritableKeyPath<BasicGlobalOptions, T>) -> T {
|
||||
get { basic[keyPath: keyPath] }
|
||||
set { basic[keyPath: keyPath] = newValue }
|
||||
}
|
||||
|
||||
subscript<T>(dynamicMember keyPath: KeyPath<BasicGlobalOptions, T>) -> T {
|
||||
basic[keyPath: keyPath]
|
||||
}
|
||||
}
|
||||
|
||||
extension GenerateOptions {
|
||||
|
||||
func loggingOptions(commandName: String) -> CliClient.LoggingOptions {
|
||||
basic.loggingOptions(commandName: commandName)
|
||||
}
|
||||
|
||||
func pandocOptions(
|
||||
_ fileType: CliClient.PandocOptions.FileType
|
||||
) -> CliClient.PandocOptions {
|
||||
.init(
|
||||
files: files.count > 0 ? files : nil,
|
||||
includeInHeader: includeInHeader.count > 0 ? includeInHeader : nil,
|
||||
outputDirectory: outputDirectory,
|
||||
outputFileName: outputFileName,
|
||||
outputFileType: fileType,
|
||||
projectDirectory: projectDirectory,
|
||||
quiet: basic.quiet,
|
||||
shell: basic.shell,
|
||||
shouldBuild: !noBuild
|
||||
)
|
||||
}
|
||||
}
|
||||
32
Sources/hpa/GenerateCommands/GeneratePdfCommand.swift
Normal file
32
Sources/hpa/GenerateCommands/GeneratePdfCommand.swift
Normal file
@@ -0,0 +1,32 @@
|
||||
import ArgumentParser
|
||||
import CliClient
|
||||
import Dependencies
|
||||
|
||||
// TODO: Need to add a step to build prior to generating file.
|
||||
|
||||
struct GeneratePdfCommand: AsyncParsableCommand {
|
||||
static let commandName = "pdf"
|
||||
|
||||
static let configuration = CommandConfiguration(
|
||||
commandName: commandName
|
||||
)
|
||||
|
||||
@Option(
|
||||
name: [.customShort("e"), .customLong("engine")],
|
||||
help: "The pdf engine to use."
|
||||
)
|
||||
var pdfEngine: String?
|
||||
|
||||
@OptionGroup var globals: GenerateOptions
|
||||
|
||||
mutating func run() async throws {
|
||||
@Dependency(\.cliClient) var cliClient
|
||||
|
||||
let output = try await cliClient.runPandocCommand(
|
||||
globals.pandocOptions(.pdf(engine: pdfEngine)),
|
||||
logging: globals.loggingOptions(commandName: Self.commandName)
|
||||
)
|
||||
|
||||
print(output)
|
||||
}
|
||||
}
|
||||
@@ -27,10 +27,10 @@ struct BasicGlobalOptions: ParsableArguments {
|
||||
struct GlobalOptions: ParsableArguments {
|
||||
|
||||
@Option(
|
||||
name: .shortAndLong,
|
||||
name: .long,
|
||||
help: "Optional path to the ansible hpa playbook directory."
|
||||
)
|
||||
var playbookDir: String?
|
||||
var playbookDirectory: String?
|
||||
|
||||
@Option(
|
||||
name: .shortAndLong,
|
||||
|
||||
@@ -11,7 +11,7 @@ extension GlobalOptions {
|
||||
arguments: arguments,
|
||||
configuration: configuration,
|
||||
inventoryFilePath: inventoryPath,
|
||||
playbookDirectory: playbookDir,
|
||||
playbookDirectory: playbookDirectory,
|
||||
quiet: quietOnlyPlaybook ? true : basic.quiet,
|
||||
shell: basic.shell
|
||||
)
|
||||
|
||||
2
Sources/hpa/Version.swift
Normal file
2
Sources/hpa/Version.swift
Normal file
@@ -0,0 +1,2 @@
|
||||
// Do not set this variable, it is set during the build process.
|
||||
let VERSION: String? = nil
|
||||
Reference in New Issue
Block a user