163 lines
3.7 KiB
Swift
163 lines
3.7 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
|
|
}
|
|
}
|
|
|
|
extension ExampleSection where Header == String, Label == String {
|
|
static func `default`(examples: [Example], usesPassingExtraOptions: Bool = true) -> some TextNode {
|
|
var examples = examples
|
|
if usesPassingExtraOptions, let first = examples.first {
|
|
examples = examples.addingPassingOptions(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.
|
|
"""
|
|
}
|
|
}
|
|
}
|