Some basic command line parsing
This commit is contained in:
parent
e9c3e036da
commit
951280361d
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue