| public struct CommandLineArguments { |
| public struct MissingArgumentError: Error, CustomStringConvertible { |
| let argName: String |
| |
| public var description: String { |
| return "Missing required argument: \(argName)" |
| } |
| } |
| public struct UnkeyedArgumentError: Error, CustomStringConvertible { |
| let argName: String |
| |
| public var description: String { |
| return "Unexpectedly found command line argument \(argName) without a key" |
| } |
| } |
| |
| private let args: [String: String] |
| |
| public static func parse<T: Sequence>(_ args: T) throws -> CommandLineArguments |
| where T.Element == String { |
| var parsedArgs: [String: String] = [:] |
| var currentKey: String? = nil |
| for arg in args { |
| if arg.hasPrefix("-") { |
| // Parse a new key |
| if let currentKey = currentKey { |
| // The last key didn't have a value. Just add it with an empty string as |
| // the value to the parsed args |
| parsedArgs[currentKey] = "" |
| } |
| currentKey = arg |
| } else { |
| if let currentKey = currentKey { |
| parsedArgs[currentKey] = arg |
| } else { |
| throw UnkeyedArgumentError(argName: arg) |
| } |
| currentKey = nil |
| } |
| } |
| if let currentKey = currentKey { |
| // The last key didn't have a value. Just add it with an empty string as |
| // the value to the parsed args |
| parsedArgs[currentKey] = "" |
| } |
| return CommandLineArguments(args: parsedArgs) |
| } |
| |
| public subscript(key: String) -> String? { |
| return args[key] |
| } |
| |
| public func getRequired(_ key: String) throws -> String { |
| if let value = args[key] { |
| return value |
| } else { |
| throw MissingArgumentError(argName: key) |
| } |
| } |
| |
| public func has(_ key: String) -> Bool { |
| return args[key] != nil |
| } |
| } |