Flag.swift 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // This source file is part of the Swift Argument Parser open source project
  4. //
  5. // Copyright (c) 2020 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 property wrapper that represents a command-line flag.
  12. ///
  13. /// Use the `@Flag` wrapper to define a property of your custom type as a
  14. /// command-line flag. A *flag* is a dash-prefixed label that can be provided on
  15. /// the command line, such as `-d` and `--debug`.
  16. ///
  17. /// For example, the following program declares a flag that lets a user indicate
  18. /// that seconds should be included when printing the time.
  19. ///
  20. /// ```swift
  21. /// @main
  22. /// struct Time: ParsableCommand {
  23. /// @Flag var includeSeconds = false
  24. ///
  25. /// mutating func run() {
  26. /// if includeSeconds {
  27. /// print(Date.now.formatted(.dateTime.hour().minute().second()))
  28. /// } else {
  29. /// print(Date.now.formatted(.dateTime.hour().minute()))
  30. /// }
  31. /// }
  32. /// }
  33. /// ```
  34. ///
  35. /// `includeSeconds` has a default value of `false`, but becomes `true` if
  36. /// `--include-seconds` is provided on the command line.
  37. ///
  38. /// $ time
  39. /// 11:09 AM
  40. /// $ time --include-seconds
  41. /// 11:09:15 AM
  42. ///
  43. /// A flag can have a value that is a `Bool`, an `Int`, or any `EnumerableFlag`
  44. /// type. When using an `EnumerableFlag` type as a flag, the individual cases
  45. /// form the flags that are used on the command line.
  46. ///
  47. /// @main
  48. /// struct Math: ParsableCommand {
  49. /// enum Operation: EnumerableFlag {
  50. /// case add
  51. /// case multiply
  52. /// }
  53. ///
  54. /// @Flag var operation: Operation
  55. ///
  56. /// mutating func run() {
  57. /// print("Time to \(operation)!")
  58. /// }
  59. /// }
  60. ///
  61. /// Instead of using the name of the `operation` property as the flag in this
  62. /// case, the two cases of the `Operation` enumeration become valid flags.
  63. /// The `operation` property is neither optional nor given a default value, so
  64. /// one of the two flags is required.
  65. ///
  66. /// $ math --add
  67. /// Time to add!
  68. /// $ math
  69. /// Error: Missing one of: '--add', '--multiply'
  70. @propertyWrapper
  71. public struct Flag<Value>: Decodable, ParsedWrapper {
  72. internal var _parsedValue: Parsed<Value>
  73. internal init(_parsedValue: Parsed<Value>) {
  74. self._parsedValue = _parsedValue
  75. }
  76. public init(from _decoder: Decoder) throws {
  77. try self.init(_decoder: _decoder)
  78. }
  79. /// This initializer works around a quirk of property wrappers, where the
  80. /// compiler will not see no-argument initializers in extensions.
  81. ///
  82. /// Explicitly marking this initializer unavailable means that when `Value`
  83. /// is a type supported by `Flag` like `Bool` or `EnumerableFlag`, the
  84. /// appropriate overload will be selected instead.
  85. ///
  86. /// ```swift
  87. /// @Flag() var flag: Bool // Syntax without this initializer
  88. /// @Flag var flag: Bool // Syntax with this initializer
  89. /// ```
  90. @available(
  91. *, unavailable,
  92. message:
  93. "A default value must be provided unless the value type is supported by Flag."
  94. )
  95. public init() {
  96. fatalError("unavailable")
  97. }
  98. /// The value presented by this property wrapper.
  99. public var wrappedValue: Value {
  100. get {
  101. switch _parsedValue {
  102. case .value(let v):
  103. return v
  104. case .definition:
  105. configurationFailure(directlyInitializedError)
  106. }
  107. }
  108. set {
  109. _parsedValue = .value(newValue)
  110. }
  111. }
  112. }
  113. extension Flag: Sendable where Value: Sendable {}
  114. extension Flag: CustomStringConvertible {
  115. public var description: String {
  116. switch _parsedValue {
  117. case .value(let v):
  118. return String(describing: v)
  119. case .definition:
  120. return "Flag(*definition*)"
  121. }
  122. }
  123. }
  124. extension Flag: DecodableParsedWrapper where Value: Decodable {}
  125. /// The options for converting a Boolean flag into a `true`/`false` pair.
  126. public struct FlagInversion: Hashable {
  127. internal enum Representation {
  128. case prefixedNo
  129. case prefixedEnableDisable
  130. }
  131. internal var base: Representation
  132. /// Adds a matching flag with a `no-` prefix to represent `false`.
  133. ///
  134. /// For example, the `shouldRender` property in this declaration is set to
  135. /// `true` when a user provides `--render` and to `false` when the user
  136. /// provides `--no-render`:
  137. ///
  138. /// @Flag(name: .customLong("render"), inversion: .prefixedNo)
  139. /// var shouldRender: Bool
  140. public static var prefixedNo: FlagInversion {
  141. self.init(base: .prefixedNo)
  142. }
  143. // swift-format-ignore: BeginDocumentationCommentWithOneLineSummary
  144. /// Uses matching flags with `enable-` and `disable-` prefixes.
  145. ///
  146. /// For example, the `extraOutput` property in this declaration is set to
  147. /// `true` when a user provides `--enable-extra-output` and to `false` when
  148. /// the user provides `--disable-extra-output`:
  149. ///
  150. /// @Flag(inversion: .prefixedEnableDisable)
  151. /// var extraOutput: Bool
  152. public static var prefixedEnableDisable: FlagInversion {
  153. self.init(base: .prefixedEnableDisable)
  154. }
  155. }
  156. extension FlagInversion: Sendable {}
  157. /// The options for treating enumeration-based flags as exclusive.
  158. public struct FlagExclusivity: Hashable {
  159. internal enum Representation {
  160. case exclusive
  161. case chooseFirst
  162. case chooseLast
  163. }
  164. internal var base: Representation
  165. /// Only one of the enumeration cases may be provided.
  166. public static var exclusive: FlagExclusivity {
  167. self.init(base: .exclusive)
  168. }
  169. /// The first enumeration case that is provided is used.
  170. public static var chooseFirst: FlagExclusivity {
  171. self.init(base: .chooseFirst)
  172. }
  173. /// The last enumeration case that is provided is used.
  174. public static var chooseLast: FlagExclusivity {
  175. self.init(base: .chooseLast)
  176. }
  177. }
  178. extension FlagExclusivity: Sendable {}
  179. extension Flag where Value == Bool? {
  180. /// Creates a Boolean property that reads its value from the presence of
  181. /// one or more inverted flags.
  182. ///
  183. /// Use this initializer to create an optional Boolean flag with an on/off
  184. /// pair. With the following declaration, for example, the user can specify
  185. /// either `--use-https` or `--no-use-https` to set the `useHTTPS` flag to
  186. /// `true` or `false`, respectively. If neither is specified, the resulting
  187. /// flag value would be `nil`.
  188. ///
  189. /// @Flag(inversion: .prefixedNo)
  190. /// var useHTTPS: Bool?
  191. ///
  192. /// - Parameters:
  193. /// - name: A specification for what names are allowed for this flag.
  194. /// - inversion: The method for converting this flags name into an on/off
  195. /// pair.
  196. /// - exclusivity: The behavior to use when an on/off pair of flags is
  197. /// specified.
  198. /// - help: Information about how to use this flag.
  199. public init(
  200. name: NameSpecification = .long,
  201. inversion: FlagInversion,
  202. exclusivity: FlagExclusivity = .chooseLast,
  203. help: ArgumentHelp? = nil
  204. ) {
  205. self.init(
  206. _parsedValue: .init { key in
  207. .flag(
  208. key: key,
  209. name: name,
  210. default: nil,
  211. required: false,
  212. inversion: inversion,
  213. exclusivity: exclusivity,
  214. help: help)
  215. })
  216. }
  217. /// This initializer allows a user to provide a `nil` default value for
  218. /// `@Flag`-marked `Optional<Bool>` property without allowing a non-`nil`
  219. /// default value.
  220. public init(
  221. wrappedValue _value: _OptionalNilComparisonType,
  222. name: NameSpecification = .long,
  223. inversion: FlagInversion,
  224. exclusivity: FlagExclusivity = .chooseLast,
  225. help: ArgumentHelp? = nil
  226. ) {
  227. self.init(
  228. name: name,
  229. inversion: inversion,
  230. exclusivity: exclusivity,
  231. help: help)
  232. }
  233. }
  234. extension Flag where Value == Bool {
  235. /// Creates a Boolean property with an optional default value, intended to be called by other constructors to centralize logic.
  236. ///
  237. /// This private `init` allows us to expose multiple other similar constructors to allow for standard default property initialization while reducing code duplication.
  238. private init(
  239. name: NameSpecification,
  240. initial: Bool?,
  241. help: ArgumentHelp? = nil
  242. ) {
  243. self.init(
  244. _parsedValue: .init { key in
  245. .flag(key: key, name: name, default: initial, help: help)
  246. })
  247. }
  248. /// Creates a Boolean property with default value provided by standard Swift default value syntax that reads its value from the presence of a flag.
  249. ///
  250. /// - Parameters:
  251. /// - wrappedValue: A default value to use for this property, provided implicitly by the compiler during property wrapper initialization.
  252. /// - name: A specification for what names are allowed for this flag.
  253. /// - help: Information about how to use this flag.
  254. public init(
  255. wrappedValue: Bool,
  256. name: NameSpecification = .long,
  257. help: ArgumentHelp? = nil
  258. ) {
  259. self.init(
  260. name: name,
  261. initial: wrappedValue,
  262. help: help
  263. )
  264. }
  265. /// Creates a property with an optional default value, intended to be called by other constructors to centralize logic.
  266. ///
  267. /// This private `init` allows us to expose multiple other similar constructors to allow for standard default property initialization while reducing code duplication.
  268. private init(
  269. name: NameSpecification,
  270. initial: Bool?,
  271. inversion: FlagInversion,
  272. exclusivity: FlagExclusivity,
  273. help: ArgumentHelp?
  274. ) {
  275. self.init(
  276. _parsedValue: .init { key in
  277. .flag(
  278. key: key,
  279. name: name,
  280. default: initial,
  281. required: initial == nil,
  282. inversion: inversion,
  283. exclusivity: exclusivity,
  284. help: help)
  285. })
  286. }
  287. /// Creates a Boolean property with default value provided by standard Swift default value syntax that reads its value from the presence of one or more inverted flags.
  288. ///
  289. /// Use this initializer to create a Boolean flag with an on/off pair.
  290. /// With the following declaration, for example, the user can specify either `--use-https` or `--no-use-https` to set the `useHTTPS` flag to `true` or `false`, respectively.
  291. ///
  292. /// ```swift
  293. /// @Flag(inversion: .prefixedNo)
  294. /// var useHTTPS: Bool = true
  295. /// ```
  296. ///
  297. /// - Parameters:
  298. /// - wrappedValue: A default value to use for this property, provided
  299. /// implicitly by the compiler during property wrapper initialization.
  300. /// - name: A specification for what names are allowed for this flag.
  301. /// - inversion: The method for converting this flag's name into an on/off pair.
  302. /// - exclusivity: The behavior to use when an on/off pair of flags is specified.
  303. /// - help: Information about how to use this flag.
  304. public init(
  305. wrappedValue: Bool,
  306. name: NameSpecification = .long,
  307. inversion: FlagInversion,
  308. exclusivity: FlagExclusivity = .chooseLast,
  309. help: ArgumentHelp? = nil
  310. ) {
  311. self.init(
  312. name: name,
  313. initial: wrappedValue,
  314. inversion: inversion,
  315. exclusivity: exclusivity,
  316. help: help
  317. )
  318. }
  319. /// Creates a Boolean property with no default value that reads its value from the presence of one or more inverted flags.
  320. ///
  321. /// Use this initializer to create a Boolean flag with an on/off pair.
  322. /// With the following declaration, for example, the user can specify either `--use-https` or `--no-use-https` to set the `useHTTPS` flag to `true` or `false`, respectively.
  323. ///
  324. /// ```swift
  325. /// @Flag(inversion: .prefixedNo)
  326. /// var useHTTPS: Bool
  327. /// ```
  328. ///
  329. /// - Parameters:
  330. /// - name: A specification for what names are allowed for this flag.
  331. /// - inversion: The method for converting this flag's name into an on/off pair.
  332. /// - exclusivity: The behavior to use when an on/off pair of flags is specified.
  333. /// - help: Information about how to use this flag.
  334. public init(
  335. name: NameSpecification = .long,
  336. inversion: FlagInversion,
  337. exclusivity: FlagExclusivity = .chooseLast,
  338. help: ArgumentHelp? = nil
  339. ) {
  340. self.init(
  341. name: name,
  342. initial: nil,
  343. inversion: inversion,
  344. exclusivity: exclusivity,
  345. help: help
  346. )
  347. }
  348. }
  349. extension Flag where Value == Int {
  350. /// Creates an integer property that gets its value from the number of times
  351. /// a flag appears.
  352. ///
  353. /// This property defaults to a value of zero.
  354. ///
  355. /// - Parameters:
  356. /// - name: A specification for what names are allowed for this flag.
  357. /// - help: Information about how to use this flag.
  358. public init(
  359. name: NameSpecification = .long,
  360. help: ArgumentHelp? = nil
  361. ) {
  362. self.init(
  363. _parsedValue: .init { key in
  364. .counter(key: key, name: name, help: help)
  365. })
  366. }
  367. }
  368. // - MARK: EnumerableFlag
  369. extension Flag where Value: EnumerableFlag {
  370. /// Creates a property with an optional default value, intended to be called by other constructors to centralize logic.
  371. ///
  372. /// This private `init` allows us to expose multiple other similar constructors to allow for standard default property initialization while reducing code duplication.
  373. private init(
  374. initial: Value?,
  375. exclusivity: FlagExclusivity,
  376. help: ArgumentHelp?
  377. ) {
  378. self.init(
  379. _parsedValue: .init { key in
  380. // Create a string representation of the default value. Since this is a
  381. // flag, the default value to show to the user is the `--value-name`
  382. // flag that a user would provide on the command line, not a Swift value.
  383. let defaultValueFlag = initial.flatMap { value -> String? in
  384. let defaultKey = InputKey(
  385. name: String(describing: value), parent: key)
  386. let defaultNames = Value.name(for: value).makeNames(defaultKey)
  387. return defaultNames.first?.synopsisString
  388. }
  389. let caseHelps = Value.allCases.map { Value.help(for: $0) }
  390. let hasCustomCaseHelp = caseHelps.contains(where: { $0 != nil })
  391. let args = Value.allCases.enumerated().map {
  392. (i, value) -> ArgumentDefinition in
  393. let caseKey = InputKey(name: String(describing: value), parent: key)
  394. let name = Value.name(for: value)
  395. let helpForCase = caseHelps[i] ?? help
  396. var defaultValueString: String? = nil
  397. if hasCustomCaseHelp {
  398. if value == initial {
  399. defaultValueString = defaultValueFlag
  400. }
  401. } else {
  402. defaultValueString = defaultValueFlag
  403. }
  404. let help = ArgumentDefinition.Help(
  405. allValueStrings: [],
  406. options: initial != nil ? .isOptional : [],
  407. help: helpForCase,
  408. defaultValue: defaultValueString,
  409. key: key,
  410. isComposite: !hasCustomCaseHelp)
  411. return ArgumentDefinition.flag(
  412. name: name,
  413. key: key,
  414. caseKey: caseKey,
  415. help: help,
  416. parsingStrategy: .default,
  417. initialValue: initial,
  418. update: .nullary({ (origin, name, values) in
  419. try ArgumentSet.updateFlag(
  420. key: key, value: value, origin: origin, values: &values,
  421. exclusivity: exclusivity)
  422. })
  423. )
  424. }
  425. return ArgumentSet(args)
  426. })
  427. }
  428. /// Creates a property with a default value provided by standard Swift default value syntax that gets its value from the presence of a flag.
  429. ///
  430. /// Use this initializer to customize the name and number of states further than using a `Bool`.
  431. /// To use, define an `EnumerableFlag` enumeration with a case for each state, and use that as the type for your flag.
  432. /// In this case, the user can specify either `--use-production-server` or `--use-development-server` to set the flag's value.
  433. ///
  434. /// ```swift
  435. /// enum ServerChoice: EnumerableFlag {
  436. /// case useProductionServer
  437. /// case useDevelopmentServer
  438. /// }
  439. ///
  440. /// @Flag var serverChoice: ServerChoice = .useProductionServer
  441. /// ```
  442. ///
  443. /// - Parameters:
  444. /// - wrappedValue: A default value to use for this property, provided implicitly by the compiler during property wrapper initialization.
  445. /// - exclusivity: The behavior to use when multiple flags are specified.
  446. /// - help: Information about how to use this flag.
  447. public init(
  448. wrappedValue: Value,
  449. exclusivity: FlagExclusivity = .exclusive,
  450. help: ArgumentHelp? = nil
  451. ) {
  452. self.init(
  453. initial: wrappedValue,
  454. exclusivity: exclusivity,
  455. help: help
  456. )
  457. }
  458. /// Creates a property with no default value that gets its value from the presence of a flag.
  459. ///
  460. /// Use this initializer to customize the name and number of states further than using a `Bool`.
  461. /// To use, define an `EnumerableFlag` enumeration with a case for each state, and use that as the type for your flag.
  462. /// In this case, the user can specify either `--use-production-server` or `--use-development-server` to set the flag's value.
  463. ///
  464. /// ```swift
  465. /// enum ServerChoice: EnumerableFlag {
  466. /// case useProductionServer
  467. /// case useDevelopmentServer
  468. /// }
  469. ///
  470. /// @Flag var serverChoice: ServerChoice
  471. /// ```
  472. ///
  473. /// - Parameters:
  474. /// - exclusivity: The behavior to use when multiple flags are specified.
  475. /// - help: Information about how to use this flag.
  476. public init(
  477. exclusivity: FlagExclusivity = .exclusive,
  478. help: ArgumentHelp? = nil
  479. ) {
  480. self.init(
  481. initial: nil,
  482. exclusivity: exclusivity,
  483. help: help
  484. )
  485. }
  486. }
  487. extension Flag {
  488. /// Creates a property that gets its value from the presence of a flag,
  489. /// where the allowed flags are defined by an `EnumerableFlag` type.
  490. public init<Element>(
  491. exclusivity: FlagExclusivity = .exclusive,
  492. help: ArgumentHelp? = nil
  493. ) where Value == Element?, Element: EnumerableFlag {
  494. self.init(
  495. _parsedValue: .init { parentKey in
  496. let caseHelps = Element.allCases.map { Element.help(for: $0) }
  497. let hasCustomCaseHelp = caseHelps.contains(where: { $0 != nil })
  498. let args = Element.allCases.enumerated().map {
  499. (i, value) -> ArgumentDefinition in
  500. let caseKey = InputKey(
  501. name: String(describing: value), parent: parentKey)
  502. let name = Element.name(for: value)
  503. let helpForCase = hasCustomCaseHelp ? (caseHelps[i] ?? help) : help
  504. let help = ArgumentDefinition.Help(
  505. allValueStrings: [],
  506. options: [.isOptional],
  507. help: helpForCase,
  508. defaultValue: nil,
  509. key: parentKey,
  510. isComposite: !hasCustomCaseHelp)
  511. return ArgumentDefinition.flag(
  512. name: name, key: parentKey, caseKey: caseKey, help: help,
  513. parsingStrategy: .default, initialValue: nil as Element?,
  514. update: .nullary({ (origin, name, values) in
  515. try ArgumentSet.updateFlag(
  516. key: parentKey, value: value, origin: origin, values: &values,
  517. exclusivity: exclusivity)
  518. }))
  519. }
  520. return ArgumentSet(args)
  521. })
  522. }
  523. /// Creates an array property with an optional default value, intended to be called by other constructors to centralize logic.
  524. ///
  525. /// This private `init` allows us to expose multiple other similar constructors to allow for standard default property initialization while reducing code duplication.
  526. private init<Element>(
  527. initial: [Element]?,
  528. help: ArgumentHelp? = nil
  529. ) where Value == [Element], Element: EnumerableFlag {
  530. self.init(
  531. _parsedValue: .init { parentKey in
  532. let caseHelps = Element.allCases.map { Element.help(for: $0) }
  533. let hasCustomCaseHelp = caseHelps.contains(where: { $0 != nil })
  534. let args = Element.allCases.enumerated().map {
  535. (i, value) -> ArgumentDefinition in
  536. let caseKey = InputKey(
  537. name: String(describing: value), parent: parentKey)
  538. let name = Element.name(for: value)
  539. let helpForCase = hasCustomCaseHelp ? (caseHelps[i] ?? help) : help
  540. let help = ArgumentDefinition.Help(
  541. allValueStrings: [],
  542. options: [.isOptional],
  543. help: helpForCase,
  544. defaultValue: nil,
  545. key: parentKey,
  546. isComposite: !hasCustomCaseHelp)
  547. return ArgumentDefinition.flag(
  548. name: name, key: parentKey, caseKey: caseKey, help: help,
  549. parsingStrategy: .default, initialValue: initial,
  550. update: .nullary({ (origin, name, values) in
  551. values.update(
  552. forKey: parentKey, inputOrigin: origin, initial: [Element](),
  553. closure: {
  554. $0.append(value)
  555. })
  556. }))
  557. }
  558. return ArgumentSet(args)
  559. })
  560. }
  561. /// Creates an array property that gets its values from the presence of
  562. /// zero or more flags, where the allowed flags are defined by an
  563. /// `EnumerableFlag` type.
  564. ///
  565. /// This property has an empty array as its default value.
  566. ///
  567. /// - Parameters:
  568. /// - wrappedValue: A default value to use for this property, provided
  569. // implicitly by the compiler during property wrapper initialization.
  570. /// - help: Information about how to use this flag.
  571. public init<Element>(
  572. wrappedValue: [Element],
  573. help: ArgumentHelp? = nil
  574. ) where Value == [Element], Element: EnumerableFlag {
  575. self.init(
  576. initial: wrappedValue,
  577. help: help
  578. )
  579. }
  580. /// Creates an array property with no default value that gets its values from the presence of zero or more flags, where the allowed flags are defined by an `EnumerableFlag` type.
  581. ///
  582. /// This method is called to initialize an array `Flag` with no default value such as:
  583. /// ```swift
  584. /// @Flag
  585. /// var foo: [CustomFlagType]
  586. /// ```
  587. ///
  588. /// - Parameter help: Information about how to use this flag.
  589. public init<Element>(
  590. help: ArgumentHelp? = nil
  591. ) where Value == [Element], Element: EnumerableFlag {
  592. self.init(
  593. initial: nil,
  594. help: help
  595. )
  596. }
  597. }
  598. extension ArgumentDefinition {
  599. static func flag<V>(
  600. name: NameSpecification, key: InputKey, caseKey: InputKey, help: Help,
  601. parsingStrategy: ArgumentDefinition.ParsingStrategy, initialValue: V?,
  602. update: Update
  603. ) -> ArgumentDefinition {
  604. ArgumentDefinition(
  605. kind: .name(key: caseKey, specification: name), help: help,
  606. completion: .default, parsingStrategy: parsingStrategy, update: update,
  607. initial: { origin, values in
  608. if let initial = initialValue {
  609. values.set(initial, forKey: key, inputOrigin: origin)
  610. }
  611. })
  612. }
  613. }