import ArgumentParser import CliClient struct BasicGlobalOptions: ParsableArguments { @Flag( name: .shortAndLong, help: "Increase logging level (can be passed multiple times)." ) var verbose: Int @Flag( name: .shortAndLong, help: "Supress logging." ) var quiet = false @Option( name: .shortAndLong, help: "Optional shell to use when calling shell commands.", completion: .file() ) var shell: String? } @dynamicMemberLookup struct GlobalOptions: ParsableArguments { @Option( name: .shortAndLong, help: "Optional path to the ansible hpa playbook directory." ) var playbookDir: String? @Option( name: .shortAndLong, help: "Optional path to the ansible inventory to use." ) var inventoryPath: String? @Flag( name: .long, help: "Supress only playbook logging." ) var quietOnlyPlaybook = false @OptionGroup var basic: BasicGlobalOptions subscript(dynamicMember keyPath: WritableKeyPath) -> T { get { basic[keyPath: keyPath] } set { basic[keyPath: keyPath] = newValue } } subscript(dynamicMember keyPath: KeyPath) -> T { basic[keyPath: keyPath] } } extension GlobalOptions { func loggingOptions(commandName: String) -> CliClient.LoggingOptions { .init( commandName: commandName, logLevel: .init(globals: basic, quietOnlyPlaybook: quietOnlyPlaybook) ) } } extension BasicGlobalOptions { func loggingOptions(commandName: String) -> CliClient.LoggingOptions { .init( commandName: commandName, logLevel: .init(globals: self, quietOnlyPlaybook: false) ) } }