@@ -454,6 +454,105 @@ extension Option {
454454 }
455455}
456456
457+ // MARK: - @Option T Initializers (name-aware transform)
458+ extension Option {
459+ /// Creates a property with a default value that reads its value from a
460+ /// labeled option, parsing with a closure that receives the matched option
461+ /// name along with the value string.
462+ ///
463+ /// This initializer is useful when a single `@Option` property has multiple
464+ /// names and the transform needs to know which name was used. For example:
465+ ///
466+ /// ```swift
467+ /// @Option(
468+ /// name: [.customLong("resize"), .customLong("crop")],
469+ /// transformIncludingName: { name, value in
470+ /// switch name {
471+ /// case "resize": return .resize(value)
472+ /// case "crop": return .crop(value)
473+ /// default: fatalError()
474+ /// }
475+ /// }
476+ /// ) var operations: [Operation] = []
477+ /// ```
478+ ///
479+ /// - Parameters:
480+ /// - wrappedValue: The default value to use for this property, provided
481+ /// implicitly by the compiler during property wrapper initialization.
482+ /// - name: A specification for what names are allowed for this option.
483+ /// - parsingStrategy: The behavior to use when looking for this option's
484+ /// value.
485+ /// - help: Information about how to use this option.
486+ /// - completion: The type of command-line completion provided for this
487+ /// option.
488+ /// - transformIncludingName: A closure that receives the matched option
489+ /// name (without leading dashes) and the value string, and returns this
490+ /// property's type or throws an error.
491+ @preconcurrency
492+ public init (
493+ wrappedValue: Value ,
494+ name: NameSpecification = . long,
495+ parsing parsingStrategy: SingleValueParsingStrategy = . next,
496+ help: ArgumentHelp ? = nil ,
497+ completion: CompletionKind ? = nil ,
498+ transformIncludingName: @Sendable @escaping ( _ optionName: String , _ value: String ) throws -> Value
499+ ) {
500+ self . init (
501+ _parsedValue: . init { key in
502+ let arg = ArgumentDefinition (
503+ container: Bare< Value> . self ,
504+ key: key,
505+ kind: . name( key: key, specification: name) ,
506+ help: help,
507+ parsingStrategy: parsingStrategy. base,
508+ transformIncludingName: transformIncludingName,
509+ initial: wrappedValue,
510+ completion: completion)
511+
512+ return ArgumentSet ( arg)
513+ } )
514+ }
515+
516+ /// Creates a required property that reads its value from a labeled option,
517+ /// parsing with a closure that receives the matched option name along with
518+ /// the value string.
519+ ///
520+ /// - Parameters:
521+ /// - name: A specification for what names are allowed for this option.
522+ /// - parsingStrategy: The behavior to use when looking for this option's
523+ /// value.
524+ /// - help: Information about how to use this option.
525+ /// - completion: The type of command-line completion provided for this
526+ /// option.
527+ /// - transformIncludingName: A closure that receives the matched option
528+ /// name (without leading dashes) and the value string, and returns this
529+ /// property's type or throws an error.
530+ @preconcurrency
531+ @_disfavoredOverload
532+ public init (
533+ name: NameSpecification = . long,
534+ parsing parsingStrategy: SingleValueParsingStrategy = . next,
535+ help: ArgumentHelp ? = nil ,
536+ completion: CompletionKind ? = nil ,
537+ transformIncludingName: @Sendable @escaping ( _ optionName: String , _ value: String ) throws -> Value
538+ ) {
539+ self . init (
540+ _parsedValue: . init { key in
541+ let arg = ArgumentDefinition (
542+ container: Bare< Value> . self ,
543+ key: key,
544+ kind: . name( key: key, specification: name) ,
545+ help: help,
546+ parsingStrategy: parsingStrategy. base,
547+ transformIncludingName: transformIncludingName,
548+ initial: nil ,
549+ completion: completion)
550+
551+ return ArgumentSet ( arg)
552+ } )
553+ }
554+ }
555+
457556// MARK: - @Option Optional<T: ExpressibleByArgument> Initializers
458557extension Option {
459558 /// Creates an optional property that reads its value from a labeled option,
@@ -911,3 +1010,184 @@ extension Option {
9111010 } )
9121011 }
9131012}
1013+
1014+ // MARK: - @Option Optional<T> Initializers (name-aware transform)
1015+ extension Option {
1016+ /// Creates an optional property that reads its value from a labeled option,
1017+ /// parsing with a closure that receives the matched option name, with an
1018+ /// explicit `nil` default.
1019+ ///
1020+ /// - Parameters:
1021+ /// - wrappedValue: A default value to use for this property, provided
1022+ /// implicitly by the compiler during property wrapper initialization.
1023+ /// - name: A specification for what names are allowed for this option.
1024+ /// - parsingStrategy: The behavior to use when looking for this option's
1025+ /// value.
1026+ /// - help: Information about how to use this option.
1027+ /// - completion: The type of command-line completion provided for this
1028+ /// option.
1029+ /// - transformIncludingName: A closure that receives the matched option
1030+ /// name (without leading dashes) and the value string, and returns this
1031+ /// property's type or throws an error.
1032+ @preconcurrency
1033+ public init < T> (
1034+ wrappedValue: _OptionalNilComparisonType ,
1035+ name: NameSpecification = . long,
1036+ parsing parsingStrategy: SingleValueParsingStrategy = . next,
1037+ help: ArgumentHelp ? = nil ,
1038+ completion: CompletionKind ? = nil ,
1039+ transformIncludingName: @Sendable @escaping ( _ optionName: String , _ value: String ) throws -> T
1040+ ) where Value == T ? {
1041+ self . init (
1042+ _parsedValue: . init { key in
1043+ let arg = ArgumentDefinition (
1044+ container: Optional< T> . self ,
1045+ key: key,
1046+ kind: . name( key: key, specification: name) ,
1047+ help: help,
1048+ parsingStrategy: parsingStrategy. base,
1049+ transformIncludingName: transformIncludingName,
1050+ initial: nil ,
1051+ completion: completion)
1052+
1053+ return ArgumentSet ( arg)
1054+ } )
1055+ }
1056+
1057+ /// Creates an optional property that reads its value from a labeled option,
1058+ /// parsing with a closure that receives the matched option name.
1059+ ///
1060+ /// - Parameters:
1061+ /// - name: A specification for what names are allowed for this option.
1062+ /// - parsingStrategy: The behavior to use when looking for this option's
1063+ /// value.
1064+ /// - help: Information about how to use this option.
1065+ /// - completion: The type of command-line completion provided for this
1066+ /// option.
1067+ /// - transformIncludingName: A closure that receives the matched option
1068+ /// name (without leading dashes) and the value string, and returns this
1069+ /// property's type or throws an error.
1070+ @preconcurrency
1071+ public init < T> (
1072+ name: NameSpecification = . long,
1073+ parsing parsingStrategy: SingleValueParsingStrategy = . next,
1074+ help: ArgumentHelp ? = nil ,
1075+ completion: CompletionKind ? = nil ,
1076+ transformIncludingName: @Sendable @escaping ( _ optionName: String , _ value: String ) throws -> T
1077+ ) where Value == T ? {
1078+ self . init (
1079+ _parsedValue: . init { key in
1080+ let arg = ArgumentDefinition (
1081+ container: Optional< T> . self ,
1082+ key: key,
1083+ kind: . name( key: key, specification: name) ,
1084+ help: help,
1085+ parsingStrategy: parsingStrategy. base,
1086+ transformIncludingName: transformIncludingName,
1087+ initial: nil ,
1088+ completion: completion)
1089+
1090+ return ArgumentSet ( arg)
1091+ } )
1092+ }
1093+ }
1094+
1095+ // MARK: - @Option Array<T> Initializers (name-aware transform)
1096+ extension Option {
1097+ /// Creates an array property that reads its values from zero or more labeled
1098+ /// options, parsing each element with a closure that receives the matched
1099+ /// option name along with the value string.
1100+ ///
1101+ /// This is particularly useful when multiple option names map to a single
1102+ /// array property and the relative ordering of different options matters:
1103+ ///
1104+ /// ```swift
1105+ /// @Option(
1106+ /// name: [.customLong("resize"), .customLong("crop")],
1107+ /// transformIncludingName: { name, value in
1108+ /// switch name {
1109+ /// case "resize": return .resize(value)
1110+ /// case "crop": return .crop(value)
1111+ /// default: fatalError()
1112+ /// }
1113+ /// }
1114+ /// ) var operations: [Operation] = []
1115+ /// ```
1116+ ///
1117+ /// - Parameters:
1118+ /// - wrappedValue: A default value to use for this property, provided
1119+ /// implicitly by the compiler during property wrapper initialization.
1120+ /// If this initial value is non-empty, elements passed from the command
1121+ /// line are appended to the original contents.
1122+ /// - name: A specification for what names are allowed for this option.
1123+ /// - parsingStrategy: The behavior to use when parsing the elements for
1124+ /// this option.
1125+ /// - help: Information about how to use this option.
1126+ /// - completion: The type of command-line completion provided for this
1127+ /// option.
1128+ /// - transformIncludingName: A closure that receives the matched option
1129+ /// name (without leading dashes) and the value string, and returns the
1130+ /// element type or throws an error.
1131+ @preconcurrency
1132+ public init < T> (
1133+ wrappedValue: [ T ] ,
1134+ name: NameSpecification = . long,
1135+ parsing parsingStrategy: ArrayParsingStrategy = . singleValue,
1136+ help: ArgumentHelp ? = nil ,
1137+ completion: CompletionKind ? = nil ,
1138+ transformIncludingName: @Sendable @escaping ( _ optionName: String , _ value: String ) throws -> T
1139+ ) where Value == [ T ] {
1140+ self . init (
1141+ _parsedValue: . init { key in
1142+ let arg = ArgumentDefinition (
1143+ container: Array< T> . self ,
1144+ key: key,
1145+ kind: . name( key: key, specification: name) ,
1146+ help: help,
1147+ parsingStrategy: parsingStrategy. base,
1148+ transformIncludingName: transformIncludingName,
1149+ initial: wrappedValue,
1150+ completion: completion)
1151+
1152+ return ArgumentSet ( arg)
1153+ } )
1154+ }
1155+
1156+ /// Creates a required array property that reads its values from zero or more
1157+ /// labeled options, parsing each element with a closure that receives the
1158+ /// matched option name along with the value string.
1159+ ///
1160+ /// - Parameters:
1161+ /// - name: A specification for what names are allowed for this option.
1162+ /// - parsingStrategy: The behavior to use when parsing the elements for
1163+ /// this option.
1164+ /// - help: Information about how to use this option.
1165+ /// - completion: The type of command-line completion provided for this
1166+ /// option.
1167+ /// - transformIncludingName: A closure that receives the matched option
1168+ /// name (without leading dashes) and the value string, and returns the
1169+ /// element type or throws an error.
1170+ @preconcurrency
1171+ public init < T> (
1172+ name: NameSpecification = . long,
1173+ parsing parsingStrategy: ArrayParsingStrategy = . singleValue,
1174+ help: ArgumentHelp ? = nil ,
1175+ completion: CompletionKind ? = nil ,
1176+ transformIncludingName: @Sendable @escaping ( _ optionName: String , _ value: String ) throws -> T
1177+ ) where Value == [ T ] {
1178+ self . init (
1179+ _parsedValue: . init { key in
1180+ let arg = ArgumentDefinition (
1181+ container: Array< T> . self ,
1182+ key: key,
1183+ kind: . name( key: key, specification: name) ,
1184+ help: help,
1185+ parsingStrategy: parsingStrategy. base,
1186+ transformIncludingName: transformIncludingName,
1187+ initial: nil ,
1188+ completion: completion)
1189+
1190+ return ArgumentSet ( arg)
1191+ } )
1192+ }
1193+ }
0 commit comments