| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- //===----------------------------------------------------------------------===//
- //
- // This source file is part of the Swift Argument Parser open source project
- //
- // Copyright (c) 2020 Apple Inc. and the Swift project authors
- // Licensed under Apache License v2.0 with Runtime Library Exception
- //
- // See https://swift.org/LICENSE.txt for license information
- //
- //===----------------------------------------------------------------------===//
- extension Collection {
- /// - returns: A non-empty collection or `nil`.
- fileprivate var nonEmpty: Self? { isEmpty ? nil : self }
- }
- /// Header used to validate serialization version of an encoded ToolInfo struct.
- public struct ToolInfoHeader: Decodable {
- /// A sentinel value indicating the version of the ToolInfo struct used to
- /// generate the serialized form.
- public var serializationVersion: Int
- public init(serializationVersion: Int) {
- self.serializationVersion = serializationVersion
- }
- }
- /// Top-level structure containing serialization version and information for all
- /// commands in a tool.
- public struct ToolInfoV0: Codable, Hashable {
- /// A sentinel value indicating the version of the ToolInfo struct used to
- /// generate the serialized form.
- public var serializationVersion = 0
- /// Root command of the tool.
- public var command: CommandInfoV0
- public init(command: CommandInfoV0) {
- self.command = command
- }
- }
- /// All information about a particular command, including arguments and
- /// subcommands.
- public struct CommandInfoV0: Codable, Hashable {
- /// Super commands and tools.
- public var superCommands: [String]?
- /// Command should appear in help displays.
- public var shouldDisplay: Bool = true
- /// Name used to invoke the command.
- public var commandName: String
- /// List of command aliases.
- public var aliases: [String]?
- /// Short description of the command's functionality.
- public var abstract: String?
- /// Extended description of the command's functionality.
- public var discussion: String?
- /// Optional name of the subcommand invoked when the command is invoked with
- /// no arguments.
- public var defaultSubcommand: String?
- /// List of nested commands.
- public var subcommands: [CommandInfoV0]?
- /// List of supported arguments.
- public var arguments: [ArgumentInfoV0]?
- public init(
- superCommands: [String],
- shouldDisplay: Bool,
- commandName: String,
- aliases: [String]?,
- abstract: String,
- discussion: String,
- defaultSubcommand: String?,
- subcommands: [CommandInfoV0],
- arguments: [ArgumentInfoV0]
- ) {
- self.superCommands = superCommands.nonEmpty
- self.shouldDisplay = shouldDisplay
- self.commandName = commandName
- self.aliases = aliases?.nonEmpty
- self.abstract = abstract.nonEmpty
- self.discussion = discussion.nonEmpty
- self.defaultSubcommand = defaultSubcommand?.nonEmpty
- self.subcommands = subcommands.nonEmpty
- self.arguments = arguments.nonEmpty
- }
- public init(from decoder: any Decoder) throws {
- let container = try decoder.container(keyedBy: CodingKeys.self)
- self.superCommands = try container.decodeIfPresent(
- [String].self, forKey: .superCommands)
- self.commandName = try container.decode(String.self, forKey: .commandName)
- self.aliases = try container.decodeIfPresent(
- [String].self, forKey: .aliases)
- self.abstract = try container.decodeIfPresent(
- String.self, forKey: .abstract)
- self.discussion = try container.decodeIfPresent(
- String.self, forKey: .discussion)
- self.shouldDisplay =
- try container.decodeIfPresent(Bool.self, forKey: .shouldDisplay) ?? true
- self.defaultSubcommand = try container.decodeIfPresent(
- String.self, forKey: .defaultSubcommand)
- self.subcommands = try container.decodeIfPresent(
- [CommandInfoV0].self, forKey: .subcommands)
- self.arguments = try container.decodeIfPresent(
- [ArgumentInfoV0].self, forKey: .arguments)
- }
- }
- /// All information about a particular argument, including display names and
- /// options.
- public struct ArgumentInfoV0: Codable, Hashable {
- /// Information about an argument's name.
- public struct NameInfoV0: Codable, Hashable {
- /// Kind of prefix of an argument's name.
- public enum KindV0: String, Codable, Hashable {
- /// A multi-character name preceded by two dashes.
- case long
- /// A single character name preceded by a single dash.
- case short
- /// A multi-character name preceded by a single dash.
- case longWithSingleDash
- }
- /// Kind of prefix the NameInfoV0 describes.
- public var kind: KindV0
- /// Single or multi-character name of the argument.
- public var name: String
- public init(kind: NameInfoV0.KindV0, name: String) {
- self.kind = kind
- self.name = name
- }
- }
- /// Kind of argument.
- public enum KindV0: String, Codable, Hashable {
- /// Argument specified as a bare value on the command line.
- case positional
- /// Argument specified as a value prefixed by a `--flag` on the command line.
- case option
- /// Argument specified only as a `--flag` on the command line.
- case flag
- }
- public enum ParsingStrategyV0: String, Codable, Hashable {
- /// Expect the next `SplitArguments.Element` to be a value and parse it.
- /// Will fail if the next input is an option.
- case `default`
- /// Parse the next `SplitArguments.Element.value`
- case scanningForValue
- /// Parse the next `SplitArguments.Element` as a value, regardless of its type.
- case unconditional
- /// Parse multiple `SplitArguments.Element.value` up to the next non-`.value`
- case upToNextOption
- /// Parse all remaining `SplitArguments.Element` as values, regardless of its type.
- case allRemainingInput
- /// Collect all the elements after the terminator, preventing them from
- /// appearing in any other position.
- case postTerminator
- /// Collect all unused inputs once recognized arguments/options/flags have
- /// been parsed.
- case allUnrecognized
- }
- public enum CompletionKindV0: Codable, Hashable {
- /// Use the specified list of completion strings.
- case list(values: [String])
- /// Complete file names with the specified extensions.
- case file(extensions: [String])
- /// Complete directory names that match the specified pattern.
- case directory
- /// Call the given shell command to generate completions.
- case shellCommand(command: String)
- /// Generate completions using the given three-parameter closure.
- case custom
- /// Generate completions using the given async three-parameter closure.
- case customAsync
- /// Generate completions using the given one-parameter closure.
- @available(*, deprecated, message: "Use custom instead.")
- case customDeprecated
- }
- /// Kind of argument the ArgumentInfo describes.
- public var kind: KindV0
- /// Argument should appear in help displays.
- public var shouldDisplay: Bool
- /// Custom name of argument's section.
- public var sectionTitle: String?
- /// Argument can be omitted.
- public var isOptional: Bool
- /// Argument can be specified multiple times.
- public var isRepeating: Bool
- /// Parsing strategy of the ArgumentInfo.
- public var parsingStrategy: ParsingStrategyV0
- /// All names of the argument.
- public var names: [NameInfoV0]?
- /// The best name to use when referring to the argument in help displays.
- public var preferredName: NameInfoV0?
- /// Name of argument's value.
- public var valueName: String?
- /// Default value of the argument is none is specified on the command line.
- public var defaultValue: String?
- // NOTE: this property will not be renamed to 'allValueStrings' to avoid
- // breaking compatibility with the current serialized format.
- //
- // This property is effectively deprecated.
- /// List of all valid values.
- public var allValues: [String]?
- /// List of all valid values.
- public var allValueStrings: [String]? {
- get { self.allValues }
- set { self.allValues = newValue }
- }
- /// Mapping of valid values to descriptions of the value.
- public var allValueDescriptions: [String: String]?
- /// The type of completion to use for an argument or an option value.
- ///
- /// `nil` if the tool uses the default completion kind.
- public var completionKind: CompletionKindV0?
- /// Short description of the argument's functionality.
- public var abstract: String?
- /// Extended description of the argument's functionality.
- public var discussion: String?
- public init(
- kind: KindV0,
- shouldDisplay: Bool,
- sectionTitle: String?,
- isOptional: Bool,
- isRepeating: Bool,
- parsingStrategy: ParsingStrategyV0,
- names: [NameInfoV0]?,
- preferredName: NameInfoV0?,
- valueName: String?,
- defaultValue: String?,
- allValueStrings: [String]?,
- allValueDescriptions: [String: String]?,
- completionKind: CompletionKindV0?,
- abstract: String?,
- discussion: String?
- ) {
- self.kind = kind
- self.shouldDisplay = shouldDisplay
- self.sectionTitle = sectionTitle
- self.isOptional = isOptional
- self.isRepeating = isRepeating
- self.parsingStrategy = parsingStrategy
- self.names = names?.nonEmpty
- self.preferredName = preferredName
- self.valueName = valueName?.nonEmpty
- self.defaultValue = defaultValue?.nonEmpty
- self.allValueStrings = allValueStrings?.nonEmpty
- self.allValueDescriptions = allValueDescriptions?.nonEmpty
- self.completionKind = completionKind
- self.abstract = abstract?.nonEmpty
- self.discussion = discussion?.nonEmpty
- }
- }
|