Files
swift-hpa/Sources/hpa/Internal/Discussion+playbook.swift

182 lines
4.1 KiB
Swift

import CliDoc
extension CliDoc.Discussion where Content == AnyTextNode {
static func playbook(
examples: [Example]
) -> Self {
.init {
VStack {
Note.mostOptionsNotRequired
ExampleSection.default(examples: examples)
SeeAlso(label: "Ansible playbook options.", command: "ansible-playbook --help")
ImportantNote.passingExtraArgs
}
.separator(.newLine(count: 2))
.eraseToAnyTextNode()
}
}
}
extension Array where Element == Example {
func addingPassingOptions(command: String) -> Self {
var output = self
output.append((
label: "Passing extra arguments / options",
example: "\(command) -- --vaultId=myId@$SCRIPTS/vault-gopass-client"
))
return output
}
func addingPipeToOtherCommand(command: String) -> Self {
var output = self
output.append((
label: "Piping output to other command.",
example: "\(command) --quiet | xargs open"
))
return output
}
}
extension ExampleSection where Header == String, Label == String {
static func `default`(
examples: [Example],
usesPassingExtraOptions: Bool = true,
usesPipeToOtherCommand: Bool = true
) -> some TextNode {
var examples = examples
if let first = examples.first {
if usesPassingExtraOptions {
examples = examples.addingPassingOptions(command: first.example)
}
if usesPipeToOtherCommand {
examples = examples.addingPipeToOtherCommand(command: first.example)
}
}
return Self(examples: examples) {
"EXAMPLES:"
} label: {
"Some common usage examples."
}
.exampleStyle(HPAExampleStyle())
}
}
struct HPAExampleStyle: ExampleStyle {
func render(content: ExampleConfiguration) -> some TextNode {
VStack {
content.examples.map { example in
VStack {
example.label.color(.green).bold()
ShellCommand.hpaCommand(example.example)
}
}
}
.separator(.newLine(count: 2))
}
}
extension ShellCommand where Content == String, Symbol == String {
static func hpaCommand(_ command: String) -> Self {
.init { "\(Constants.appName) \(command)" } symbol: { "$" }
}
}
struct SeeAlso<Label: TextNode, Content: TextNode>: TextNode {
let title = "SEE ALSO:"
let label: Label
let content: Content
init(
@TextBuilder content: () -> Content,
@TextBuilder label: () -> Label
) {
self.content = content()
self.label = label()
}
var body: some TextNode {
VStack {
LabeledContent {
label.italic()
} label: {
title.color(.yellow).bold().underline()
}
ShellCommand { content } symbol: { "$" }
}
}
}
extension SeeAlso where Content == String, Label == Empty {
init(command: String) {
self.init { "\(Constants.appName) \(command)" } label: { Empty() }
}
}
extension SeeAlso where Content == String, Label == String {
init(label: String, command: String) {
self.init { "\(Constants.appName) \(command)" } label: { label }
}
}
struct Note<Content: TextNode>: TextNode {
let label: String = "NOTE:"
let content: Content
init(
@TextBuilder _ content: () -> Content
) {
self.content = content()
}
var body: some TextNode {
HStack {
label.color(.yellow).bold()
content
}
}
}
extension Note where Content == String {
static var mostOptionsNotRequired: Self {
.init {
"Most options are not required if you have a configuration file setup."
}
}
}
struct ImportantNote<Content: TextNode>: TextNode {
let label: String = "IMPORTANT NOTE:"
let content: Content
init(
@TextBuilder _ content: () -> Content
) {
self.content = content()
}
var body: some TextNode {
HStack {
label.color(.red).bold().underline()
content
}
}
}
extension ImportantNote where Content == String {
static var passingExtraArgs: Self {
.init {
"""
Any extra options passed to the underlying command need to come after
`--` otherwise an "Unknown option" error will occur. See above example of passing
extra options.
"""
}
}
}