mirror of
https://github.com/mas-cli/mas
synced 2024-11-22 03:23:08 +00:00
🔥 Deintegrate CocoaSeeds
This commit is contained in:
parent
97f56a39fa
commit
89c9ee68c9
17 changed files with 0 additions and 1827 deletions
7
Seedfile
7
Seedfile
|
@ -1,7 +0,0 @@
|
|||
github "carthage/Commandant", "0.13.0", files: "Sources/Commandant/*.swift"
|
||||
github "antitypical/Result", "3.2.4", files: "Result/*.swift"
|
||||
|
||||
target :"mas-tests" do
|
||||
github "Quick/Nimble", "v7.0.3", files: "Nimble/**.{swift,h}"
|
||||
github "Quick/Quick", "v1.2.0", files: "Quick/**.{swift,h}"
|
||||
end
|
|
@ -1,99 +0,0 @@
|
|||
//
|
||||
// Argument.swift
|
||||
// Commandant
|
||||
//
|
||||
// Created by Syo Ikeda on 12/14/15.
|
||||
// Copyright (c) 2015 Carthage. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
/// Describes an argument that can be provided on the command line.
|
||||
public struct Argument<T> {
|
||||
/// The default value for this argument. This is the value that will be used
|
||||
/// if the argument is never explicitly specified on the command line.
|
||||
///
|
||||
/// If this is nil, this argument is always required.
|
||||
public let defaultValue: T?
|
||||
|
||||
/// A human-readable string describing the purpose of this argument. This will
|
||||
/// be shown in help messages.
|
||||
public let usage: String
|
||||
|
||||
public init(defaultValue: T? = nil, usage: String) {
|
||||
self.defaultValue = defaultValue
|
||||
self.usage = usage
|
||||
}
|
||||
|
||||
fileprivate func invalidUsageError<ClientError>(_ value: String) -> CommandantError<ClientError> {
|
||||
let description = "Invalid value for '\(self)': \(value)"
|
||||
return .usageError(description: description)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Operators
|
||||
|
||||
extension CommandMode {
|
||||
/// Evaluates the given argument in the given mode.
|
||||
///
|
||||
/// If parsing command line arguments, and no value was specified on the command
|
||||
/// line, the argument's `defaultValue` is used.
|
||||
public static func <| <T: ArgumentProtocol, ClientError>(mode: CommandMode, argument: Argument<T>) -> Result<T, CommandantError<ClientError>> {
|
||||
switch mode {
|
||||
case let .arguments(arguments):
|
||||
guard let stringValue = arguments.consumePositionalArgument() else {
|
||||
if let defaultValue = argument.defaultValue {
|
||||
return .success(defaultValue)
|
||||
} else {
|
||||
return .failure(missingArgumentError(argument.usage))
|
||||
}
|
||||
}
|
||||
|
||||
if let value = T.from(string: stringValue) {
|
||||
return .success(value)
|
||||
} else {
|
||||
return .failure(argument.invalidUsageError(stringValue))
|
||||
}
|
||||
|
||||
case .usage:
|
||||
return .failure(informativeUsageError(argument))
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluates the given argument list in the given mode.
|
||||
///
|
||||
/// If parsing command line arguments, and no value was specified on the command
|
||||
/// line, the argument's `defaultValue` is used.
|
||||
public static func <| <T: ArgumentProtocol, ClientError>(mode: CommandMode, argument: Argument<[T]>) -> Result<[T], CommandantError<ClientError>> {
|
||||
switch mode {
|
||||
case let .arguments(arguments):
|
||||
guard let firstValue = arguments.consumePositionalArgument() else {
|
||||
if let defaultValue = argument.defaultValue {
|
||||
return .success(defaultValue)
|
||||
} else {
|
||||
return .failure(missingArgumentError(argument.usage))
|
||||
}
|
||||
}
|
||||
|
||||
var values = [T]()
|
||||
|
||||
guard let value = T.from(string: firstValue) else {
|
||||
return .failure(argument.invalidUsageError(firstValue))
|
||||
}
|
||||
|
||||
values.append(value)
|
||||
|
||||
while let nextValue = arguments.consumePositionalArgument() {
|
||||
guard let value = T.from(string: nextValue) else {
|
||||
return .failure(argument.invalidUsageError(nextValue))
|
||||
}
|
||||
|
||||
values.append(value)
|
||||
}
|
||||
|
||||
return .success(values)
|
||||
|
||||
case .usage:
|
||||
return .failure(informativeUsageError(argument))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,191 +0,0 @@
|
|||
//
|
||||
// ArgumentParser.swift
|
||||
// Commandant
|
||||
//
|
||||
// Created by Justin Spahr-Summers on 2014-11-21.
|
||||
// Copyright (c) 2014 Carthage. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Represents an argument passed on the command line.
|
||||
private enum RawArgument: Equatable {
|
||||
/// A key corresponding to an option (e.g., `verbose` for `--verbose`).
|
||||
case key(String)
|
||||
|
||||
/// A value, either associated with an option or passed as a positional
|
||||
/// argument.
|
||||
case value(String)
|
||||
|
||||
/// One or more flag arguments (e.g 'r' and 'f' for `-rf`)
|
||||
case flag(OrderedSet<Character>)
|
||||
}
|
||||
|
||||
private func ==(lhs: RawArgument, rhs: RawArgument) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case let (.key(left), .key(right)):
|
||||
return left == right
|
||||
|
||||
case let (.value(left), .value(right)):
|
||||
return left == right
|
||||
|
||||
case let (.flag(left), .flag(right)):
|
||||
return left == right
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
extension RawArgument: CustomStringConvertible {
|
||||
fileprivate var description: String {
|
||||
switch self {
|
||||
case let .key(key):
|
||||
return "--\(key)"
|
||||
|
||||
case let .value(value):
|
||||
return "\"\(value)\""
|
||||
|
||||
case let .flag(flags):
|
||||
return "-\(String(flags))"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Destructively parses a list of command-line arguments.
|
||||
public final class ArgumentParser {
|
||||
/// The remaining arguments to be extracted, in their raw form.
|
||||
private var rawArguments: [RawArgument] = []
|
||||
|
||||
/// Initializes the generator from a simple list of command-line arguments.
|
||||
public init(_ arguments: [String]) {
|
||||
// The first instance of `--` terminates the option list.
|
||||
let params = arguments.split(maxSplits: 1, omittingEmptySubsequences: false) { $0 == "--" }
|
||||
|
||||
// Parse out the keyed and flag options.
|
||||
let options = params.first!
|
||||
rawArguments.append(contentsOf: options.map { arg in
|
||||
if arg.hasPrefix("-") {
|
||||
// Do we have `--{key}` or `-{flags}`.
|
||||
let opt = arg.dropFirst()
|
||||
if opt.first == "-" {
|
||||
return .key(String(opt.dropFirst()))
|
||||
} else {
|
||||
return .flag(OrderedSet(opt))
|
||||
}
|
||||
} else {
|
||||
return .value(arg)
|
||||
}
|
||||
})
|
||||
|
||||
// Remaining arguments are all positional parameters.
|
||||
if params.count == 2 {
|
||||
let positional = params.last!
|
||||
rawArguments.append(contentsOf: positional.map(RawArgument.value))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the remaining arguments.
|
||||
internal var remainingArguments: [String]? {
|
||||
return rawArguments.isEmpty ? nil : rawArguments.map { $0.description }
|
||||
}
|
||||
|
||||
/// Returns whether the given key was enabled or disabled, or nil if it
|
||||
/// was not given at all.
|
||||
///
|
||||
/// If the key is found, it is then removed from the list of arguments
|
||||
/// remaining to be parsed.
|
||||
internal func consumeBoolean(forKey key: String) -> Bool? {
|
||||
let oldArguments = rawArguments
|
||||
rawArguments.removeAll()
|
||||
|
||||
var result: Bool?
|
||||
for arg in oldArguments {
|
||||
if arg == .key(key) {
|
||||
result = true
|
||||
} else if arg == .key("no-\(key)") {
|
||||
result = false
|
||||
} else {
|
||||
rawArguments.append(arg)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/// Returns the value associated with the given flag, or nil if the flag was
|
||||
/// not specified. If the key is presented, but no value was given, an error
|
||||
/// is returned.
|
||||
///
|
||||
/// If a value is found, the key and the value are both removed from the
|
||||
/// list of arguments remaining to be parsed.
|
||||
internal func consumeValue(forKey key: String) -> Result<String?, CommandantError<NoError>> {
|
||||
let oldArguments = rawArguments
|
||||
rawArguments.removeAll()
|
||||
|
||||
var foundValue: String?
|
||||
var index = 0
|
||||
|
||||
while index < oldArguments.count {
|
||||
defer { index += 1 }
|
||||
let arg = oldArguments[index]
|
||||
|
||||
guard arg == .key(key) else {
|
||||
rawArguments.append(arg)
|
||||
continue
|
||||
}
|
||||
|
||||
index += 1
|
||||
guard index < oldArguments.count, case let .value(value) = oldArguments[index] else {
|
||||
return .failure(missingArgumentError("--\(key)"))
|
||||
}
|
||||
|
||||
foundValue = value
|
||||
}
|
||||
|
||||
return .success(foundValue)
|
||||
}
|
||||
|
||||
/// Returns the next positional argument that hasn't yet been returned, or
|
||||
/// nil if there are no more positional arguments.
|
||||
internal func consumePositionalArgument() -> String? {
|
||||
for (index, arg) in rawArguments.enumerated() {
|
||||
if case let .value(value) = arg {
|
||||
rawArguments.remove(at: index)
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/// Returns whether the given key was specified and removes it from the
|
||||
/// list of arguments remaining.
|
||||
internal func consume(key: String) -> Bool {
|
||||
let oldArguments = rawArguments
|
||||
rawArguments = oldArguments.filter { $0 != .key(key) }
|
||||
|
||||
return rawArguments.count < oldArguments.count
|
||||
}
|
||||
|
||||
/// Returns whether the given flag was specified and removes it from the
|
||||
/// list of arguments remaining.
|
||||
internal func consumeBoolean(flag: Character) -> Bool {
|
||||
for (index, arg) in rawArguments.enumerated() {
|
||||
if case let .flag(flags) = arg, flags.contains(flag) {
|
||||
var flags = flags
|
||||
flags.remove(flag)
|
||||
|
||||
if flags.isEmpty {
|
||||
rawArguments.remove(at: index)
|
||||
} else {
|
||||
rawArguments[index] = .flag(flags)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
//
|
||||
// ArgumentProtocol.swift
|
||||
// Commandant
|
||||
//
|
||||
// Created by Syo Ikeda on 12/14/15.
|
||||
// Copyright (c) 2015 Carthage. All rights reserved.
|
||||
//
|
||||
|
||||
/// Represents a value that can be converted from a command-line argument.
|
||||
public protocol ArgumentProtocol {
|
||||
/// A human-readable name for this type.
|
||||
static var name: String { get }
|
||||
|
||||
/// Attempts to parse a value from the given command-line argument.
|
||||
static func from(string: String) -> Self?
|
||||
}
|
||||
|
||||
extension Int: ArgumentProtocol {
|
||||
public static let name = "integer"
|
||||
|
||||
public static func from(string: String) -> Int? {
|
||||
return Int(string)
|
||||
}
|
||||
}
|
||||
|
||||
extension String: ArgumentProtocol {
|
||||
public static let name = "string"
|
||||
|
||||
public static func from(string: String) -> String? {
|
||||
return string
|
||||
}
|
||||
}
|
||||
|
||||
extension RawRepresentable where RawValue: StringProtocol, Self: ArgumentProtocol {
|
||||
public static func from(string: String) -> Self? {
|
||||
return RawValue(string).flatMap(Self.init(rawValue:))
|
||||
}
|
||||
}
|
||||
|
||||
extension RawRepresentable where RawValue: FixedWidthInteger, Self: ArgumentProtocol {
|
||||
public static func from(string: String) -> Self? {
|
||||
return RawValue(string).flatMap(Self.init(rawValue:))
|
||||
}
|
||||
}
|
|
@ -1,222 +0,0 @@
|
|||
//
|
||||
// Command.swift
|
||||
// Commandant
|
||||
//
|
||||
// Created by Justin Spahr-Summers on 2014-10-10.
|
||||
// Copyright (c) 2014 Carthage. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Represents a subcommand that can be executed with its own set of arguments.
|
||||
public protocol CommandProtocol {
|
||||
|
||||
/// The command's options type.
|
||||
associatedtype Options: OptionsProtocol
|
||||
|
||||
associatedtype ClientError: Error = Options.ClientError
|
||||
|
||||
/// The action that users should specify to use this subcommand (e.g.,
|
||||
/// `help`).
|
||||
var verb: String { get }
|
||||
|
||||
/// A human-readable, high-level description of what this command is used
|
||||
/// for.
|
||||
var function: String { get }
|
||||
|
||||
/// Runs this subcommand with the given options.
|
||||
func run(_ options: Options) -> Result<(), ClientError>
|
||||
}
|
||||
|
||||
/// A type-erased command.
|
||||
public struct CommandWrapper<ClientError: Error> {
|
||||
public let verb: String
|
||||
public let function: String
|
||||
|
||||
public let run: (ArgumentParser) -> Result<(), CommandantError<ClientError>>
|
||||
|
||||
public let usage: () -> CommandantError<ClientError>?
|
||||
|
||||
/// Creates a command that wraps another.
|
||||
fileprivate init<C: CommandProtocol>(_ command: C) where C.ClientError == ClientError, C.Options.ClientError == ClientError {
|
||||
verb = command.verb
|
||||
function = command.function
|
||||
run = { (arguments: ArgumentParser) -> Result<(), CommandantError<ClientError>> in
|
||||
let options = C.Options.evaluate(.arguments(arguments))
|
||||
|
||||
if let remainingArguments = arguments.remainingArguments {
|
||||
return .failure(unrecognizedArgumentsError(remainingArguments))
|
||||
}
|
||||
|
||||
switch options {
|
||||
case let .success(options):
|
||||
return command
|
||||
.run(options)
|
||||
.mapError(CommandantError.commandError)
|
||||
|
||||
case let .failure(error):
|
||||
return .failure(error)
|
||||
}
|
||||
}
|
||||
usage = { () -> CommandantError<ClientError>? in
|
||||
return C.Options.evaluate(.usage).error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes the "mode" in which a command should run.
|
||||
public enum CommandMode {
|
||||
/// Options should be parsed from the given command-line arguments.
|
||||
case arguments(ArgumentParser)
|
||||
|
||||
/// Each option should record its usage information in an error, for
|
||||
/// presentation to the user.
|
||||
case usage
|
||||
}
|
||||
|
||||
/// Maintains the list of commands available to run.
|
||||
public final class CommandRegistry<ClientError: Error> {
|
||||
private var commandsByVerb: [String: CommandWrapper<ClientError>] = [:]
|
||||
|
||||
/// All available commands.
|
||||
public var commands: [CommandWrapper<ClientError>] {
|
||||
return commandsByVerb.values.sorted { return $0.verb < $1.verb }
|
||||
}
|
||||
|
||||
public init() {}
|
||||
|
||||
/// Registers the given commands, making those available to run.
|
||||
///
|
||||
/// If another commands were already registered with the same `verb`s, those
|
||||
/// will be overwritten.
|
||||
@discardableResult
|
||||
public func register<C: CommandProtocol>(_ commands: C...)
|
||||
-> CommandRegistry
|
||||
where C.ClientError == ClientError, C.Options.ClientError == ClientError
|
||||
{
|
||||
for command in commands {
|
||||
commandsByVerb[command.verb] = CommandWrapper(command)
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
/// Runs the command corresponding to the given verb, passing it the given
|
||||
/// arguments.
|
||||
///
|
||||
/// Returns the results of the execution, or nil if no such command exists.
|
||||
public func run(command verb: String, arguments: [String]) -> Result<(), CommandantError<ClientError>>? {
|
||||
return self[verb]?.run(ArgumentParser(arguments))
|
||||
}
|
||||
|
||||
/// Returns the command matching the given verb, or nil if no such command
|
||||
/// is registered.
|
||||
public subscript(verb: String) -> CommandWrapper<ClientError>? {
|
||||
return commandsByVerb[verb]
|
||||
}
|
||||
}
|
||||
|
||||
extension CommandRegistry {
|
||||
/// Hands off execution to the CommandRegistry, by parsing CommandLine.arguments
|
||||
/// and then running whichever command has been identified in the argument
|
||||
/// list.
|
||||
///
|
||||
/// If the chosen command executes successfully, the process will exit with
|
||||
/// a successful exit code.
|
||||
///
|
||||
/// If the chosen command fails, the provided error handler will be invoked,
|
||||
/// then the process will exit with a failure exit code.
|
||||
///
|
||||
/// If a matching command could not be found but there is any `executable-verb`
|
||||
/// style subcommand executable in the caller's `$PATH`, the subcommand will
|
||||
/// be executed.
|
||||
///
|
||||
/// If a matching command could not be found or a usage error occurred,
|
||||
/// a helpful error message will be written to `stderr`, then the process
|
||||
/// will exit with a failure error code.
|
||||
public func main(defaultVerb: String, errorHandler: (ClientError) -> ()) -> Never {
|
||||
main(arguments: CommandLine.arguments, defaultVerb: defaultVerb, errorHandler: errorHandler)
|
||||
}
|
||||
|
||||
/// Hands off execution to the CommandRegistry, by parsing `arguments`
|
||||
/// and then running whichever command has been identified in the argument
|
||||
/// list.
|
||||
///
|
||||
/// If the chosen command executes successfully, the process will exit with
|
||||
/// a successful exit code.
|
||||
///
|
||||
/// If the chosen command fails, the provided error handler will be invoked,
|
||||
/// then the process will exit with a failure exit code.
|
||||
///
|
||||
/// If a matching command could not be found but there is any `executable-verb`
|
||||
/// style subcommand executable in the caller's `$PATH`, the subcommand will
|
||||
/// be executed.
|
||||
///
|
||||
/// If a matching command could not be found or a usage error occurred,
|
||||
/// a helpful error message will be written to `stderr`, then the process
|
||||
/// will exit with a failure error code.
|
||||
public func main(arguments: [String], defaultVerb: String, errorHandler: (ClientError) -> ()) -> Never {
|
||||
assert(arguments.count >= 1)
|
||||
|
||||
var arguments = arguments
|
||||
|
||||
// Extract the executable name.
|
||||
let executableName = arguments.remove(at: 0)
|
||||
|
||||
// use the default verb even if we have other arguments
|
||||
var verb = defaultVerb
|
||||
if let argument = arguments.first, !argument.hasPrefix("-") {
|
||||
verb = argument
|
||||
// Remove the command name.
|
||||
arguments.remove(at: 0)
|
||||
}
|
||||
|
||||
switch run(command: verb, arguments: arguments) {
|
||||
case .success?:
|
||||
exit(EXIT_SUCCESS)
|
||||
|
||||
case let .failure(error)?:
|
||||
switch error {
|
||||
case let .usageError(description):
|
||||
fputs(description + "\n", stderr)
|
||||
|
||||
case let .commandError(error):
|
||||
errorHandler(error)
|
||||
}
|
||||
|
||||
exit(EXIT_FAILURE)
|
||||
|
||||
case nil:
|
||||
if let subcommandExecuted = executeSubcommandIfExists(executableName, verb: verb, arguments: arguments) {
|
||||
exit(subcommandExecuted)
|
||||
}
|
||||
|
||||
fputs("Unrecognized command: '\(verb)'. See `\(executableName) help`.\n", stderr)
|
||||
exit(EXIT_FAILURE)
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds and executes a subcommand which exists in your $PATH. The executable
|
||||
/// name must be in the form of `executable-verb`.
|
||||
///
|
||||
/// - Returns: The exit status of found subcommand or nil.
|
||||
private func executeSubcommandIfExists(_ executableName: String, verb: String, arguments: [String]) -> Int32? {
|
||||
let subcommand = "\(NSString(string: executableName).lastPathComponent)-\(verb)"
|
||||
|
||||
func launchTask(_ path: String, arguments: [String]) -> Int32 {
|
||||
let task = Process()
|
||||
task.launchPath = path
|
||||
task.arguments = arguments
|
||||
|
||||
task.launch()
|
||||
task.waitUntilExit()
|
||||
|
||||
return task.terminationStatus
|
||||
}
|
||||
|
||||
guard launchTask("/usr/bin/which", arguments: [ "-s", subcommand ]) == 0 else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return launchTask("/usr/bin/env", arguments: [ subcommand ] + arguments)
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
//
|
||||
// Commandant.h
|
||||
// Commandant
|
||||
//
|
||||
// Created by Justin Spahr-Summers on 2014-11-21.
|
||||
// Copyright (c) 2014 Carthage. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
//! Project version number for Commandant.
|
||||
FOUNDATION_EXPORT double CommandantVersionNumber;
|
||||
|
||||
//! Project version string for Commandant.
|
||||
FOUNDATION_EXPORT const unsigned char CommandantVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <Commandant/PublicHeader.h>
|
|
@ -1,153 +0,0 @@
|
|||
//
|
||||
// Errors.swift
|
||||
// Commandant
|
||||
//
|
||||
// Created by Justin Spahr-Summers on 2014-10-24.
|
||||
// Copyright (c) 2014 Carthage. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Possible errors that can originate from Commandant.
|
||||
///
|
||||
/// `ClientError` should be the type of error (if any) that can occur when
|
||||
/// running commands.
|
||||
public enum CommandantError<ClientError>: Error {
|
||||
/// An option was used incorrectly.
|
||||
case usageError(description: String)
|
||||
|
||||
/// An error occurred while running a command.
|
||||
case commandError(ClientError)
|
||||
}
|
||||
|
||||
extension CommandantError: CustomStringConvertible {
|
||||
public var description: String {
|
||||
switch self {
|
||||
case let .usageError(description):
|
||||
return description
|
||||
|
||||
case let .commandError(error):
|
||||
return String(describing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs an `InvalidArgument` error that indicates a missing value for
|
||||
/// the argument by the given name.
|
||||
internal func missingArgumentError<ClientError>(_ argumentName: String) -> CommandantError<ClientError> {
|
||||
let description = "Missing argument for \(argumentName)"
|
||||
return .usageError(description: description)
|
||||
}
|
||||
|
||||
/// Constructs an error by combining the example of key (and value, if applicable)
|
||||
/// with the usage description.
|
||||
internal func informativeUsageError<ClientError>(_ keyValueExample: String, usage: String) -> CommandantError<ClientError> {
|
||||
let lines = usage.components(separatedBy: .newlines)
|
||||
|
||||
return .usageError(description: lines.reduce(keyValueExample) { previous, value in
|
||||
return previous + "\n\t" + value
|
||||
})
|
||||
}
|
||||
|
||||
/// Combines the text of the two errors, if they're both `UsageError`s.
|
||||
/// Otherwise, uses whichever one is not (biased toward the left).
|
||||
internal func combineUsageErrors<ClientError>(_ lhs: CommandantError<ClientError>, _ rhs: CommandantError<ClientError>) -> CommandantError<ClientError> {
|
||||
switch (lhs, rhs) {
|
||||
case let (.usageError(left), .usageError(right)):
|
||||
let combinedDescription = "\(left)\n\n\(right)"
|
||||
return .usageError(description: combinedDescription)
|
||||
|
||||
case (.usageError, _):
|
||||
return rhs
|
||||
|
||||
case (_, .usageError), (_, _):
|
||||
return lhs
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs an error that indicates unrecognized arguments remains.
|
||||
internal func unrecognizedArgumentsError<ClientError>(_ options: [String]) -> CommandantError<ClientError> {
|
||||
return .usageError(description: "Unrecognized arguments: " + options.joined(separator: ", "))
|
||||
}
|
||||
|
||||
// MARK: Argument
|
||||
|
||||
/// Constructs an error that describes how to use the argument, with the given
|
||||
/// example of value usage if applicable.
|
||||
internal func informativeUsageError<T, ClientError>(_ valueExample: String, argument: Argument<T>) -> CommandantError<ClientError> {
|
||||
if argument.defaultValue != nil {
|
||||
return informativeUsageError("[\(valueExample)]", usage: argument.usage)
|
||||
} else {
|
||||
return informativeUsageError(valueExample, usage: argument.usage)
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs an error that describes how to use the argument.
|
||||
internal func informativeUsageError<T: ArgumentProtocol, ClientError>(_ argument: Argument<T>) -> CommandantError<ClientError> {
|
||||
var example = ""
|
||||
|
||||
var valueExample = ""
|
||||
if let defaultValue = argument.defaultValue {
|
||||
valueExample = "\(defaultValue)"
|
||||
}
|
||||
|
||||
if valueExample.isEmpty {
|
||||
example += "(\(T.name))"
|
||||
} else {
|
||||
example += valueExample
|
||||
}
|
||||
|
||||
return informativeUsageError(example, argument: argument)
|
||||
}
|
||||
|
||||
/// Constructs an error that describes how to use the argument list.
|
||||
internal func informativeUsageError<T: ArgumentProtocol, ClientError>(_ argument: Argument<[T]>) -> CommandantError<ClientError> {
|
||||
var example = ""
|
||||
|
||||
var valueExample = ""
|
||||
if let defaultValue = argument.defaultValue {
|
||||
valueExample = "\(defaultValue)"
|
||||
}
|
||||
|
||||
if valueExample.isEmpty {
|
||||
example += "(\(T.name))"
|
||||
} else {
|
||||
example += valueExample
|
||||
}
|
||||
|
||||
return informativeUsageError(example, argument: argument)
|
||||
}
|
||||
|
||||
// MARK: Option
|
||||
|
||||
/// Constructs an error that describes how to use the option, with the given
|
||||
/// example of key (and value, if applicable) usage.
|
||||
internal func informativeUsageError<T, ClientError>(_ keyValueExample: String, option: Option<T>) -> CommandantError<ClientError> {
|
||||
return informativeUsageError("[\(keyValueExample)]", usage: option.usage)
|
||||
}
|
||||
|
||||
/// Constructs an error that describes how to use the option.
|
||||
internal func informativeUsageError<T: ArgumentProtocol, ClientError>(_ option: Option<T>) -> CommandantError<ClientError> {
|
||||
return informativeUsageError("--\(option.key) \(option.defaultValue)", option: option)
|
||||
}
|
||||
|
||||
/// Constructs an error that describes how to use the option.
|
||||
internal func informativeUsageError<T: ArgumentProtocol, ClientError>(_ option: Option<T?>) -> CommandantError<ClientError> {
|
||||
return informativeUsageError("--\(option.key) (\(T.name))", option: option)
|
||||
}
|
||||
|
||||
/// Constructs an error that describes how to use the option.
|
||||
internal func informativeUsageError<T: ArgumentProtocol, ClientError>(_ option: Option<[T]>) -> CommandantError<ClientError> {
|
||||
return informativeUsageError("--\(option.key) (\(option.defaultValue))", option: option)
|
||||
}
|
||||
|
||||
/// Constructs an error that describes how to use the option.
|
||||
internal func informativeUsageError<T: ArgumentProtocol, ClientError>(_ option: Option<[T]?>) -> CommandantError<ClientError> {
|
||||
return informativeUsageError("--\(option.key) (\(T.name))", option: option)
|
||||
}
|
||||
|
||||
/// Constructs an error that describes how to use the given boolean option.
|
||||
internal func informativeUsageError<ClientError>(_ option: Option<Bool>) -> CommandantError<ClientError> {
|
||||
let key = option.key
|
||||
return informativeUsageError((option.defaultValue ? "--no-\(key)" : "--\(key)"), option: option)
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
//
|
||||
// HelpCommand.swift
|
||||
// Commandant
|
||||
//
|
||||
// Created by Justin Spahr-Summers on 2014-10-10.
|
||||
// Copyright (c) 2014 Carthage. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// A basic implementation of a `help` command, using information available in a
|
||||
/// `CommandRegistry`.
|
||||
///
|
||||
/// If you want to use this command, initialize it with the registry, then add
|
||||
/// it to that same registry:
|
||||
///
|
||||
/// let commands: CommandRegistry<MyErrorType> = …
|
||||
/// let helpCommand = HelpCommand(registry: commands)
|
||||
/// commands.register(helpCommand)
|
||||
public struct HelpCommand<ClientError: Error>: CommandProtocol {
|
||||
public typealias Options = HelpOptions<ClientError>
|
||||
|
||||
public let verb = "help"
|
||||
public let function = "Display general or command-specific help"
|
||||
|
||||
private let registry: CommandRegistry<ClientError>
|
||||
|
||||
/// Initializes the command to provide help from the given registry of
|
||||
/// commands.
|
||||
public init(registry: CommandRegistry<ClientError>) {
|
||||
self.registry = registry
|
||||
}
|
||||
|
||||
public func run(_ options: Options) -> Result<(), ClientError> {
|
||||
if let verb = options.verb {
|
||||
if let command = self.registry[verb] {
|
||||
print(command.function)
|
||||
if let usageError = command.usage() {
|
||||
print("\n\(usageError)")
|
||||
}
|
||||
return .success(())
|
||||
} else {
|
||||
fputs("Unrecognized command: '\(verb)'\n", stderr)
|
||||
}
|
||||
}
|
||||
|
||||
print("Available commands:\n")
|
||||
|
||||
let maxVerbLength = self.registry.commands.map { $0.verb.count }.max() ?? 0
|
||||
|
||||
for command in self.registry.commands {
|
||||
let padding = repeatElement(Character(" "), count: maxVerbLength - command.verb.count)
|
||||
print(" \(command.verb)\(String(padding)) \(command.function)")
|
||||
}
|
||||
|
||||
return .success(())
|
||||
}
|
||||
}
|
||||
|
||||
public struct HelpOptions<ClientError: Error>: OptionsProtocol {
|
||||
fileprivate let verb: String?
|
||||
|
||||
private init(verb: String?) {
|
||||
self.verb = verb
|
||||
}
|
||||
|
||||
private static func create(_ verb: String) -> HelpOptions {
|
||||
return self.init(verb: (verb == "" ? nil : verb))
|
||||
}
|
||||
|
||||
public static func evaluate(_ m: CommandMode) -> Result<HelpOptions, CommandantError<ClientError>> {
|
||||
return create
|
||||
<*> m <| Argument(defaultValue: "", usage: "the command to display help for")
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.13.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2014 Carthage. All rights reserved.</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -1,273 +0,0 @@
|
|||
//
|
||||
// Option.swift
|
||||
// Commandant
|
||||
//
|
||||
// Created by Justin Spahr-Summers on 2014-11-21.
|
||||
// Copyright (c) 2014 Carthage. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Represents a record of options for a command, which can be parsed from
|
||||
/// a list of command-line arguments.
|
||||
///
|
||||
/// This is most helpful when used in conjunction with the `Option` and `Switch`
|
||||
/// types, and `<*>` and `<|` combinators.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// struct LogOptions: OptionsProtocol {
|
||||
/// let verbosity: Int
|
||||
/// let outputFilename: String
|
||||
/// let shouldDelete: Bool
|
||||
/// let logName: String
|
||||
///
|
||||
/// static func create(_ verbosity: Int) -> (String) -> (Bool) -> (String) -> LogOptions {
|
||||
/// return { outputFilename in { shouldDelete in { logName in LogOptions(verbosity: verbosity, outputFilename: outputFilename, shouldDelete: shouldDelete, logName: logName) } } }
|
||||
/// }
|
||||
///
|
||||
/// static func evaluate(_ m: CommandMode) -> Result<LogOptions, CommandantError<YourErrorType>> {
|
||||
/// return create
|
||||
/// <*> m <| Option(key: "verbose", defaultValue: 0, usage: "the verbosity level with which to read the logs")
|
||||
/// <*> m <| Option(key: "outputFilename", defaultValue: "", usage: "a file to print output to, instead of stdout")
|
||||
/// <*> m <| Switch(flag: "d", key: "delete", usage: "delete the logs when finished")
|
||||
/// <*> m <| Argument(usage: "the log to read")
|
||||
/// }
|
||||
/// }
|
||||
public protocol OptionsProtocol {
|
||||
associatedtype ClientError: Error
|
||||
|
||||
/// Evaluates this set of options in the given mode.
|
||||
///
|
||||
/// Returns the parsed options or a `UsageError`.
|
||||
static func evaluate(_ m: CommandMode) -> Result<Self, CommandantError<ClientError>>
|
||||
}
|
||||
|
||||
/// An `OptionsProtocol` that has no options.
|
||||
public struct NoOptions<ClientError: Error>: OptionsProtocol {
|
||||
public init() {}
|
||||
|
||||
public static func evaluate(_ m: CommandMode) -> Result<NoOptions, CommandantError<ClientError>> {
|
||||
return .success(NoOptions())
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes an option that can be provided on the command line.
|
||||
public struct Option<T> {
|
||||
/// The key that controls this option. For example, a key of `verbose` would
|
||||
/// be used for a `--verbose` option.
|
||||
public let key: String
|
||||
|
||||
/// The default value for this option. This is the value that will be used
|
||||
/// if the option is never explicitly specified on the command line.
|
||||
public let defaultValue: T
|
||||
|
||||
/// A human-readable string describing the purpose of this option. This will
|
||||
/// be shown in help messages.
|
||||
///
|
||||
/// For boolean operations, this should describe the effect of _not_ using
|
||||
/// the default value (i.e., what will happen if you disable/enable the flag
|
||||
/// differently from the default).
|
||||
public let usage: String
|
||||
|
||||
public init(key: String, defaultValue: T, usage: String) {
|
||||
self.key = key
|
||||
self.defaultValue = defaultValue
|
||||
self.usage = usage
|
||||
}
|
||||
}
|
||||
|
||||
extension Option: CustomStringConvertible {
|
||||
public var description: String {
|
||||
return "--\(key)"
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Operators
|
||||
|
||||
// Inspired by the Argo library:
|
||||
// https://github.com/thoughtbot/Argo
|
||||
/*
|
||||
Copyright (c) 2014 thoughtbot, inc.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
infix operator <*> : LogicalDisjunctionPrecedence
|
||||
|
||||
infix operator <| : MultiplicationPrecedence
|
||||
|
||||
/// Applies `f` to the value in the given result.
|
||||
///
|
||||
/// In the context of command-line option parsing, this is used to chain
|
||||
/// together the parsing of multiple arguments. See OptionsProtocol for an example.
|
||||
public func <*> <T, U, ClientError>(f: (T) -> U, value: Result<T, CommandantError<ClientError>>) -> Result<U, CommandantError<ClientError>> {
|
||||
return value.map(f)
|
||||
}
|
||||
|
||||
/// Applies the function in `f` to the value in the given result.
|
||||
///
|
||||
/// In the context of command-line option parsing, this is used to chain
|
||||
/// together the parsing of multiple arguments. See OptionsProtocol for an example.
|
||||
public func <*> <T, U, ClientError>(f: Result<((T) -> U), CommandantError<ClientError>>, value: Result<T, CommandantError<ClientError>>) -> Result<U, CommandantError<ClientError>> {
|
||||
switch (f, value) {
|
||||
case let (.failure(left), .failure(right)):
|
||||
return .failure(combineUsageErrors(left, right))
|
||||
|
||||
case let (.failure(left), .success):
|
||||
return .failure(left)
|
||||
|
||||
case let (.success, .failure(right)):
|
||||
return .failure(right)
|
||||
|
||||
case let (.success(f), .success(value)):
|
||||
let newValue = f(value)
|
||||
return .success(newValue)
|
||||
}
|
||||
}
|
||||
|
||||
extension CommandMode {
|
||||
/// Evaluates the given option in the given mode.
|
||||
///
|
||||
/// If parsing command line arguments, and no value was specified on the command
|
||||
/// line, the option's `defaultValue` is used.
|
||||
public static func <| <T: ArgumentProtocol, ClientError>(mode: CommandMode, option: Option<T>) -> Result<T, CommandantError<ClientError>> {
|
||||
let wrapped = Option<T?>(key: option.key, defaultValue: option.defaultValue, usage: option.usage)
|
||||
// Since we are passing a non-nil default value, we can safely unwrap the
|
||||
// result.
|
||||
return (mode <| wrapped).map { $0! }
|
||||
}
|
||||
|
||||
/// Evaluates the given option in the given mode.
|
||||
///
|
||||
/// If parsing command line arguments, and no value was specified on the command
|
||||
/// line, `nil` is used.
|
||||
public static func <| <T: ArgumentProtocol, ClientError>(mode: CommandMode, option: Option<T?>) -> Result<T?, CommandantError<ClientError>> {
|
||||
let key = option.key
|
||||
switch mode {
|
||||
case let .arguments(arguments):
|
||||
var stringValue: String?
|
||||
switch arguments.consumeValue(forKey: key) {
|
||||
case let .success(value):
|
||||
stringValue = value
|
||||
|
||||
case let .failure(error):
|
||||
switch error {
|
||||
case let .usageError(description):
|
||||
return .failure(.usageError(description: description))
|
||||
|
||||
case .commandError:
|
||||
fatalError("CommandError should be impossible when parameterized over NoError")
|
||||
}
|
||||
}
|
||||
|
||||
if let stringValue = stringValue {
|
||||
if let value = T.from(string: stringValue) {
|
||||
return .success(value)
|
||||
}
|
||||
|
||||
let description = "Invalid value for '--\(key)': \(stringValue)"
|
||||
return .failure(.usageError(description: description))
|
||||
} else {
|
||||
return .success(option.defaultValue)
|
||||
}
|
||||
|
||||
case .usage:
|
||||
return .failure(informativeUsageError(option))
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluates the given option in the given mode.
|
||||
///
|
||||
/// If parsing command line arguments, and no value was specified on the command
|
||||
/// line, the option's `defaultValue` is used.
|
||||
public static func <| <T: ArgumentProtocol, ClientError>(mode: CommandMode, option: Option<[T]>) -> Result<[T], CommandantError<ClientError>> {
|
||||
let wrapped = Option<[T]?>(key: option.key, defaultValue: option.defaultValue, usage: option.usage)
|
||||
// Since we are passing a non-nil default value, we can safely unwrap the
|
||||
// result.
|
||||
return (mode <| wrapped).map { $0! }
|
||||
}
|
||||
|
||||
/// Evaluates the given option in the given mode.
|
||||
///
|
||||
/// If parsing command line arguments, and no value was specified on the command
|
||||
/// line, `nil` is used.
|
||||
public static func <| <T: ArgumentProtocol, ClientError>(mode: CommandMode, option: Option<[T]?>) -> Result<[T]?, CommandantError<ClientError>> {
|
||||
let key = option.key
|
||||
|
||||
switch mode {
|
||||
case let .arguments(arguments):
|
||||
let stringValue: String?
|
||||
switch arguments.consumeValue(forKey: key) {
|
||||
case let .success(value):
|
||||
stringValue = value
|
||||
|
||||
case let .failure(error):
|
||||
switch error {
|
||||
case let .usageError(description):
|
||||
return .failure(.usageError(description: description))
|
||||
|
||||
case .commandError:
|
||||
fatalError("CommandError should be impossible when parameterized over NoError")
|
||||
}
|
||||
}
|
||||
|
||||
guard let unwrappedStringValue = stringValue else {
|
||||
return .success(option.defaultValue)
|
||||
}
|
||||
|
||||
let components = unwrappedStringValue.split(
|
||||
omittingEmptySubsequences: true,
|
||||
whereSeparator: [",", " "].contains
|
||||
)
|
||||
var resultValues: [T] = []
|
||||
for component in components {
|
||||
guard let value = T.from(string: String(component)) else {
|
||||
let description = "Invalid value for '--\(key)': \(unwrappedStringValue)"
|
||||
return .failure(.usageError(description: description))
|
||||
}
|
||||
resultValues.append(value)
|
||||
}
|
||||
return .success(resultValues)
|
||||
|
||||
case .usage:
|
||||
return .failure(informativeUsageError(option))
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluates the given boolean option in the given mode.
|
||||
///
|
||||
/// If parsing command line arguments, and no value was specified on the command
|
||||
/// line, the option's `defaultValue` is used.
|
||||
public static func <| <ClientError>(mode: CommandMode, option: Option<Bool>) -> Result<Bool, CommandantError<ClientError>> {
|
||||
switch mode {
|
||||
case let .arguments(arguments):
|
||||
if let value = arguments.consumeBoolean(forKey: option.key) {
|
||||
return .success(value)
|
||||
} else {
|
||||
return .success(option.defaultValue)
|
||||
}
|
||||
|
||||
case .usage:
|
||||
return .failure(informativeUsageError(option))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/// A poor man's ordered set.
|
||||
internal struct OrderedSet<T: Hashable> {
|
||||
fileprivate var values: [T] = []
|
||||
|
||||
init<S: Sequence>(_ sequence: S) where S.Element == T {
|
||||
for e in sequence where !values.contains(e) {
|
||||
values.append(e)
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
mutating func remove(_ member: T) -> T? {
|
||||
if let index = values.index(of: member) {
|
||||
return values.remove(at: index)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension OrderedSet: Equatable {
|
||||
static func == (_ lhs: OrderedSet, rhs: OrderedSet) -> Bool {
|
||||
return lhs.values == rhs.values
|
||||
}
|
||||
}
|
||||
|
||||
extension OrderedSet: Collection {
|
||||
subscript(position: Int) -> T {
|
||||
return values[position]
|
||||
}
|
||||
|
||||
var count: Int {
|
||||
return values.count
|
||||
}
|
||||
|
||||
var isEmpty: Bool {
|
||||
return values.isEmpty
|
||||
}
|
||||
|
||||
var startIndex: Int {
|
||||
return values.startIndex
|
||||
}
|
||||
|
||||
var endIndex: Int {
|
||||
return values.endIndex
|
||||
}
|
||||
|
||||
func index(after i: Int) -> Int {
|
||||
return values.index(after: i)
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
//
|
||||
// Switch.swift
|
||||
// Commandant
|
||||
//
|
||||
// Created by Neil Pankey on 3/31/15.
|
||||
// Copyright (c) 2015 Carthage. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
/// Describes a parameterless command line flag that defaults to false and can only
|
||||
/// be switched on. Canonical examples include `--force` and `--recurse`.
|
||||
///
|
||||
/// For a boolean toggle that can be enabled and disabled use `Option<Bool>`.
|
||||
public struct Switch {
|
||||
/// The key that enables this switch. For example, a key of `verbose` would be
|
||||
/// used for a `--verbose` option.
|
||||
public let key: String
|
||||
|
||||
/// Optional single letter flag that enables this switch. For example, `-v` would
|
||||
/// be used as a shorthand for `--verbose`.
|
||||
///
|
||||
/// Multiple flags can be grouped together as a single argument and will split
|
||||
/// when parsing (e.g. `rm -rf` treats 'r' and 'f' as inidividual flags).
|
||||
public let flag: Character?
|
||||
|
||||
/// A human-readable string describing the purpose of this option. This will
|
||||
/// be shown in help messages.
|
||||
public let usage: String
|
||||
|
||||
public init(flag: Character? = nil, key: String, usage: String) {
|
||||
self.flag = flag
|
||||
self.key = key
|
||||
self.usage = usage
|
||||
}
|
||||
}
|
||||
|
||||
extension Switch: CustomStringConvertible {
|
||||
public var description: String {
|
||||
var options = "--\(key)"
|
||||
if let flag = self.flag {
|
||||
options += "|-\(flag)"
|
||||
}
|
||||
return options
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Operators
|
||||
|
||||
extension CommandMode {
|
||||
/// Evaluates the given boolean switch in the given mode.
|
||||
///
|
||||
/// If parsing command line arguments, and no value was specified on the command
|
||||
/// line, the option's `defaultValue` is used.
|
||||
public static func <| <ClientError> (mode: CommandMode, option: Switch) -> Result<Bool, CommandantError<ClientError>> {
|
||||
switch mode {
|
||||
case let .arguments(arguments):
|
||||
var enabled = arguments.consume(key: option.key)
|
||||
|
||||
if let flag = option.flag, !enabled {
|
||||
enabled = arguments.consumeBoolean(flag: flag)
|
||||
}
|
||||
return .success(enabled)
|
||||
|
||||
case .usage:
|
||||
return .failure(informativeUsageError(option.description, usage: option.usage))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
// Copyright (c) 2015 Rob Rix. All rights reserved.
|
||||
|
||||
/// Project version number for Result.
|
||||
extern double ResultVersionNumber;
|
||||
|
||||
/// Project version string for Result.
|
||||
extern const unsigned char ResultVersionString[];
|
||||
|
|
@ -1,276 +0,0 @@
|
|||
// Copyright (c) 2015 Rob Rix. All rights reserved.
|
||||
|
||||
/// An enum representing either a failure with an explanatory error, or a success with a result value.
|
||||
public enum Result<T, Error: Swift.Error>: ResultProtocol, CustomStringConvertible, CustomDebugStringConvertible {
|
||||
case success(T)
|
||||
case failure(Error)
|
||||
|
||||
// MARK: Constructors
|
||||
|
||||
/// Constructs a success wrapping a `value`.
|
||||
public init(value: T) {
|
||||
self = .success(value)
|
||||
}
|
||||
|
||||
/// Constructs a failure wrapping an `error`.
|
||||
public init(error: Error) {
|
||||
self = .failure(error)
|
||||
}
|
||||
|
||||
/// Constructs a result from an `Optional`, failing with `Error` if `nil`.
|
||||
public init(_ value: T?, failWith: @autoclosure () -> Error) {
|
||||
self = value.map(Result.success) ?? .failure(failWith())
|
||||
}
|
||||
|
||||
/// Constructs a result from a function that uses `throw`, failing with `Error` if throws.
|
||||
public init(_ f: @autoclosure () throws -> T) {
|
||||
self.init(attempt: f)
|
||||
}
|
||||
|
||||
/// Constructs a result from a function that uses `throw`, failing with `Error` if throws.
|
||||
public init(attempt f: () throws -> T) {
|
||||
do {
|
||||
self = .success(try f())
|
||||
} catch var error {
|
||||
if Error.self == AnyError.self {
|
||||
error = AnyError(error)
|
||||
}
|
||||
self = .failure(error as! Error)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Deconstruction
|
||||
|
||||
/// Returns the value from `success` Results or `throw`s the error.
|
||||
public func dematerialize() throws -> T {
|
||||
switch self {
|
||||
case let .success(value):
|
||||
return value
|
||||
case let .failure(error):
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/// Case analysis for Result.
|
||||
///
|
||||
/// Returns the value produced by applying `ifFailure` to `failure` Results, or `ifSuccess` to `success` Results.
|
||||
public func analysis<Result>(ifSuccess: (T) -> Result, ifFailure: (Error) -> Result) -> Result {
|
||||
switch self {
|
||||
case let .success(value):
|
||||
return ifSuccess(value)
|
||||
case let .failure(value):
|
||||
return ifFailure(value)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Errors
|
||||
|
||||
/// The domain for errors constructed by Result.
|
||||
public static var errorDomain: String { return "com.antitypical.Result" }
|
||||
|
||||
/// The userInfo key for source functions in errors constructed by Result.
|
||||
public static var functionKey: String { return "\(errorDomain).function" }
|
||||
|
||||
/// The userInfo key for source file paths in errors constructed by Result.
|
||||
public static var fileKey: String { return "\(errorDomain).file" }
|
||||
|
||||
/// The userInfo key for source file line numbers in errors constructed by Result.
|
||||
public static var lineKey: String { return "\(errorDomain).line" }
|
||||
|
||||
/// Constructs an error.
|
||||
public static func error(_ message: String? = nil, function: String = #function, file: String = #file, line: Int = #line) -> NSError {
|
||||
var userInfo: [String: Any] = [
|
||||
functionKey: function,
|
||||
fileKey: file,
|
||||
lineKey: line,
|
||||
]
|
||||
|
||||
if let message = message {
|
||||
userInfo[NSLocalizedDescriptionKey] = message
|
||||
}
|
||||
|
||||
return NSError(domain: errorDomain, code: 0, userInfo: userInfo)
|
||||
}
|
||||
|
||||
|
||||
// MARK: CustomStringConvertible
|
||||
|
||||
public var description: String {
|
||||
return analysis(
|
||||
ifSuccess: { ".success(\($0))" },
|
||||
ifFailure: { ".failure(\($0))" })
|
||||
}
|
||||
|
||||
|
||||
// MARK: CustomDebugStringConvertible
|
||||
|
||||
public var debugDescription: String {
|
||||
return description
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Derive result from failable closure
|
||||
|
||||
public func materialize<T>(_ f: () throws -> T) -> Result<T, AnyError> {
|
||||
return materialize(try f())
|
||||
}
|
||||
|
||||
public func materialize<T>(_ f: @autoclosure () throws -> T) -> Result<T, AnyError> {
|
||||
do {
|
||||
return .success(try f())
|
||||
} catch {
|
||||
return .failure(AnyError(error))
|
||||
}
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "Use the overload which returns `Result<T, AnyError>` instead")
|
||||
public func materialize<T>(_ f: () throws -> T) -> Result<T, NSError> {
|
||||
return materialize(try f())
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "Use the overload which returns `Result<T, AnyError>` instead")
|
||||
public func materialize<T>(_ f: @autoclosure () throws -> T) -> Result<T, NSError> {
|
||||
do {
|
||||
return .success(try f())
|
||||
} catch {
|
||||
// This isn't great, but it lets us maintain compatibility until this deprecated
|
||||
// method can be removed.
|
||||
#if _runtime(_ObjC)
|
||||
return .failure(error as NSError)
|
||||
#else
|
||||
// https://github.com/apple/swift-corelibs-foundation/blob/swift-3.0.2-RELEASE/Foundation/NSError.swift#L314
|
||||
let userInfo = _swift_Foundation_getErrorDefaultUserInfo(error) as? [String: Any]
|
||||
let nsError = NSError(domain: error._domain, code: error._code, userInfo: userInfo)
|
||||
return .failure(nsError)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Cocoa API conveniences
|
||||
|
||||
#if !os(Linux)
|
||||
|
||||
/// Constructs a `Result` with the result of calling `try` with an error pointer.
|
||||
///
|
||||
/// This is convenient for wrapping Cocoa API which returns an object or `nil` + an error, by reference. e.g.:
|
||||
///
|
||||
/// Result.try { NSData(contentsOfURL: URL, options: .dataReadingMapped, error: $0) }
|
||||
@available(*, deprecated, message: "This will be removed in Result 4.0. Use `Result.init(attempt:)` instead. See https://github.com/antitypical/Result/issues/85 for the details.")
|
||||
public func `try`<T>(_ function: String = #function, file: String = #file, line: Int = #line, `try`: (NSErrorPointer) -> T?) -> Result<T, NSError> {
|
||||
var error: NSError?
|
||||
return `try`(&error).map(Result.success) ?? .failure(error ?? Result<T, NSError>.error(function: function, file: file, line: line))
|
||||
}
|
||||
|
||||
/// Constructs a `Result` with the result of calling `try` with an error pointer.
|
||||
///
|
||||
/// This is convenient for wrapping Cocoa API which returns a `Bool` + an error, by reference. e.g.:
|
||||
///
|
||||
/// Result.try { NSFileManager.defaultManager().removeItemAtURL(URL, error: $0) }
|
||||
@available(*, deprecated, message: "This will be removed in Result 4.0. Use `Result.init(attempt:)` instead. See https://github.com/antitypical/Result/issues/85 for the details.")
|
||||
public func `try`(_ function: String = #function, file: String = #file, line: Int = #line, `try`: (NSErrorPointer) -> Bool) -> Result<(), NSError> {
|
||||
var error: NSError?
|
||||
return `try`(&error) ?
|
||||
.success(())
|
||||
: .failure(error ?? Result<(), NSError>.error(function: function, file: file, line: line))
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// MARK: - ErrorConvertible conformance
|
||||
|
||||
extension NSError: ErrorConvertible {
|
||||
public static func error(from error: Swift.Error) -> Self {
|
||||
func cast<T: NSError>(_ error: Swift.Error) -> T {
|
||||
return error as! T
|
||||
}
|
||||
|
||||
return cast(error)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Errors
|
||||
|
||||
/// An “error” that is impossible to construct.
|
||||
///
|
||||
/// This can be used to describe `Result`s where failures will never
|
||||
/// be generated. For example, `Result<Int, NoError>` describes a result that
|
||||
/// contains an `Int`eger and is guaranteed never to be a `failure`.
|
||||
public enum NoError: Swift.Error, Equatable {
|
||||
public static func ==(lhs: NoError, rhs: NoError) -> Bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
/// A type-erased error which wraps an arbitrary error instance. This should be
|
||||
/// useful for generic contexts.
|
||||
public struct AnyError: Swift.Error {
|
||||
/// The underlying error.
|
||||
public let error: Swift.Error
|
||||
|
||||
public init(_ error: Swift.Error) {
|
||||
if let anyError = error as? AnyError {
|
||||
self = anyError
|
||||
} else {
|
||||
self.error = error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AnyError: ErrorConvertible {
|
||||
public static func error(from error: Error) -> AnyError {
|
||||
return AnyError(error)
|
||||
}
|
||||
}
|
||||
|
||||
extension AnyError: CustomStringConvertible {
|
||||
public var description: String {
|
||||
return String(describing: error)
|
||||
}
|
||||
}
|
||||
|
||||
// There appears to be a bug in Foundation on Linux which prevents this from working:
|
||||
// https://bugs.swift.org/browse/SR-3565
|
||||
// Don't forget to comment the tests back in when removing this check when it's fixed!
|
||||
#if !os(Linux)
|
||||
|
||||
extension AnyError: LocalizedError {
|
||||
public var errorDescription: String? {
|
||||
return error.localizedDescription
|
||||
}
|
||||
|
||||
public var failureReason: String? {
|
||||
return (error as? LocalizedError)?.failureReason
|
||||
}
|
||||
|
||||
public var helpAnchor: String? {
|
||||
return (error as? LocalizedError)?.helpAnchor
|
||||
}
|
||||
|
||||
public var recoverySuggestion: String? {
|
||||
return (error as? LocalizedError)?.recoverySuggestion
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// MARK: - migration support
|
||||
extension Result {
|
||||
@available(*, unavailable, renamed: "success")
|
||||
public static func Success(_: T) -> Result<T, Error> {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
@available(*, unavailable, renamed: "failure")
|
||||
public static func Failure(_: Error) -> Result<T, Error> {
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
|
||||
extension NSError {
|
||||
@available(*, unavailable, renamed: "error(from:)")
|
||||
public static func errorFromErrorType(_ error: Swift.Error) -> Self {
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
|
||||
import Foundation
|
|
@ -1,203 +0,0 @@
|
|||
// Copyright (c) 2015 Rob Rix. All rights reserved.
|
||||
|
||||
/// A type that can represent either failure with an error or success with a result value.
|
||||
public protocol ResultProtocol {
|
||||
associatedtype Value
|
||||
associatedtype Error: Swift.Error
|
||||
|
||||
/// Constructs a successful result wrapping a `value`.
|
||||
init(value: Value)
|
||||
|
||||
/// Constructs a failed result wrapping an `error`.
|
||||
init(error: Error)
|
||||
|
||||
/// Case analysis for ResultProtocol.
|
||||
///
|
||||
/// Returns the value produced by appliying `ifFailure` to the error if self represents a failure, or `ifSuccess` to the result value if self represents a success.
|
||||
func analysis<U>(ifSuccess: (Value) -> U, ifFailure: (Error) -> U) -> U
|
||||
|
||||
/// Returns the value if self represents a success, `nil` otherwise.
|
||||
///
|
||||
/// A default implementation is provided by a protocol extension. Conforming types may specialize it.
|
||||
var value: Value? { get }
|
||||
|
||||
/// Returns the error if self represents a failure, `nil` otherwise.
|
||||
///
|
||||
/// A default implementation is provided by a protocol extension. Conforming types may specialize it.
|
||||
var error: Error? { get }
|
||||
}
|
||||
|
||||
public extension ResultProtocol {
|
||||
|
||||
/// Returns the value if self represents a success, `nil` otherwise.
|
||||
public var value: Value? {
|
||||
return analysis(ifSuccess: { $0 }, ifFailure: { _ in nil })
|
||||
}
|
||||
|
||||
/// Returns the error if self represents a failure, `nil` otherwise.
|
||||
public var error: Error? {
|
||||
return analysis(ifSuccess: { _ in nil }, ifFailure: { $0 })
|
||||
}
|
||||
|
||||
/// Returns a new Result by mapping `Success`es’ values using `transform`, or re-wrapping `Failure`s’ errors.
|
||||
public func map<U>(_ transform: (Value) -> U) -> Result<U, Error> {
|
||||
return flatMap { .success(transform($0)) }
|
||||
}
|
||||
|
||||
/// Returns the result of applying `transform` to `Success`es’ values, or re-wrapping `Failure`’s errors.
|
||||
public func flatMap<U>(_ transform: (Value) -> Result<U, Error>) -> Result<U, Error> {
|
||||
return analysis(
|
||||
ifSuccess: transform,
|
||||
ifFailure: Result<U, Error>.failure)
|
||||
}
|
||||
|
||||
/// Returns a Result with a tuple of the receiver and `other` values if both
|
||||
/// are `Success`es, or re-wrapping the error of the earlier `Failure`.
|
||||
public func fanout<R: ResultProtocol>(_ other: @autoclosure () -> R) -> Result<(Value, R.Value), Error>
|
||||
where Error == R.Error
|
||||
{
|
||||
return self.flatMap { left in other().map { right in (left, right) } }
|
||||
}
|
||||
|
||||
/// Returns a new Result by mapping `Failure`'s values using `transform`, or re-wrapping `Success`es’ values.
|
||||
public func mapError<Error2>(_ transform: (Error) -> Error2) -> Result<Value, Error2> {
|
||||
return flatMapError { .failure(transform($0)) }
|
||||
}
|
||||
|
||||
/// Returns the result of applying `transform` to `Failure`’s errors, or re-wrapping `Success`es’ values.
|
||||
public func flatMapError<Error2>(_ transform: (Error) -> Result<Value, Error2>) -> Result<Value, Error2> {
|
||||
return analysis(
|
||||
ifSuccess: Result<Value, Error2>.success,
|
||||
ifFailure: transform)
|
||||
}
|
||||
|
||||
/// Returns a new Result by mapping `Success`es’ values using `success`, and by mapping `Failure`'s values using `failure`.
|
||||
public func bimap<U, Error2>(success: (Value) -> U, failure: (Error) -> Error2) -> Result<U, Error2> {
|
||||
return analysis(
|
||||
ifSuccess: { .success(success($0)) },
|
||||
ifFailure: { .failure(failure($0)) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public extension ResultProtocol {
|
||||
|
||||
// MARK: Higher-order functions
|
||||
|
||||
/// Returns `self.value` if this result is a .Success, or the given value otherwise. Equivalent with `??`
|
||||
public func recover(_ value: @autoclosure () -> Value) -> Value {
|
||||
return self.value ?? value()
|
||||
}
|
||||
|
||||
/// Returns this result if it is a .Success, or the given result otherwise. Equivalent with `??`
|
||||
public func recover(with result: @autoclosure () -> Self) -> Self {
|
||||
return analysis(
|
||||
ifSuccess: { _ in self },
|
||||
ifFailure: { _ in result() })
|
||||
}
|
||||
}
|
||||
|
||||
/// Protocol used to constrain `tryMap` to `Result`s with compatible `Error`s.
|
||||
public protocol ErrorConvertible: Swift.Error {
|
||||
static func error(from error: Swift.Error) -> Self
|
||||
}
|
||||
|
||||
public extension ResultProtocol where Error: ErrorConvertible {
|
||||
|
||||
/// Returns the result of applying `transform` to `Success`es’ values, or wrapping thrown errors.
|
||||
public func tryMap<U>(_ transform: (Value) throws -> U) -> Result<U, Error> {
|
||||
return flatMap { value in
|
||||
do {
|
||||
return .success(try transform(value))
|
||||
}
|
||||
catch {
|
||||
let convertedError = Error.error(from: error)
|
||||
// Revisit this in a future version of Swift. https://twitter.com/jckarter/status/672931114944696321
|
||||
return .failure(convertedError)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Operators
|
||||
|
||||
infix operator &&& : LogicalConjunctionPrecedence
|
||||
|
||||
/// Returns a Result with a tuple of `left` and `right` values if both are `Success`es, or re-wrapping the error of the earlier `Failure`.
|
||||
@available(*, deprecated, renamed: "ResultProtocol.fanout(self:_:)")
|
||||
public func &&& <L: ResultProtocol, R: ResultProtocol> (left: L, right: @autoclosure () -> R) -> Result<(L.Value, R.Value), L.Error>
|
||||
where L.Error == R.Error
|
||||
{
|
||||
return left.fanout(right)
|
||||
}
|
||||
|
||||
precedencegroup ChainingPrecedence {
|
||||
associativity: left
|
||||
higherThan: TernaryPrecedence
|
||||
}
|
||||
|
||||
infix operator >>- : ChainingPrecedence
|
||||
|
||||
/// Returns the result of applying `transform` to `Success`es’ values, or re-wrapping `Failure`’s errors.
|
||||
///
|
||||
/// This is a synonym for `flatMap`.
|
||||
@available(*, deprecated, renamed: "ResultProtocol.flatMap(self:_:)")
|
||||
public func >>- <T: ResultProtocol, U> (result: T, transform: (T.Value) -> Result<U, T.Error>) -> Result<U, T.Error> {
|
||||
return result.flatMap(transform)
|
||||
}
|
||||
|
||||
/// Returns `true` if `left` and `right` are both `Success`es and their values are equal, or if `left` and `right` are both `Failure`s and their errors are equal.
|
||||
public func == <T: ResultProtocol> (left: T, right: T) -> Bool
|
||||
where T.Value: Equatable, T.Error: Equatable
|
||||
{
|
||||
if let left = left.value, let right = right.value {
|
||||
return left == right
|
||||
} else if let left = left.error, let right = right.error {
|
||||
return left == right
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/// Returns `true` if `left` and `right` represent different cases, or if they represent the same case but different values.
|
||||
public func != <T: ResultProtocol> (left: T, right: T) -> Bool
|
||||
where T.Value: Equatable, T.Error: Equatable
|
||||
{
|
||||
return !(left == right)
|
||||
}
|
||||
|
||||
/// Returns the value of `left` if it is a `Success`, or `right` otherwise. Short-circuits.
|
||||
public func ?? <T: ResultProtocol> (left: T, right: @autoclosure () -> T.Value) -> T.Value {
|
||||
return left.recover(right())
|
||||
}
|
||||
|
||||
/// Returns `left` if it is a `Success`es, or `right` otherwise. Short-circuits.
|
||||
public func ?? <T: ResultProtocol> (left: T, right: @autoclosure () -> T) -> T {
|
||||
return left.recover(with: right())
|
||||
}
|
||||
|
||||
// MARK: - migration support
|
||||
@available(*, unavailable, renamed: "ResultProtocol")
|
||||
public typealias ResultType = ResultProtocol
|
||||
|
||||
@available(*, unavailable, renamed: "Error")
|
||||
public typealias ResultErrorType = Swift.Error
|
||||
|
||||
@available(*, unavailable, renamed: "ErrorConvertible")
|
||||
public typealias ErrorTypeConvertible = ErrorConvertible
|
||||
|
||||
@available(*, deprecated, renamed: "ErrorConvertible")
|
||||
public protocol ErrorProtocolConvertible: ErrorConvertible {}
|
||||
|
||||
extension ResultProtocol {
|
||||
@available(*, unavailable, renamed: "recover(with:)")
|
||||
public func recoverWith(_ result: @autoclosure () -> Self) -> Self {
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
|
||||
extension ErrorConvertible {
|
||||
@available(*, unavailable, renamed: "error(from:)")
|
||||
public static func errorFromErrorType(_ error: Swift.Error) -> Self {
|
||||
fatalError()
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
---
|
||||
SEEDS:
|
||||
- Commandant (0.13.0)
|
||||
- Result (3.2.4)
|
||||
- Nimble (v7.0.3)
|
||||
- Quick (v1.2.0)
|
|
@ -7,30 +7,11 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
073998C12AE3BEEC41CE0DAD /* OrderedSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9871C2273F4D762A1F19B07 /* OrderedSet.swift */; };
|
||||
09756A23E9102359296C821B /* ResultProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5150F7FB7CF2A77F675D8E92 /* ResultProtocol.swift */; };
|
||||
09A04CB22DC02B86AE4ACC8A /* ArgumentParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA9D96DDBBCCCC5944160ABE /* ArgumentParser.swift */; };
|
||||
0C47E694564FCB59996690DD /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E4D331CCD66ADFE19CE39 /* Command.swift */; };
|
||||
0EBF5CDD379D7462C3389536 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9257C5FABA335E5F060CB7F7 /* Result.swift */; };
|
||||
15E27926A580EABEB1B218EF /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1B6BEDF32AF3F8A575FB1F /* Switch.swift */; };
|
||||
27340A5BB9F2A5B166E3A72A /* ArgumentProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4237E5AA1A289D03D2A2FB8 /* ArgumentProtocol.swift */; };
|
||||
3053D11E74A22A4C5A6BE833 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = F547B3DC473CFB1BE0AEB70A /* Errors.swift */; };
|
||||
30EA893640B02CCF679F9C57 /* Option.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD7FE171F643805F7BC38A7 /* Option.swift */; };
|
||||
3F177C62A7053BA3ED415E5E /* Argument.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36A4ABD8025E13060312925 /* Argument.swift */; };
|
||||
4913269B1F48921D0010EB86 /* CKSoftwareMap+AppLookup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4913269A1F48921D0010EB86 /* CKSoftwareMap+AppLookup.swift */; };
|
||||
49C2F3FDD805256BE934A70E /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF1B6BEDF32AF3F8A575FB1F /* Switch.swift */; };
|
||||
4C8321353B9AE40539A1AC8A /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = F547B3DC473CFB1BE0AEB70A /* Errors.swift */; };
|
||||
693A98991CBFFA760004D3B4 /* Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693A98981CBFFA760004D3B4 /* Search.swift */; };
|
||||
693A989B1CBFFAAA0004D3B4 /* NSURLSession+Synchronous.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693A989A1CBFFAAA0004D3B4 /* NSURLSession+Synchronous.swift */; };
|
||||
8078FAA81EC4F2FB004B5B3F /* Lucky.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8078FAA71EC4F2FB004B5B3F /* Lucky.swift */; };
|
||||
900A1E811DBAC8CB0069B1A8 /* Info.swift in Sources */ = {isa = PBXBuildFile; fileRef = 900A1E801DBAC8CB0069B1A8 /* Info.swift */; };
|
||||
92AE0FD7BE06D64692E6C1E6 /* OrderedSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9871C2273F4D762A1F19B07 /* OrderedSet.swift */; };
|
||||
AD0785BC0EC6BBF4ED560DCC /* ArgumentParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA9D96DDBBCCCC5944160ABE /* ArgumentParser.swift */; };
|
||||
ADE553C828AF4EAFF39ED3E1 /* ArgumentProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4237E5AA1A289D03D2A2FB8 /* ArgumentProtocol.swift */; };
|
||||
C50DD25454FC5CAA1F37763F /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9257C5FABA335E5F060CB7F7 /* Result.swift */; };
|
||||
DE6E193A6671F3D6807F746D /* Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E4D331CCD66ADFE19CE39 /* Command.swift */; };
|
||||
EBD6B44FDF65E0253153629F /* HelpCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FDC2B8063EC231E28353D23 /* HelpCommand.swift */; };
|
||||
EC113CE6C98E8D8358228D33 /* ResultProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5150F7FB7CF2A77F675D8E92 /* ResultProtocol.swift */; };
|
||||
ED031A7C1B5127C00097692E /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED031A7B1B5127C00097692E /* main.swift */; };
|
||||
ED0F237F1B87522400AE40CD /* Install.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F237E1B87522400AE40CD /* Install.swift */; };
|
||||
ED0F23831B87533A00AE40CD /* List.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F23821B87533A00AE40CD /* List.swift */; };
|
||||
|
@ -49,9 +30,6 @@
|
|||
EDE296531C700F4300554778 /* SignOut.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDE296521C700F4300554778 /* SignOut.swift */; };
|
||||
EDEAA0C01B51CE6200F2FC3F /* StoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDEAA0BF1B51CE6200F2FC3F /* StoreFoundation.framework */; };
|
||||
EDEAA17D1B5C579100F2FC3F /* CommerceKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDEAA17C1B5C579100F2FC3F /* CommerceKit.framework */; };
|
||||
F184B6B7CD9C013CACDED0FB /* Argument.swift in Sources */ = {isa = PBXBuildFile; fileRef = F36A4ABD8025E13060312925 /* Argument.swift */; };
|
||||
F48562FA81B0C0258AC063B4 /* HelpCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FDC2B8063EC231E28353D23 /* HelpCommand.swift */; };
|
||||
F6D2058A70757D3477185A50 /* Option.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD7FE171F643805F7BC38A7 /* Option.swift */; };
|
||||
F865880B2030F6DE0093DE57 /* MASErrorTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = F865880A2030F6DE0093DE57 /* MASErrorTestCase.swift */; };
|
||||
F86588272030FAE70093DE57 /* MASError.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0F238C1B8756E600AE40CD /* MASError.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
@ -79,20 +57,11 @@
|
|||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
2AD7FE171F643805F7BC38A7 /* Option.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Option.swift; path = Seeds/Commandant/Sources/Commandant/Option.swift; sourceTree = "<group>"; };
|
||||
326E4D331CCD66ADFE19CE39 /* Command.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Command.swift; path = Seeds/Commandant/Sources/Commandant/Command.swift; sourceTree = "<group>"; };
|
||||
4913269A1F48921D0010EB86 /* CKSoftwareMap+AppLookup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CKSoftwareMap+AppLookup.swift"; sourceTree = "<group>"; };
|
||||
5150F7FB7CF2A77F675D8E92 /* ResultProtocol.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ResultProtocol.swift; path = Seeds/Result/Result/ResultProtocol.swift; sourceTree = "<group>"; };
|
||||
693A98981CBFFA760004D3B4 /* Search.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Search.swift; sourceTree = "<group>"; };
|
||||
693A989A1CBFFAAA0004D3B4 /* NSURLSession+Synchronous.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSURLSession+Synchronous.swift"; sourceTree = "<group>"; };
|
||||
8078FAA71EC4F2FB004B5B3F /* Lucky.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lucky.swift; sourceTree = "<group>"; };
|
||||
8FDC2B8063EC231E28353D23 /* HelpCommand.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HelpCommand.swift; path = Seeds/Commandant/Sources/Commandant/HelpCommand.swift; sourceTree = "<group>"; };
|
||||
900A1E801DBAC8CB0069B1A8 /* Info.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Info.swift; sourceTree = "<group>"; };
|
||||
9257C5FABA335E5F060CB7F7 /* Result.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Result.swift; path = Seeds/Result/Result/Result.swift; sourceTree = "<group>"; };
|
||||
AF1B6BEDF32AF3F8A575FB1F /* Switch.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Switch.swift; path = Seeds/Commandant/Sources/Commandant/Switch.swift; sourceTree = "<group>"; };
|
||||
B4237E5AA1A289D03D2A2FB8 /* ArgumentProtocol.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ArgumentProtocol.swift; path = Seeds/Commandant/Sources/Commandant/ArgumentProtocol.swift; sourceTree = "<group>"; };
|
||||
D9871C2273F4D762A1F19B07 /* OrderedSet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = OrderedSet.swift; path = Seeds/Commandant/Sources/Commandant/OrderedSet.swift; sourceTree = "<group>"; };
|
||||
EA9D96DDBBCCCC5944160ABE /* ArgumentParser.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ArgumentParser.swift; path = Seeds/Commandant/Sources/Commandant/ArgumentParser.swift; sourceTree = "<group>"; };
|
||||
ED031A781B5127C00097692E /* mas */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = mas; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
ED031A7B1B5127C00097692E /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||
ED0F237E1B87522400AE40CD /* Install.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Install.swift; sourceTree = "<group>"; };
|
||||
|
@ -137,8 +106,6 @@
|
|||
EDEAA1551B5C576D00F2FC3F /* CKUpdateController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CKUpdateController.h; sourceTree = "<group>"; };
|
||||
EDEAA1661B5C576D00F2FC3F /* ISStoreURLOperationDelegate-Protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ISStoreURLOperationDelegate-Protocol.h"; sourceTree = "<group>"; };
|
||||
EDEAA17C1B5C579100F2FC3F /* CommerceKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CommerceKit.framework; path = /System/Library/PrivateFrameworks/CommerceKit.framework; sourceTree = "<absolute>"; };
|
||||
F36A4ABD8025E13060312925 /* Argument.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Argument.swift; path = Seeds/Commandant/Sources/Commandant/Argument.swift; sourceTree = "<group>"; };
|
||||
F547B3DC473CFB1BE0AEB70A /* Errors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Errors.swift; path = Seeds/Commandant/Sources/Commandant/Errors.swift; sourceTree = "<group>"; };
|
||||
F8233C87201EBDF000268278 /* mas-tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "mas-tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F8233C8B201EBDF100268278 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
F865880A2030F6DE0093DE57 /* MASErrorTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MASErrorTestCase.swift; sourceTree = "<group>"; };
|
||||
|
@ -164,56 +131,6 @@
|
|||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
0739FA024AB80925B32D64D1 /* Seeds */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A49C8EB621015CD588C621FD /* Commandant */,
|
||||
A96B40B5852A4F029AFDA669 /* Nimble */,
|
||||
6EB4B681BB79E32622860164 /* Quick */,
|
||||
6569B225928F21A4A639BB22 /* Result */,
|
||||
);
|
||||
name = Seeds;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6569B225928F21A4A639BB22 /* Result */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9257C5FABA335E5F060CB7F7 /* Result.swift */,
|
||||
5150F7FB7CF2A77F675D8E92 /* ResultProtocol.swift */,
|
||||
);
|
||||
name = Result;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6EB4B681BB79E32622860164 /* Quick */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = Quick;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A49C8EB621015CD588C621FD /* Commandant */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F36A4ABD8025E13060312925 /* Argument.swift */,
|
||||
EA9D96DDBBCCCC5944160ABE /* ArgumentParser.swift */,
|
||||
B4237E5AA1A289D03D2A2FB8 /* ArgumentProtocol.swift */,
|
||||
326E4D331CCD66ADFE19CE39 /* Command.swift */,
|
||||
F547B3DC473CFB1BE0AEB70A /* Errors.swift */,
|
||||
8FDC2B8063EC231E28353D23 /* HelpCommand.swift */,
|
||||
2AD7FE171F643805F7BC38A7 /* Option.swift */,
|
||||
D9871C2273F4D762A1F19B07 /* OrderedSet.swift */,
|
||||
AF1B6BEDF32AF3F8A575FB1F /* Switch.swift */,
|
||||
);
|
||||
name = Commandant;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A96B40B5852A4F029AFDA669 /* Nimble */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = Nimble;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
ED031A6F1B5127C00097692E = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -222,7 +139,6 @@
|
|||
EDFC76381B642A2E00D0DBD7 /* Frameworks */,
|
||||
EDEAA0C11B51CEBD00F2FC3F /* PrivateHeaders */,
|
||||
ED031A791B5127C00097692E /* Products */,
|
||||
0739FA024AB80925B32D64D1 /* Seeds */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
@ -448,14 +364,8 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
ED0F23871B87537200AE40CD /* Account.swift in Sources */,
|
||||
F184B6B7CD9C013CACDED0FB /* Argument.swift in Sources */,
|
||||
AD0785BC0EC6BBF4ED560DCC /* ArgumentParser.swift in Sources */,
|
||||
ADE553C828AF4EAFF39ED3E1 /* ArgumentProtocol.swift in Sources */,
|
||||
4913269B1F48921D0010EB86 /* CKSoftwareMap+AppLookup.swift in Sources */,
|
||||
0C47E694564FCB59996690DD /* Command.swift in Sources */,
|
||||
ED0F238B1B87569C00AE40CD /* Downloader.swift in Sources */,
|
||||
3053D11E74A22A4C5A6BE833 /* Errors.swift in Sources */,
|
||||
EBD6B44FDF65E0253153629F /* HelpCommand.swift in Sources */,
|
||||
900A1E811DBAC8CB0069B1A8 /* Info.swift in Sources */,
|
||||
ED0F237F1B87522400AE40CD /* Install.swift in Sources */,
|
||||
ED0F23901B87A56F00AE40CD /* ISStoreAccount.swift in Sources */,
|
||||
|
@ -464,18 +374,13 @@
|
|||
ED031A7C1B5127C00097692E /* main.swift in Sources */,
|
||||
ED0F238D1B8756E600AE40CD /* MASError.swift in Sources */,
|
||||
693A989B1CBFFAAA0004D3B4 /* NSURLSession+Synchronous.swift in Sources */,
|
||||
30EA893640B02CCF679F9C57 /* Option.swift in Sources */,
|
||||
92AE0FD7BE06D64692E6C1E6 /* OrderedSet.swift in Sources */,
|
||||
ED0F23851B87536A00AE40CD /* Outdated.swift in Sources */,
|
||||
ED0F23891B87543D00AE40CD /* PurchaseDownloadObserver.swift in Sources */,
|
||||
EDCBF9531D89AC6F000039C6 /* Reset.swift in Sources */,
|
||||
0EBF5CDD379D7462C3389536 /* Result.swift in Sources */,
|
||||
09756A23E9102359296C821B /* ResultProtocol.swift in Sources */,
|
||||
693A98991CBFFA760004D3B4 /* Search.swift in Sources */,
|
||||
EDC90B651C70045E0019E396 /* SignIn.swift in Sources */,
|
||||
EDE296531C700F4300554778 /* SignOut.swift in Sources */,
|
||||
EDA3BE521B8B84AF00C18D70 /* SSPurchase.swift in Sources */,
|
||||
15E27926A580EABEB1B218EF /* Switch.swift in Sources */,
|
||||
EDD3B3631C34709400B56B88 /* Upgrade.swift in Sources */,
|
||||
EDCBF9551D89CFC7000039C6 /* Utilities.swift in Sources */,
|
||||
EDB6CE8C1BAEC3D400648B4D /* Version.swift in Sources */,
|
||||
|
@ -486,19 +391,8 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3F177C62A7053BA3ED415E5E /* Argument.swift in Sources */,
|
||||
09A04CB22DC02B86AE4ACC8A /* ArgumentParser.swift in Sources */,
|
||||
27340A5BB9F2A5B166E3A72A /* ArgumentProtocol.swift in Sources */,
|
||||
DE6E193A6671F3D6807F746D /* Command.swift in Sources */,
|
||||
4C8321353B9AE40539A1AC8A /* Errors.swift in Sources */,
|
||||
F48562FA81B0C0258AC063B4 /* HelpCommand.swift in Sources */,
|
||||
F86588272030FAE70093DE57 /* MASError.swift in Sources */,
|
||||
F865880B2030F6DE0093DE57 /* MASErrorTestCase.swift in Sources */,
|
||||
F6D2058A70757D3477185A50 /* Option.swift in Sources */,
|
||||
073998C12AE3BEEC41CE0DAD /* OrderedSet.swift in Sources */,
|
||||
C50DD25454FC5CAA1F37763F /* Result.swift in Sources */,
|
||||
EC113CE6C98E8D8358228D33 /* ResultProtocol.swift in Sources */,
|
||||
49C2F3FDD805256BE934A70E /* Switch.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue