ParentCommand.swift 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // This source file is part of the Swift Argument Parser open source project
  4. //
  5. // Copyright (c) 2025 Apple Inc. and the Swift project authors
  6. // Licensed under Apache License v2.0 with Runtime Library Exception
  7. //
  8. // See https://swift.org/LICENSE.txt for license information
  9. //
  10. //===----------------------------------------------------------------------===//
  11. /// A wrapper that adds a reference to a parent command.
  12. ///
  13. /// Use the `@ParentCommand` wrapper to gain access to a parent command's state.
  14. ///
  15. /// The arguments, options, and flags in a `@ParentCommand` type are omitted from
  16. /// the help screen for the including child command, and only appear in the parent's
  17. /// help screen. To include the help in both screens, use the ``OptionGroup``
  18. /// wrapper instead.
  19. ///
  20. ///
  21. /// ```swift
  22. /// struct SuperCommand: ParsableCommand {
  23. /// static let configuration = CommandConfiguration(
  24. /// subcommands: [SubCommand.self]
  25. /// )
  26. ///
  27. /// @Flag(name: .shortAndLong)
  28. /// var verbose: Bool = false
  29. /// }
  30. ///
  31. /// struct SubCommand: ParsableCommand {
  32. /// @ParentCommand var parent: SuperCommand
  33. ///
  34. /// mutating func run() throws {
  35. /// if self.parent.verbose {
  36. /// print("Verbose")
  37. /// }
  38. /// }
  39. /// }
  40. /// ```
  41. @propertyWrapper
  42. public struct ParentCommand<Value: ParsableCommand>: Decodable, ParsedWrapper {
  43. internal var _parsedValue: Parsed<Value>
  44. internal init(_parsedValue: Parsed<Value>) {
  45. self._parsedValue = _parsedValue
  46. }
  47. public init(from _decoder: Decoder) throws {
  48. if let d = _decoder as? SingleValueDecoder,
  49. let value = try? d.previousValue(Value.self)
  50. {
  51. self.init(_parsedValue: .value(value))
  52. } else {
  53. throw ParserError.notParentCommand("\(Value.self)")
  54. }
  55. }
  56. public init() {
  57. self.init(
  58. _parsedValue: .init { _ in
  59. .init()
  60. }
  61. )
  62. }
  63. public var wrappedValue: Value {
  64. get {
  65. switch _parsedValue {
  66. case .value(let v):
  67. return v
  68. case .definition:
  69. configurationFailure(directlyInitializedError)
  70. }
  71. }
  72. set {
  73. _parsedValue = .value(newValue)
  74. }
  75. }
  76. }
  77. extension ParentCommand: Sendable where Value: Sendable {}
  78. extension ParentCommand: CustomStringConvertible {
  79. public var description: String {
  80. switch _parsedValue {
  81. case .value(let v):
  82. return String(describing: v)
  83. case .definition:
  84. return "ParentCommand(*definition*)"
  85. }
  86. }
  87. }