1
0

Name.swift 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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. enum Name {
  12. /// A name (usually multi-character) prefixed with `--` (2 dashes) or equivalent.
  13. case long(String)
  14. /// A single character name prefixed with `-` (1 dash) or equivalent.
  15. ///
  16. /// Usually supports mixing multiple short names with a single dash, i.e. `-ab` is equivalent to `-a -b`.
  17. case short(Character, allowingJoined: Bool = false)
  18. /// A name (usually multi-character) prefixed with `-` (1 dash).
  19. case longWithSingleDash(String)
  20. }
  21. extension Name {
  22. init(_ baseName: Substring) {
  23. assert(
  24. baseName.first == "-", "Attempted to create name for unprefixed argument")
  25. if baseName.hasPrefix("--") {
  26. self = .long(String(baseName.dropFirst(2)))
  27. } else if baseName.count == 2, let name = baseName.last {
  28. // single character "-x" style
  29. self = .short(name)
  30. } else {
  31. // long name with single dash
  32. self = .longWithSingleDash(String(baseName.dropFirst()))
  33. }
  34. }
  35. }
  36. // short argument names based on the synopsisString
  37. // this will put the single - options before the -- options
  38. extension Name: Comparable {
  39. static func < (lhs: Name, rhs: Name) -> Bool {
  40. lhs.synopsisString < rhs.synopsisString
  41. }
  42. }
  43. extension Name: Hashable {}
  44. extension Name {
  45. enum Case: Equatable {
  46. case long
  47. case short
  48. case longWithSingleDash
  49. }
  50. var `case`: Case {
  51. switch self {
  52. case .short:
  53. return .short
  54. case .longWithSingleDash:
  55. return .longWithSingleDash
  56. case .long:
  57. return .long
  58. }
  59. }
  60. }
  61. extension Name {
  62. var synopsisString: String {
  63. switch self {
  64. case .long(let n):
  65. return "--\(n)"
  66. case .short(let n, _):
  67. return "-\(n)"
  68. case .longWithSingleDash(let n):
  69. return "-\(n)"
  70. }
  71. }
  72. var valueString: String {
  73. switch self {
  74. case .long(let n):
  75. return n
  76. case .short(let n, _):
  77. return String(n)
  78. case .longWithSingleDash(let n):
  79. return n
  80. }
  81. }
  82. var allowsJoined: Bool {
  83. switch self {
  84. case .short(_, let allowingJoined):
  85. return allowingJoined
  86. default:
  87. return false
  88. }
  89. }
  90. /// The instance to match against user input -- this always has
  91. /// `allowingJoined` as `false`, since that's the way input is parsed.
  92. var nameToMatch: Name {
  93. switch self {
  94. case .long, .longWithSingleDash: return self
  95. case .short(let c, _): return .short(c)
  96. }
  97. }
  98. }
  99. extension BidirectionalCollection where Element == Name {
  100. var preferredName: Name? {
  101. first { $0.case != .short } ?? first
  102. }
  103. var partitioned: [Name] {
  104. filter { $0.case == .short } + filter { $0.case != .short }
  105. }
  106. }