import CliDoc extension CliDoc.Discussion { static func playbook( examples: [(label: String, example: String)] ) -> Self { .init { Section { Note.mostOptionsNotRequired Examples(examples: examples) SeeAlso(label: "Ansible playbook options.", command: "ansible-playbook --help") ImportantNote.passingExtraArgs } .labeledContentStyle(.custom("foo:")) } } } extension ShellCommand { static func hpaCommand(_ command: String) -> Self { .init(command: "\(Constants.appName) \(command)") } } struct SeeAlso: NodeRepresentable { let node: any NodeRepresentable init(label: String, command: String) { self.node = Group(separator: "\n") { Note("SEE ALSO:") { label } ShellCommand(command: command) } } func render() -> String { node.render() } } struct Examples: NodeRepresentable { typealias Example = (label: String, example: String) let examples: [Example] func render() -> String { Group(separator: "\n") { Note("EXAMPLES:") { "Common usage examples." } for (label, command) in examples { LabeledContent("\t\(label.green.bold)", separator: "\n") { ShellCommand.hpaCommand(command) } } if let first = examples.first { LabeledContent("\n\tPassing extra options.".green.bold, separator: "\n") { ShellCommand.hpaCommand("\(first.example) -- --vault-id \"myId@$SCRIPTS/vault-gopass-client\"") } } }.render() } } struct Note: NodeRepresentable { let node: any NodeRepresentable init( _ label: String = "NOTE:", @NodeBuilder _ content: () -> any NodeRepresentable ) { self.node = LabeledContent( separator: " ", label: { label.yellow.bold }, content: { content().style(.italic) } ) } func render() -> String { node.render() } static var mostOptionsNotRequired: Self { .init { "Most options are not required if you have a configuration file setup." } } } // TODO: Fix the text. struct ImportantNote: NodeRepresentable { let node: any NodeRepresentable init( _ label: String = "IMPORTANT NOTE:", @NodeBuilder _ content: () -> any NodeRepresentable ) { self.node = LabeledContent( separator: "\n", label: { label.red.bold.underline }, content: { content().style(.italic) } ) } func render() -> String { node.render() } 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. """ } } }