mirror of
https://github.com/mas-cli/mas
synced 2024-11-21 19:23:01 +00:00
Revert to Swift 1.2
This commit is contained in:
parent
cb16a0ec92
commit
bdf66136df
14 changed files with 224 additions and 284 deletions
|
@ -3,7 +3,7 @@
|
|||
/// Wraps a type `T` in a reference type.
|
||||
///
|
||||
/// Typically this is used to work around limitations of value types (for example, the lack of codegen for recursive value types and type-parameterized enums with >1 case). It is also useful for sharing a single (presumably large) value without copying it.
|
||||
public final class Box<T>: BoxType, CustomStringConvertible {
|
||||
public final class Box<T>: BoxType, Printable {
|
||||
/// Initializes a `Box` with the given value.
|
||||
public init(_ value: T) {
|
||||
self.value = value
|
||||
|
@ -28,6 +28,6 @@ public final class Box<T>: BoxType, CustomStringConvertible {
|
|||
// MARK: Printable
|
||||
|
||||
public var description: String {
|
||||
return String(value)
|
||||
return toString(value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
/// While this, like `Box<T>` could be used to work around limitations of value types, it is much more useful for sharing a single mutable value such that mutations are shared.
|
||||
///
|
||||
/// As with all mutable state, this should be used carefully, for example as an optimization, rather than a default design choice. Most of the time, `Box<T>` will suffice where any `BoxType` is needed.
|
||||
public final class MutableBox<T>: MutableBoxType, CustomStringConvertible {
|
||||
public final class MutableBox<T>: MutableBoxType, Printable {
|
||||
/// Initializes a `MutableBox` with the given value.
|
||||
public init(_ value: T) {
|
||||
self.value = value
|
||||
|
@ -22,6 +22,6 @@ public final class MutableBox<T>: MutableBoxType, CustomStringConvertible {
|
|||
// MARK: Printable
|
||||
|
||||
public var description: String {
|
||||
return String(value)
|
||||
return toString(value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ private func ==(lhs: RawArgument, rhs: RawArgument) -> Bool {
|
|||
}
|
||||
}
|
||||
|
||||
extension RawArgument: CustomStringConvertible {
|
||||
extension RawArgument: Printable {
|
||||
private var description: String {
|
||||
switch self {
|
||||
case let .Key(key):
|
||||
|
@ -67,8 +67,8 @@ public final class ArgumentParser {
|
|||
rawArguments.extend(options.map { arg in
|
||||
if arg.hasPrefix("-") {
|
||||
// Do we have `--{key}` or `-{flags}`.
|
||||
let opt = dropFirst(arg.characters)
|
||||
return String(opt).hasPrefix("-") ? .Key(String(dropFirst(opt))) : .Flag(Set(opt))
|
||||
var opt = dropFirst(arg)
|
||||
return opt.hasPrefix("-") ? .Key(dropFirst(opt)) : .Flag(Set(opt))
|
||||
} else {
|
||||
return .Value(arg)
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ public final class ArgumentParser {
|
|||
// Remaining arguments are all positional parameters.
|
||||
if params.count == 2 {
|
||||
let positional = params.last!
|
||||
rawArguments.extend(Array(positional.map { .Value($0) }))
|
||||
rawArguments.extend(positional.map { .Value($0) })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,13 +130,13 @@ public final class ArgumentParser {
|
|||
}
|
||||
}
|
||||
|
||||
return .Failure(missingArgumentError("--\(key)"))
|
||||
return .failure(missingArgumentError("--\(key)"))
|
||||
} else {
|
||||
rawArguments.append(arg)
|
||||
}
|
||||
}
|
||||
|
||||
return .Success(foundValue)
|
||||
return .success(foundValue)
|
||||
}
|
||||
|
||||
/// Returns the next positional argument that hasn't yet been returned, or
|
||||
|
@ -168,7 +168,7 @@ public final class ArgumentParser {
|
|||
/// Returns whether the given flag was specified and removes it from the
|
||||
/// list of arguments remaining.
|
||||
internal func consumeBooleanFlag(flag: Character) -> Bool {
|
||||
for (index, arg) in rawArguments.enumerate() {
|
||||
for (index, arg) in enumerate(rawArguments) {
|
||||
switch arg {
|
||||
case var .Flag(flags) where flags.contains(flag):
|
||||
flags.remove(flag)
|
||||
|
|
|
@ -58,7 +58,7 @@ public final class CommandRegistry<ClientError> {
|
|||
|
||||
/// All available commands.
|
||||
public var commands: [CommandOf<ClientError>] {
|
||||
return commandsByVerb.values.sort { return $0.verb < $1.verb }
|
||||
return sorted(commandsByVerb.values) { return $0.verb < $1.verb }
|
||||
}
|
||||
|
||||
public init() {}
|
||||
|
@ -100,7 +100,7 @@ extension CommandRegistry {
|
|||
/// 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.
|
||||
@noreturn public func main(defaultVerb defaultVerb: String, errorHandler: ClientError -> ()) {
|
||||
@noreturn public func main(#defaultVerb: String, errorHandler: ClientError -> ()) {
|
||||
var arguments = Process.arguments
|
||||
assert(arguments.count >= 1)
|
||||
|
||||
|
@ -119,12 +119,12 @@ extension CommandRegistry {
|
|||
exit(EXIT_SUCCESS)
|
||||
|
||||
case let .Some(.Failure(error)):
|
||||
switch error {
|
||||
switch error.value {
|
||||
case let .UsageError(description):
|
||||
fputs(description + "\n", stderr)
|
||||
|
||||
case let .CommandError(error):
|
||||
errorHandler(error)
|
||||
errorHandler(error.value)
|
||||
}
|
||||
|
||||
exit(EXIT_FAILURE)
|
||||
|
|
|
@ -12,22 +12,22 @@ import Foundation
|
|||
///
|
||||
/// `ClientError` should be the type of error (if any) that can occur when
|
||||
/// running commands.
|
||||
public enum CommandantError<ClientError>: ErrorType {
|
||||
public enum CommandantError<ClientError> {
|
||||
/// An option was used incorrectly.
|
||||
case UsageError(description: String)
|
||||
|
||||
/// An error occurred while running a command.
|
||||
case CommandError(ClientError)
|
||||
case CommandError(Box<ClientError>)
|
||||
}
|
||||
|
||||
extension CommandantError: CustomStringConvertible {
|
||||
extension CommandantError: Printable {
|
||||
public var description: String {
|
||||
switch self {
|
||||
case let .UsageError(description):
|
||||
return description
|
||||
|
||||
case let .CommandError(error):
|
||||
return String(error)
|
||||
return toString(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ internal func missingArgumentError<ClientError>(argumentName: String) -> Command
|
|||
internal func informativeUsageError<ClientError>(keyValueExample: String, usage: String) -> CommandantError<ClientError> {
|
||||
let lines = usage.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet())
|
||||
|
||||
return .UsageError(description: lines.reduce(keyValueExample) { previous, value in
|
||||
return .UsageError(description: reduce(lines, keyValueExample) { previous, value in
|
||||
return previous + "\n\t" + value
|
||||
})
|
||||
}
|
||||
|
@ -56,9 +56,9 @@ internal func informativeUsageError<ClientError>(keyValueExample: String, usage:
|
|||
/// example of key (and value, if applicable) usage.
|
||||
internal func informativeUsageError<T, ClientError>(keyValueExample: String, option: Option<T>) -> CommandantError<ClientError> {
|
||||
if option.defaultValue != nil {
|
||||
return informativeUsageError("[\(keyValueExample)]", usage: option.usage)
|
||||
return informativeUsageError("[\(keyValueExample)]", option.usage)
|
||||
} else {
|
||||
return informativeUsageError(keyValueExample, usage: option.usage)
|
||||
return informativeUsageError(keyValueExample, option.usage)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ internal func informativeUsageError<T: ArgumentType, ClientError>(option: Option
|
|||
example += valueExample
|
||||
}
|
||||
|
||||
return informativeUsageError(example, option: option)
|
||||
return informativeUsageError(example, option)
|
||||
}
|
||||
|
||||
/// Constructs an error that describes how to use the given boolean option.
|
||||
|
@ -91,9 +91,9 @@ internal func informativeUsageError<ClientError>(option: Option<Bool>) -> Comman
|
|||
let key = option.key!
|
||||
|
||||
if let defaultValue = option.defaultValue {
|
||||
return informativeUsageError((defaultValue ? "--no-\(key)" : "--\(key)"), option: option)
|
||||
return informativeUsageError((defaultValue ? "--no-\(key)" : "--\(key)"), option)
|
||||
} else {
|
||||
return informativeUsageError("--(no-)\(key)", option: option)
|
||||
return informativeUsageError("--(no-)\(key)", option)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,27 +34,28 @@ public struct HelpCommand<ClientError>: CommandType {
|
|||
.flatMap { options in
|
||||
if let verb = options.verb {
|
||||
if let command = self.registry[verb] {
|
||||
print(command.function + "\n")
|
||||
println(command.function)
|
||||
println()
|
||||
return command.run(.Usage)
|
||||
} else {
|
||||
fputs("Unrecognized command: '\(verb)'\n", stderr)
|
||||
}
|
||||
}
|
||||
|
||||
print("Available commands:\n")
|
||||
println("Available commands:\n")
|
||||
|
||||
let maxVerbLength = self.registry.commands.map { $0.verb.characters.count }.maxElement() ?? 0
|
||||
let maxVerbLength = maxElement(self.registry.commands.map { count($0.verb) })
|
||||
|
||||
for command in self.registry.commands {
|
||||
let padding = Repeat<Character>(count: maxVerbLength - command.verb.characters.count, repeatedValue: " ")
|
||||
let padding = Repeat<Character>(count: maxVerbLength - count(command.verb), repeatedValue: " ")
|
||||
|
||||
var formattedVerb = command.verb
|
||||
formattedVerb.extend(padding)
|
||||
|
||||
print(" \(formattedVerb) \(command.function)")
|
||||
println(" \(formattedVerb) \(command.function)")
|
||||
}
|
||||
|
||||
return .Success(())
|
||||
return .success(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +68,7 @@ private struct HelpOptions<ClientError>: OptionsType {
|
|||
}
|
||||
|
||||
static func create(verb: String) -> HelpOptions {
|
||||
return self.init(verb: (verb == "" ? nil : verb))
|
||||
return self(verb: (verb == "" ? nil : verb))
|
||||
}
|
||||
|
||||
static func evaluate(m: CommandMode) -> Result<HelpOptions, CommandantError<ClientError>> {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<string>org.carthage.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
|
@ -15,7 +15,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<string>0.6.1</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
|
|
@ -81,7 +81,7 @@ public struct Option<T> {
|
|||
}
|
||||
}
|
||||
|
||||
extension Option: CustomStringConvertible {
|
||||
extension Option: Printable {
|
||||
public var description: String {
|
||||
if let key = key {
|
||||
return "--\(key)"
|
||||
|
@ -104,18 +104,10 @@ extension Int: ArgumentType {
|
|||
public static let name = "integer"
|
||||
|
||||
public static func fromString(string: String) -> Int? {
|
||||
return Int(string)
|
||||
return string.toInt()
|
||||
}
|
||||
}
|
||||
|
||||
extension UInt64: ArgumentType {
|
||||
public static let name = "integer"
|
||||
|
||||
public static func fromString(string: String) -> UInt64? {
|
||||
return UInt64(string, radix: 10)
|
||||
}
|
||||
}
|
||||
|
||||
extension String: ArgumentType {
|
||||
public static let name = "string"
|
||||
|
||||
|
@ -174,17 +166,17 @@ public func <*> <T, U, ClientError>(f: T -> U, value: Result<T, CommandantError<
|
|||
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, rhs: right))
|
||||
return .failure(combineUsageErrors(left.value, right.value))
|
||||
|
||||
case let (.Failure(left), .Success):
|
||||
return .Failure(left)
|
||||
return .failure(left.value)
|
||||
|
||||
case let (.Success, .Failure(right)):
|
||||
return .Failure(right)
|
||||
return .failure(right.value)
|
||||
|
||||
case let (.Success(f), .Success(value)):
|
||||
let newValue = f(value)
|
||||
return .Success(newValue)
|
||||
let newValue = f.value(value.value)
|
||||
return .success(newValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,12 +191,12 @@ public func <| <T: ArgumentType, ClientError>(mode: CommandMode, option: Option<
|
|||
if let key = option.key {
|
||||
switch arguments.consumeValueForKey(key) {
|
||||
case let .Success(value):
|
||||
stringValue = value
|
||||
stringValue = value.value
|
||||
|
||||
case let .Failure(error):
|
||||
switch error {
|
||||
switch error.value {
|
||||
case let .UsageError(description):
|
||||
return .Failure(.UsageError(description: description))
|
||||
return .failure(.UsageError(description: description))
|
||||
|
||||
case .CommandError:
|
||||
fatalError("CommandError should be impossible when parameterized over NoError")
|
||||
|
@ -216,18 +208,18 @@ public func <| <T: ArgumentType, ClientError>(mode: CommandMode, option: Option<
|
|||
|
||||
if let stringValue = stringValue {
|
||||
if let value = T.fromString(stringValue) {
|
||||
return .Success(value)
|
||||
return .success(value)
|
||||
}
|
||||
|
||||
return .Failure(option.invalidUsageError(stringValue))
|
||||
return .failure(option.invalidUsageError(stringValue))
|
||||
} else if let defaultValue = option.defaultValue {
|
||||
return .Success(defaultValue)
|
||||
return .success(defaultValue)
|
||||
} else {
|
||||
return .Failure(missingArgumentError(option.description))
|
||||
return .failure(missingArgumentError(option.description))
|
||||
}
|
||||
|
||||
case .Usage:
|
||||
return .Failure(informativeUsageError(option))
|
||||
return .failure(informativeUsageError(option))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,14 +233,14 @@ public func <| <ClientError>(mode: CommandMode, option: Option<Bool>) -> Result<
|
|||
switch mode {
|
||||
case let .Arguments(arguments):
|
||||
if let value = arguments.consumeBooleanKey(option.key!) {
|
||||
return .Success(value)
|
||||
return .success(value)
|
||||
} else if let defaultValue = option.defaultValue {
|
||||
return .Success(defaultValue)
|
||||
return .success(defaultValue)
|
||||
} else {
|
||||
return .Failure(missingArgumentError(option.description))
|
||||
return .failure(missingArgumentError(option.description))
|
||||
}
|
||||
|
||||
case .Usage:
|
||||
return .Failure(informativeUsageError(option))
|
||||
return .failure(informativeUsageError(option))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public struct Switch {
|
|||
}
|
||||
}
|
||||
|
||||
extension Switch: CustomStringConvertible {
|
||||
extension Switch: Printable {
|
||||
public var description: String {
|
||||
var options = "--\(key)"
|
||||
if let flag = self.flag {
|
||||
|
@ -54,9 +54,9 @@ public func <| <ClientError> (mode: CommandMode, option: Switch) -> Result<Bool,
|
|||
if let flag = option.flag {
|
||||
enabled = arguments.consumeBooleanFlag(flag)
|
||||
}
|
||||
return .Success(enabled)
|
||||
return .success(enabled)
|
||||
|
||||
case .Usage:
|
||||
return .Failure(informativeUsageError(option.description, usage: option.usage))
|
||||
return .failure(informativeUsageError(option.description, option.usage))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,183 +1,163 @@
|
|||
// 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: ErrorType>: ResultType, 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?, @autoclosure failWith: () -> Error) {
|
||||
self = value.map(Result.Success) ?? .Failure(failWith())
|
||||
}
|
||||
|
||||
/// Constructs a result from a function that uses `throw`, failing with `Error` if throws
|
||||
public init(@autoclosure _ f: () throws -> T) {
|
||||
do {
|
||||
self = .Success(try f())
|
||||
} catch {
|
||||
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>(@noescape ifSuccess ifSuccess: T -> Result, @noescape ifFailure: Error -> Result) -> Result {
|
||||
switch self {
|
||||
case let .Success(value):
|
||||
return ifSuccess(value)
|
||||
case let .Failure(value):
|
||||
return ifFailure(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Higher-order functions
|
||||
|
||||
/// Returns a new Result by mapping `Success`es’ values using `transform`, or re-wrapping `Failure`s’ errors.
|
||||
public func map<U>(@noescape transform: T -> 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>(@noescape transform: T -> Result<U, Error>) -> Result<U, Error> {
|
||||
return analysis(
|
||||
ifSuccess: transform,
|
||||
ifFailure: Result<U, Error>.Failure)
|
||||
}
|
||||
|
||||
/// Returns `self.value` if this result is a .Success, or the given value otherwise. Equivalent with `??`
|
||||
public func recover(@autoclosure value: () -> T) -> T {
|
||||
return self.value ?? value()
|
||||
}
|
||||
|
||||
/// Returns this result if it is a .Success, or the given result otherwise. Equivalent with `??`
|
||||
public func recoverWith(@autoclosure result: () -> Result<T,Error>) -> Result<T,Error> {
|
||||
return analysis(
|
||||
ifSuccess: { _ in self },
|
||||
ifFailure: { _ in result() })
|
||||
}
|
||||
|
||||
/// Transform a function from one that uses `throw` to one that returns a `Result`
|
||||
// public static func materialize<T, U>(f: T throws -> U) -> T -> Result<U, ErrorType> {
|
||||
// return { x in
|
||||
// do {
|
||||
// return .Success(try f(x))
|
||||
// } catch {
|
||||
// return .Failure(error)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// 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: AnyObject] = [
|
||||
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
|
||||
}
|
||||
public enum Result<T, Error>: Printable, DebugPrintable {
|
||||
case Success(Box<T>)
|
||||
case Failure(Box<Error>)
|
||||
|
||||
// MARK: Constructors
|
||||
|
||||
/// Constructs a success wrapping a `value`.
|
||||
public init(value: T) {
|
||||
self = .Success(Box(value))
|
||||
}
|
||||
|
||||
/// Constructs a failure wrapping an `error`.
|
||||
public init(error: Error) {
|
||||
self = .Failure(Box(error))
|
||||
}
|
||||
|
||||
/// Constructs a result from an Optional, failing with `Error` if `nil`
|
||||
public init(_ value: T?, @autoclosure failWith: () -> Error) {
|
||||
self = value.map { .success($0) } ?? .failure(failWith())
|
||||
}
|
||||
|
||||
/// Constructs a success wrapping a `value`.
|
||||
public static func success(value: T) -> Result {
|
||||
return Result(value: value)
|
||||
}
|
||||
|
||||
/// Constructs a failure wrapping an `error`.
|
||||
public static func failure(error: Error) -> Result {
|
||||
return Result(error: error)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Deconstruction
|
||||
|
||||
/// Returns the value from `Success` Results, `nil` otherwise.
|
||||
public var value: T? {
|
||||
return analysis(ifSuccess: { $0 }, ifFailure: { _ in nil })
|
||||
}
|
||||
|
||||
/// Returns the error from `Failure` Results, `nil` otherwise.
|
||||
public var error: Error? {
|
||||
return analysis(ifSuccess: { _ in nil }, ifFailure: { $0 })
|
||||
}
|
||||
|
||||
/// Case analysis for Result.
|
||||
///
|
||||
/// Returns the value produced by applying `ifFailure` to `Failure` Results, or `ifSuccess` to `Success` Results.
|
||||
public func analysis<Result>(@noescape #ifSuccess: T -> Result, @noescape ifFailure: Error -> Result) -> Result {
|
||||
switch self {
|
||||
case let .Success(value):
|
||||
return ifSuccess(value.value)
|
||||
case let .Failure(value):
|
||||
return ifFailure(value.value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Higher-order functions
|
||||
|
||||
/// Returns a new Result by mapping `Success`es’ values using `transform`, or re-wrapping `Failure`s’ errors.
|
||||
public func map<U>(@noescape transform: T -> 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>(@noescape transform: T -> Result<U, Error>) -> Result<U, Error> {
|
||||
return analysis(
|
||||
ifSuccess: transform,
|
||||
ifFailure: Result<U, Error>.failure)
|
||||
}
|
||||
|
||||
/// Returns `self.value` if this result is a .Success, or the given value otherwise. Equivalent with `??`
|
||||
public func recover(@autoclosure value: () -> T) -> T {
|
||||
return self.value ?? value()
|
||||
}
|
||||
|
||||
/// Returns this result if it is a .Success, or the given result otherwise. Equivalent with `??`
|
||||
public func recoverWith(@autoclosure result: () -> Result<T,Error>) -> Result<T,Error> {
|
||||
return analysis(
|
||||
ifSuccess: { _ in self },
|
||||
ifFailure: { _ in result() })
|
||||
}
|
||||
|
||||
|
||||
// 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: AnyObject] = [
|
||||
functionKey: function,
|
||||
fileKey: file,
|
||||
lineKey: line,
|
||||
]
|
||||
|
||||
if let message = message {
|
||||
userInfo[NSLocalizedDescriptionKey] = message
|
||||
}
|
||||
|
||||
return NSError(domain: errorDomain, code: 0, userInfo: userInfo)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Printable
|
||||
|
||||
public var description: String {
|
||||
return analysis(
|
||||
ifSuccess: { ".Success(\($0))" },
|
||||
ifFailure: { ".Failure(\($0))" })
|
||||
}
|
||||
|
||||
|
||||
// MARK: DebugPrintable
|
||||
|
||||
public var debugDescription: String {
|
||||
return description
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// 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: Equatable, Error: Equatable> (left: Result<T, Error>, right: Result<T, Error>) -> Bool {
|
||||
if let left = left.value, right = right.value {
|
||||
return left == right
|
||||
} else if let left = left.error, right = right.error {
|
||||
return left == right
|
||||
}
|
||||
return false
|
||||
if let left = left.value, right = right.value {
|
||||
return left == right
|
||||
} else if let left = left.error, 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: Equatable, Error: Equatable> (left: Result<T, Error>, right: Result<T, Error>) -> Bool {
|
||||
return !(left == right)
|
||||
return !(left == right)
|
||||
}
|
||||
|
||||
|
||||
/// Returns the value of `left` if it is a `Success`, or `right` otherwise. Short-circuits.
|
||||
public func ?? <T, Error> (left: Result<T, Error>, @autoclosure right: () -> T) -> T {
|
||||
return left.recover(right())
|
||||
return left.recover(right())
|
||||
}
|
||||
|
||||
/// Returns `left` if it is a `Success`es, or `right` otherwise. Short-circuits.
|
||||
public func ?? <T, Error> (left: Result<T, Error>, @autoclosure right: () -> Result<T, Error>) -> Result<T, Error> {
|
||||
return left.recoverWith(right())
|
||||
return left.recoverWith(right())
|
||||
}
|
||||
|
||||
// MARK: - Derive result from failable closure
|
||||
|
||||
// Disable until http://www.openradar.me/21341337 is fixed.
|
||||
//public func materialize<T>(f: () throws -> T) -> Result<T, ErrorType> {
|
||||
// do {
|
||||
// return .Success(try f())
|
||||
// } catch {
|
||||
// return .Failure(error)
|
||||
// }
|
||||
//}
|
||||
|
||||
// MARK: - Cocoa API conveniences
|
||||
|
||||
|
@ -186,9 +166,9 @@ public func ?? <T, Error> (left: Result<T, Error>, @autoclosure right: () -> Res
|
|||
/// 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) }
|
||||
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))
|
||||
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) ?? Result.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.
|
||||
|
@ -196,43 +176,43 @@ public func `try`<T>(function: String = __FUNCTION__, file: String = __FILE__, l
|
|||
/// 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) }
|
||||
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))
|
||||
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))
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Operators
|
||||
|
||||
infix operator >>- {
|
||||
// Left-associativity so that chaining works like you’d expect, and for consistency with Haskell, Runes, swiftz, etc.
|
||||
associativity left
|
||||
// Left-associativity so that chaining works like you’d expect, and for consistency with Haskell, Runes, swiftz, etc.
|
||||
associativity left
|
||||
|
||||
// Higher precedence than function application, but lower than function composition.
|
||||
precedence 100
|
||||
// Higher precedence than function application, but lower than function composition.
|
||||
precedence 100
|
||||
}
|
||||
|
||||
infix operator &&& {
|
||||
/// Same associativity as &&.
|
||||
associativity left
|
||||
/// Same associativity as &&.
|
||||
associativity left
|
||||
|
||||
/// Same precedence as &&.
|
||||
precedence 120
|
||||
/// Same precedence as &&.
|
||||
precedence 120
|
||||
}
|
||||
|
||||
/// Returns the result of applying `transform` to `Success`es’ values, or re-wrapping `Failure`’s errors.
|
||||
///
|
||||
/// This is a synonym for `flatMap`.
|
||||
public func >>- <T, U, Error> (result: Result<T, Error>, @noescape transform: T -> Result<U, Error>) -> Result<U, Error> {
|
||||
return result.flatMap(transform)
|
||||
return result.flatMap(transform)
|
||||
}
|
||||
|
||||
/// 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`.
|
||||
public func &&& <T, U, Error> (left: Result<T, Error>, @autoclosure right: () -> Result<U, Error>) -> Result<(T, U), Error> {
|
||||
return left.flatMap { left in right().map { right in (left, right) } }
|
||||
return left.flatMap { left in right().map { right in (left, right) } }
|
||||
}
|
||||
|
||||
|
||||
import Foundation
|
||||
import Foundation
|
||||
|
|
|
@ -1,31 +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 ResultType {
|
||||
typealias Value
|
||||
typealias Error: ErrorType
|
||||
|
||||
/// Constructs a successful result wrapping a `value`.
|
||||
init(value: Value)
|
||||
|
||||
/// Constructs a failed result wrapping an `error`.
|
||||
init(error: Error)
|
||||
|
||||
/// Case analysis for ResultType.
|
||||
///
|
||||
/// 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>(@noescape ifSuccess ifSuccess: Value -> U, @noescape ifFailure: Error -> U) -> U
|
||||
}
|
||||
|
||||
public extension ResultType {
|
||||
|
||||
/// Returns the value if self represents a success, `nil` otherwise.
|
||||
var value: Value? {
|
||||
return analysis(ifSuccess: { $0 }, ifFailure: { _ in nil })
|
||||
}
|
||||
|
||||
/// Returns the error if self represents a failure, `nil` otherwise.
|
||||
var error: Error? {
|
||||
return analysis(ifSuccess: { _ in nil }, ifFailure: { $0 })
|
||||
}
|
||||
}
|
|
@ -15,7 +15,6 @@
|
|||
ED128ECE1B6C2A0B00C4050A /* Option.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EC71B6C2A0B00C4050A /* Option.swift */; };
|
||||
ED128ECF1B6C2A0B00C4050A /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EC81B6C2A0B00C4050A /* Switch.swift */; };
|
||||
ED128ED31B6C2AA200C4050A /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128ED21B6C2AA200C4050A /* Result.swift */; };
|
||||
ED128ED51B6C2AB700C4050A /* ResultType.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128ED41B6C2AB700C4050A /* ResultType.swift */; };
|
||||
ED128EDC1B6C2B4400C4050A /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128ED91B6C2B4400C4050A /* Box.swift */; };
|
||||
ED128EDD1B6C2B4400C4050A /* BoxType.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EDA1B6C2B4400C4050A /* BoxType.swift */; };
|
||||
ED128EDE1B6C2B4400C4050A /* MutableBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EDB1B6C2B4400C4050A /* MutableBox.swift */; };
|
||||
|
@ -48,7 +47,6 @@
|
|||
ED128EC81B6C2A0B00C4050A /* Switch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Switch.swift; sourceTree = "<group>"; };
|
||||
ED128ED11B6C2A8B00C4050A /* Result.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Result.h; sourceTree = "<group>"; };
|
||||
ED128ED21B6C2AA200C4050A /* Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = "<group>"; };
|
||||
ED128ED41B6C2AB700C4050A /* ResultType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResultType.swift; sourceTree = "<group>"; };
|
||||
ED128ED81B6C2B4400C4050A /* Box.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Box.h; sourceTree = "<group>"; };
|
||||
ED128ED91B6C2B4400C4050A /* Box.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Box.swift; sourceTree = "<group>"; };
|
||||
ED128EDA1B6C2B4400C4050A /* BoxType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxType.swift; sourceTree = "<group>"; };
|
||||
|
@ -303,7 +301,6 @@
|
|||
children = (
|
||||
ED128ED11B6C2A8B00C4050A /* Result.h */,
|
||||
ED128ED21B6C2AA200C4050A /* Result.swift */,
|
||||
ED128ED41B6C2AB700C4050A /* ResultType.swift */,
|
||||
);
|
||||
path = Result;
|
||||
sourceTree = "<group>";
|
||||
|
@ -598,7 +595,6 @@
|
|||
ED128EDE1B6C2B4400C4050A /* MutableBox.swift in Sources */,
|
||||
ED128ECA1B6C2A0B00C4050A /* ArgumentParser.swift in Sources */,
|
||||
ED128ECB1B6C2A0B00C4050A /* Command.swift in Sources */,
|
||||
ED128ED51B6C2AB700C4050A /* ResultType.swift in Sources */,
|
||||
ED128ECE1B6C2A0B00C4050A /* Option.swift in Sources */,
|
||||
ED128ECD1B6C2A0B00C4050A /* HelpCommand.swift in Sources */,
|
||||
ED128ED31B6C2AA200C4050A /* Result.swift in Sources */,
|
||||
|
@ -694,6 +690,7 @@
|
|||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "mas-cli/mas-cli-Bridging-Header.h";
|
||||
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/mas-cli/Headers/**";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
@ -706,6 +703,7 @@
|
|||
);
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "mas-cli/mas-cli-Bridging-Header.h";
|
||||
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/mas-cli/Headers/**";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
- (BOOL)isTrialVersionOfBundleIdentifier:(id)arg1;
|
||||
- (id)receiptFromBundleAtPath:(id)arg1;
|
||||
- (id)productForPath:(id)arg1;
|
||||
- (NSArray<CKSoftwareProduct *>*)allProducts;
|
||||
- (NSArray*)allProducts;
|
||||
- (CKSoftwareProduct *)productForItemIdentifier:(unsigned long long)arg1;
|
||||
- (CKSoftwareProduct *)productForBundleIdentifier:(NSString *)arg1;
|
||||
- (void)removeProductsObserver:(id)arg1;
|
||||
|
|
|
@ -20,7 +20,7 @@ func primaryAccount() -> ISStoreAccount {
|
|||
if let activePhase = download.status.activePhase {
|
||||
let percentage = String(Int(floor(download.status.percentComplete * 100))) + "%"
|
||||
// let phase = String(activePhase.phaseType)
|
||||
print("\u{001B}[2K\r" + percentage + " " + download.metadata.title, appendNewline: false)
|
||||
print("\u{001B}[2K\r" + percentage + " " + download.metadata.title)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ struct AccountCommand: CommandType {
|
|||
default:
|
||||
break
|
||||
}
|
||||
return .Success(())
|
||||
return .success(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,13 +102,13 @@ struct InstallCommand: CommandType {
|
|||
struct InstallOptions: OptionsType {
|
||||
let appId: UInt64
|
||||
|
||||
static func create(appId: UInt64) -> InstallOptions {
|
||||
return InstallOptions(appId: appId)
|
||||
static func create(appId: Int) -> InstallOptions {
|
||||
return InstallOptions(appId: UInt64(appId))
|
||||
}
|
||||
|
||||
static func evaluate(m: CommandMode) -> Result<InstallOptions, CommandantError<MASError>> {
|
||||
return create
|
||||
<*> m <| Option(usage: "the app ID to install")
|
||||
<*> m <| Option(key: nil, defaultValue: nil, usage: "the app ID to install")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ struct ListUpdatesCommand: CommandType {
|
|||
default:
|
||||
break
|
||||
}
|
||||
return .Success(())
|
||||
return .success(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,11 +145,11 @@ struct ListInstalledCommand: CommandType {
|
|||
default:
|
||||
break
|
||||
}
|
||||
return .Success(())
|
||||
return .success(())
|
||||
}
|
||||
}
|
||||
|
||||
public enum MASError: ErrorType, Equatable {
|
||||
public enum MASError: Equatable {
|
||||
public var description: String {
|
||||
return ""
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue