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 Foundation
|
||||||
|
import Basic
|
||||||
|
import SPMUtility
|
||||||
|
|
||||||
public class XcodeSimulatorTool {
|
public class XcodeSimulatorTool {
|
||||||
private let arguments: [String]
|
private let arguments: [String]
|
||||||
|
@ -8,7 +10,33 @@ public class XcodeSimulatorTool {
|
||||||
}
|
}
|
||||||
|
|
||||||
public func run() -> Int32 {
|
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
|
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 data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||||
let output = String(data: data, encoding: .utf8)
|
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.
|
/// Returns path to the built products directory.
|
||||||
|
|
Loading…
Reference in New Issue