mirror of
https://github.com/apple/swift-argument-parser.git
synced 2026-06-06 20:18:23 +00:00
121 lines
3.0 KiB
Swift
121 lines
3.0 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
enum Name {
|
|
/// A name (usually multi-character) prefixed with `--` (2 dashes) or
|
|
/// equivalent.
|
|
case long(String)
|
|
/// A single character name prefixed with `-` (1 dash) or equivalent.
|
|
///
|
|
/// Usually supports mixing multiple short names with a single dash, i.e.
|
|
/// `-ab` is equivalent to `-a -b`.
|
|
case short(Character, allowingJoined: Bool = false)
|
|
/// A name (usually multi-character) prefixed with `-` (1 dash).
|
|
case longWithSingleDash(String)
|
|
}
|
|
|
|
extension Name {
|
|
init(_ baseName: Substring) {
|
|
assert(
|
|
baseName.first == "-", "Attempted to create name for unprefixed argument")
|
|
if baseName.hasPrefix("--") {
|
|
self = .long(String(baseName.dropFirst(2)))
|
|
} else if baseName.count == 2, let name = baseName.last {
|
|
// single character "-x" style
|
|
self = .short(name)
|
|
} else {
|
|
// long name with single dash
|
|
self = .longWithSingleDash(String(baseName.dropFirst()))
|
|
}
|
|
}
|
|
}
|
|
|
|
// short argument names based on the synopsisString
|
|
// this will put the single - options before the -- options
|
|
extension Name: Comparable {
|
|
static func < (lhs: Name, rhs: Name) -> Bool {
|
|
lhs.synopsisString < rhs.synopsisString
|
|
}
|
|
}
|
|
|
|
extension Name: Hashable {}
|
|
|
|
extension Name {
|
|
enum Case: Equatable {
|
|
case long
|
|
case short
|
|
case longWithSingleDash
|
|
}
|
|
|
|
var `case`: Case {
|
|
switch self {
|
|
case .short:
|
|
return .short
|
|
case .longWithSingleDash:
|
|
return .longWithSingleDash
|
|
case .long:
|
|
return .long
|
|
}
|
|
}
|
|
}
|
|
|
|
extension Name {
|
|
var synopsisString: String {
|
|
switch self {
|
|
case .long(let n):
|
|
return "--\(n)"
|
|
case .short(let n, _):
|
|
return "-\(n)"
|
|
case .longWithSingleDash(let n):
|
|
return "-\(n)"
|
|
}
|
|
}
|
|
|
|
var valueString: String {
|
|
switch self {
|
|
case .long(let n):
|
|
return n
|
|
case .short(let n, _):
|
|
return String(n)
|
|
case .longWithSingleDash(let n):
|
|
return n
|
|
}
|
|
}
|
|
|
|
var allowsJoined: Bool {
|
|
switch self {
|
|
case .short(_, let allowingJoined):
|
|
return allowingJoined
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
/// The instance to match against user input -- this always has
|
|
/// `allowingJoined` as `false`, since that's the way input is parsed.
|
|
var nameToMatch: Name {
|
|
switch self {
|
|
case .long, .longWithSingleDash: return self
|
|
case .short(let c, _): return .short(c)
|
|
}
|
|
}
|
|
}
|
|
|
|
extension BidirectionalCollection where Element == Name {
|
|
var preferredName: Name? {
|
|
first { $0.case != .short } ?? first
|
|
}
|
|
|
|
var partitioned: [Name] {
|
|
filter { $0.case == .short } + filter { $0.case != .short }
|
|
}
|
|
}
|