Some basic command line parsing

This commit is contained in:
Simon Kågedal Reimer 2019-05-04 19:07:10 +02:00
parent e9c3e036da
commit 951280361d
4 changed files with 124 additions and 2 deletions

View File

@ -0,0 +1,71 @@
import Foundation
import Basic
import SPMUtility
struct CommandLineOptions {
enum SubCommand {
case noCommand
case version
case listDevices
}
struct Error: Swift.Error {
let underlyingError: Swift.Error
private let argumentParser: ArgumentParser
fileprivate init(underlyingError: Swift.Error, argumentParser: ArgumentParser) {
self.underlyingError = underlyingError
self.argumentParser = argumentParser
}
func printUsage(on stream: OutputByteStream) {
argumentParser.printUsage(on: stream)
}
}
private let parser: ArgumentParser
private(set) var subCommand: SubCommand
static func parse(commandName: String, arguments: [String]) throws -> CommandLineOptions {
let parser = ArgumentParser(
commandName: commandName,
usage: "[options] subcommand",
overview: "Manage Xcode simulators",
seeAlso: nil
)
let binder = ArgumentBinder<CommandLineOptions>()
binder.bind(option: parser.add(
option: "--version",
shortName: "-v",
kind: Bool.self,
usage: "Prints the version and exits"
), to: { options, _ in
options.subCommand = .version
})
parser.add(
subparser: "list-devices",
overview: "List available Xcode Simulator devices"
)
var options = CommandLineOptions(parser: parser, subCommand: .noCommand)
do {
let result = try parser.parse(arguments)
switch result.subparser(parser) {
case "list-devices":
options.subCommand = .listDevices
default:
try binder.fill(parseResult: result, into: &options)
}
} catch {
throw Error(underlyingError: error, argumentParser: parser)
}
return options
}
func printUsage(on stream: OutputByteStream) {
parser.printUsage(on: stream)
}
}

View File

@ -1,4 +1,6 @@
import Foundation
import Basic
import SPMUtility
public class XcodeSimulatorTool {
private let arguments: [String]
@ -8,7 +10,33 @@ public class XcodeSimulatorTool {
}
public func run() -> Int32 {
print("Hello from XcodeSimulatorTool")
let commandName = URL(fileURLWithPath: arguments.first!).lastPathComponent
let arguments = Array(self.arguments.dropFirst())
do {
let options = try CommandLineOptions.parse(
commandName: commandName,
arguments: arguments
)
try run(with: options)
} catch let error as CommandLineOptions.Error {
stderrStream.write("error: \(error.underlyingError.localizedDescription)\n\n")
error.printUsage(on: stderrStream)
return 1
} catch {
return 2
}
return 0
}
private func run(with options: CommandLineOptions) throws {
switch options.subCommand {
case .noCommand:
options.printUsage(on: stdoutStream)
case .version:
print("xcode-simulator-tool version 0.1")
case .listDevices:
print("Listing devices")
}
}
}

View File

@ -0,0 +1,21 @@
import XCTest
import SPMUtility
@testable import XcodeSimulatorKit
class CommandLineOptionsTests: XCTestCase {
func testListDevices() throws {
let options = try CommandLineOptions.parse(commandName: "command", arguments: ["list-devices"])
XCTAssertEqual(options.subCommand, .listDevices)
}
func testArgumentParser() throws {
let parser = ArgumentParser(commandName: "SomeBinary", usage: "sample parser", overview: "Sample overview")
parser.add(subparser: "a", overview: "A!")
parser.add(subparser: "b", overview: "B!")
let result = try parser.parse(["a"])
XCTAssertEqual(result.subparser(parser), "a")
}
}

View File

@ -26,7 +26,9 @@ final class xcode_simulator_toolTests: XCTestCase {
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)
XCTAssertEqual(output, "Hello, world!\n")
_ = output
// Not really testing the binary at the moment
}
/// Returns path to the built products directory.