Revert to Swift 1.2

This commit is contained in:
Andrew Naylor 2015-08-10 23:17:27 +08:00
parent cb16a0ec92
commit bdf66136df
14 changed files with 224 additions and 284 deletions

View file

@ -3,7 +3,7 @@
/// Wraps a type `T` in a reference type. /// 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. /// 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. /// Initializes a `Box` with the given value.
public init(_ value: T) { public init(_ value: T) {
self.value = value self.value = value
@ -28,6 +28,6 @@ public final class Box<T>: BoxType, CustomStringConvertible {
// MARK: Printable // MARK: Printable
public var description: String { public var description: String {
return String(value) return toString(value)
} }
} }

View file

@ -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. /// 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. /// 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. /// Initializes a `MutableBox` with the given value.
public init(_ value: T) { public init(_ value: T) {
self.value = value self.value = value
@ -22,6 +22,6 @@ public final class MutableBox<T>: MutableBoxType, CustomStringConvertible {
// MARK: Printable // MARK: Printable
public var description: String { public var description: String {
return String(value) return toString(value)
} }
} }

View file

@ -37,7 +37,7 @@ private func ==(lhs: RawArgument, rhs: RawArgument) -> Bool {
} }
} }
extension RawArgument: CustomStringConvertible { extension RawArgument: Printable {
private var description: String { private var description: String {
switch self { switch self {
case let .Key(key): case let .Key(key):
@ -67,8 +67,8 @@ public final class ArgumentParser {
rawArguments.extend(options.map { arg in rawArguments.extend(options.map { arg in
if arg.hasPrefix("-") { if arg.hasPrefix("-") {
// Do we have `--{key}` or `-{flags}`. // Do we have `--{key}` or `-{flags}`.
let opt = dropFirst(arg.characters) var opt = dropFirst(arg)
return String(opt).hasPrefix("-") ? .Key(String(dropFirst(opt))) : .Flag(Set(opt)) return opt.hasPrefix("-") ? .Key(dropFirst(opt)) : .Flag(Set(opt))
} else { } else {
return .Value(arg) return .Value(arg)
} }
@ -77,7 +77,7 @@ public final class ArgumentParser {
// Remaining arguments are all positional parameters. // Remaining arguments are all positional parameters.
if params.count == 2 { if params.count == 2 {
let positional = params.last! 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 { } else {
rawArguments.append(arg) rawArguments.append(arg)
} }
} }
return .Success(foundValue) return .success(foundValue)
} }
/// Returns the next positional argument that hasn't yet been returned, or /// 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 /// Returns whether the given flag was specified and removes it from the
/// list of arguments remaining. /// list of arguments remaining.
internal func consumeBooleanFlag(flag: Character) -> Bool { internal func consumeBooleanFlag(flag: Character) -> Bool {
for (index, arg) in rawArguments.enumerate() { for (index, arg) in enumerate(rawArguments) {
switch arg { switch arg {
case var .Flag(flags) where flags.contains(flag): case var .Flag(flags) where flags.contains(flag):
flags.remove(flag) flags.remove(flag)

View file

@ -58,7 +58,7 @@ public final class CommandRegistry<ClientError> {
/// All available commands. /// All available commands.
public var commands: [CommandOf<ClientError>] { 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() {} public init() {}
@ -100,7 +100,7 @@ extension CommandRegistry {
/// If a matching command could not be found or a usage error occurred, /// 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 /// a helpful error message will be written to `stderr`, then the process
/// will exit with a failure error code. /// 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 var arguments = Process.arguments
assert(arguments.count >= 1) assert(arguments.count >= 1)
@ -119,12 +119,12 @@ extension CommandRegistry {
exit(EXIT_SUCCESS) exit(EXIT_SUCCESS)
case let .Some(.Failure(error)): case let .Some(.Failure(error)):
switch error { switch error.value {
case let .UsageError(description): case let .UsageError(description):
fputs(description + "\n", stderr) fputs(description + "\n", stderr)
case let .CommandError(error): case let .CommandError(error):
errorHandler(error) errorHandler(error.value)
} }
exit(EXIT_FAILURE) exit(EXIT_FAILURE)

View file

@ -12,22 +12,22 @@ import Foundation
/// ///
/// `ClientError` should be the type of error (if any) that can occur when /// `ClientError` should be the type of error (if any) that can occur when
/// running commands. /// running commands.
public enum CommandantError<ClientError>: ErrorType { public enum CommandantError<ClientError> {
/// An option was used incorrectly. /// An option was used incorrectly.
case UsageError(description: String) case UsageError(description: String)
/// An error occurred while running a command. /// An error occurred while running a command.
case CommandError(ClientError) case CommandError(Box<ClientError>)
} }
extension CommandantError: CustomStringConvertible { extension CommandantError: Printable {
public var description: String { public var description: String {
switch self { switch self {
case let .UsageError(description): case let .UsageError(description):
return description return description
case let .CommandError(error): 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> { internal func informativeUsageError<ClientError>(keyValueExample: String, usage: String) -> CommandantError<ClientError> {
let lines = usage.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet()) 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 return previous + "\n\t" + value
}) })
} }
@ -56,9 +56,9 @@ internal func informativeUsageError<ClientError>(keyValueExample: String, usage:
/// example of key (and value, if applicable) usage. /// example of key (and value, if applicable) usage.
internal func informativeUsageError<T, ClientError>(keyValueExample: String, option: Option<T>) -> CommandantError<ClientError> { internal func informativeUsageError<T, ClientError>(keyValueExample: String, option: Option<T>) -> CommandantError<ClientError> {
if option.defaultValue != nil { if option.defaultValue != nil {
return informativeUsageError("[\(keyValueExample)]", usage: option.usage) return informativeUsageError("[\(keyValueExample)]", option.usage)
} else { } 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 example += valueExample
} }
return informativeUsageError(example, option: option) return informativeUsageError(example, option)
} }
/// Constructs an error that describes how to use the given boolean 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! let key = option.key!
if let defaultValue = option.defaultValue { if let defaultValue = option.defaultValue {
return informativeUsageError((defaultValue ? "--no-\(key)" : "--\(key)"), option: option) return informativeUsageError((defaultValue ? "--no-\(key)" : "--\(key)"), option)
} else { } else {
return informativeUsageError("--(no-)\(key)", option: option) return informativeUsageError("--(no-)\(key)", option)
} }
} }

View file

@ -34,27 +34,28 @@ public struct HelpCommand<ClientError>: CommandType {
.flatMap { options in .flatMap { options in
if let verb = options.verb { if let verb = options.verb {
if let command = self.registry[verb] { if let command = self.registry[verb] {
print(command.function + "\n") println(command.function)
println()
return command.run(.Usage) return command.run(.Usage)
} else { } else {
fputs("Unrecognized command: '\(verb)'\n", stderr) 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 { 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 var formattedVerb = command.verb
formattedVerb.extend(padding) 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 { 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>> { static func evaluate(m: CommandMode) -> Result<HelpOptions, CommandantError<ClientError>> {

View file

@ -7,7 +7,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <string>org.carthage.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
@ -15,7 +15,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>FMWK</string> <string>FMWK</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.0</string> <string>0.6.1</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>

View file

@ -81,7 +81,7 @@ public struct Option<T> {
} }
} }
extension Option: CustomStringConvertible { extension Option: Printable {
public var description: String { public var description: String {
if let key = key { if let key = key {
return "--\(key)" return "--\(key)"
@ -104,18 +104,10 @@ extension Int: ArgumentType {
public static let name = "integer" public static let name = "integer"
public static func fromString(string: String) -> Int? { 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 { extension String: ArgumentType {
public static let name = "string" 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>> { public func <*> <T, U, ClientError>(f: Result<(T -> U), CommandantError<ClientError>>, value: Result<T, CommandantError<ClientError>>) -> Result<U, CommandantError<ClientError>> {
switch (f, value) { switch (f, value) {
case let (.Failure(left), .Failure(right)): case let (.Failure(left), .Failure(right)):
return .Failure(combineUsageErrors(left, rhs: right)) return .failure(combineUsageErrors(left.value, right.value))
case let (.Failure(left), .Success): case let (.Failure(left), .Success):
return .Failure(left) return .failure(left.value)
case let (.Success, .Failure(right)): case let (.Success, .Failure(right)):
return .Failure(right) return .failure(right.value)
case let (.Success(f), .Success(value)): case let (.Success(f), .Success(value)):
let newValue = f(value) let newValue = f.value(value.value)
return .Success(newValue) return .success(newValue)
} }
} }
@ -199,12 +191,12 @@ public func <| <T: ArgumentType, ClientError>(mode: CommandMode, option: Option<
if let key = option.key { if let key = option.key {
switch arguments.consumeValueForKey(key) { switch arguments.consumeValueForKey(key) {
case let .Success(value): case let .Success(value):
stringValue = value stringValue = value.value
case let .Failure(error): case let .Failure(error):
switch error { switch error.value {
case let .UsageError(description): case let .UsageError(description):
return .Failure(.UsageError(description: description)) return .failure(.UsageError(description: description))
case .CommandError: case .CommandError:
fatalError("CommandError should be impossible when parameterized over NoError") 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 stringValue = stringValue {
if let value = T.fromString(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 { } else if let defaultValue = option.defaultValue {
return .Success(defaultValue) return .success(defaultValue)
} else { } else {
return .Failure(missingArgumentError(option.description)) return .failure(missingArgumentError(option.description))
} }
case .Usage: 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 { switch mode {
case let .Arguments(arguments): case let .Arguments(arguments):
if let value = arguments.consumeBooleanKey(option.key!) { if let value = arguments.consumeBooleanKey(option.key!) {
return .Success(value) return .success(value)
} else if let defaultValue = option.defaultValue { } else if let defaultValue = option.defaultValue {
return .Success(defaultValue) return .success(defaultValue)
} else { } else {
return .Failure(missingArgumentError(option.description)) return .failure(missingArgumentError(option.description))
} }
case .Usage: case .Usage:
return .Failure(informativeUsageError(option)) return .failure(informativeUsageError(option))
} }
} }

View file

@ -33,7 +33,7 @@ public struct Switch {
} }
} }
extension Switch: CustomStringConvertible { extension Switch: Printable {
public var description: String { public var description: String {
var options = "--\(key)" var options = "--\(key)"
if let flag = self.flag { if let flag = self.flag {
@ -54,9 +54,9 @@ public func <| <ClientError> (mode: CommandMode, option: Switch) -> Result<Bool,
if let flag = option.flag { if let flag = option.flag {
enabled = arguments.consumeBooleanFlag(flag) enabled = arguments.consumeBooleanFlag(flag)
} }
return .Success(enabled) return .success(enabled)
case .Usage: case .Usage:
return .Failure(informativeUsageError(option.description, usage: option.usage)) return .failure(informativeUsageError(option.description, option.usage))
} }
} }

View file

@ -1,183 +1,163 @@
// Copyright (c) 2015 Rob Rix. All rights reserved. // 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. /// 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 { public enum Result<T, Error>: Printable, DebugPrintable {
case Success(T) case Success(Box<T>)
case Failure(Error) case Failure(Box<Error>)
// MARK: Constructors // MARK: Constructors
/// Constructs a success wrapping a `value`. /// Constructs a success wrapping a `value`.
public init(value: T) { public init(value: T) {
self = .Success(value) self = .Success(Box(value))
} }
/// Constructs a failure wrapping an `error`. /// Constructs a failure wrapping an `error`.
public init(error: Error) { public init(error: Error) {
self = .Failure(error) self = .Failure(Box(error))
} }
/// Constructs a result from an Optional, failing with `Error` if `nil` /// Constructs a result from an Optional, failing with `Error` if `nil`
public init(_ value: T?, @autoclosure failWith: () -> Error) { public init(_ value: T?, @autoclosure failWith: () -> Error) {
self = value.map(Result.Success) ?? .Failure(failWith()) self = value.map { .success($0) } ?? .failure(failWith())
} }
/// Constructs a result from a function that uses `throw`, failing with `Error` if throws /// Constructs a success wrapping a `value`.
public init(@autoclosure _ f: () throws -> T) { public static func success(value: T) -> Result {
do { return Result(value: value)
self = .Success(try f()) }
} catch {
self = .Failure(error as! Error) /// Constructs a failure wrapping an `error`.
} public static func failure(error: Error) -> Result {
} return Result(error: error)
}
// MARK: Deconstruction
// MARK: Deconstruction
/// Returns the value from `Success` Results or `throw`s the error
public func dematerialize() throws -> T { /// Returns the value from `Success` Results, `nil` otherwise.
switch self { public var value: T? {
case let .Success(value): return analysis(ifSuccess: { $0 }, ifFailure: { _ in nil })
return value }
case let .Failure(error):
throw error /// Returns the error from `Failure` Results, `nil` otherwise.
} public var error: Error? {
} return analysis(ifSuccess: { _ in nil }, ifFailure: { $0 })
}
/// Case analysis for Result.
/// /// 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 { /// Returns the value produced by applying `ifFailure` to `Failure` Results, or `ifSuccess` to `Success` Results.
switch self { public func analysis<Result>(@noescape #ifSuccess: T -> Result, @noescape ifFailure: Error -> Result) -> Result {
case let .Success(value): switch self {
return ifSuccess(value) case let .Success(value):
case let .Failure(value): return ifSuccess(value.value)
return ifFailure(value) case let .Failure(value):
} return ifFailure(value.value)
} }
}
// MARK: Higher-order functions
// 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> { /// Returns a new Result by mapping `Success`es values using `transform`, or re-wrapping `Failure`s errors.
return flatMap { .Success(transform($0)) } 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> { /// Returns the result of applying `transform` to `Success`es values, or re-wrapping `Failure`s errors.
return analysis( public func flatMap<U>(@noescape transform: T -> Result<U, Error>) -> Result<U, Error> {
ifSuccess: transform, return analysis(
ifFailure: Result<U, Error>.Failure) 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 { /// Returns `self.value` if this result is a .Success, or the given value otherwise. Equivalent with `??`
return self.value ?? value() 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> { /// Returns this result if it is a .Success, or the given result otherwise. Equivalent with `??`
return analysis( public func recoverWith(@autoclosure result: () -> Result<T,Error>) -> Result<T,Error> {
ifSuccess: { _ in self }, return analysis(
ifFailure: { _ in result() }) 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 // MARK: Errors
// do {
// return .Success(try f(x)) /// The domain for errors constructed by Result.
// } catch { public static var errorDomain: String { return "com.antitypical.Result" }
// return .Failure(error)
// } /// 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" }
// MARK: Errors
/// The userInfo key for source file line numbers in errors constructed by Result.
/// The domain for errors constructed by Result. public static var lineKey: String { return "\(errorDomain).line" }
public static var errorDomain: String { return "com.antitypical.Result" }
/// Constructs an error.
/// The userInfo key for source functions in errors constructed by Result. public static func error(message: String? = nil, function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__) -> NSError {
public static var functionKey: String { return "\(errorDomain).function" } var userInfo: [String: AnyObject] = [
functionKey: function,
/// The userInfo key for source file paths in errors constructed by Result. fileKey: file,
public static var fileKey: String { return "\(errorDomain).file" } lineKey: line,
]
/// The userInfo key for source file line numbers in errors constructed by Result.
public static var lineKey: String { return "\(errorDomain).line" } if let message = message {
userInfo[NSLocalizedDescriptionKey] = message
/// Constructs an error. }
public static func error(message: String? = nil, function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__) -> NSError {
var userInfo: [String: AnyObject] = [ return NSError(domain: errorDomain, code: 0, userInfo: userInfo)
functionKey: function, }
fileKey: file,
lineKey: line,
] // MARK: Printable
if let message = message { public var description: String {
userInfo[NSLocalizedDescriptionKey] = message return analysis(
} ifSuccess: { ".Success(\($0))" },
ifFailure: { ".Failure(\($0))" })
return NSError(domain: errorDomain, code: 0, userInfo: userInfo) }
}
// MARK: DebugPrintable
// MARK: CustomStringConvertible
public var debugDescription: String {
public var description: String { return description
return analysis( }
ifSuccess: { ".Success(\($0))" },
ifFailure: { ".Failure(\($0))" })
}
// MARK: CustomDebugStringConvertible
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. /// 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 { public func == <T: Equatable, Error: Equatable> (left: Result<T, Error>, right: Result<T, Error>) -> Bool {
if let left = left.value, right = right.value { if let left = left.value, right = right.value {
return left == right return left == right
} else if let left = left.error, right = right.error { } else if let left = left.error, right = right.error {
return left == right return left == right
} }
return false return false
} }
/// Returns `true` if `left` and `right` represent different cases, or if they represent the same case but different values. /// 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 { 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. /// 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 { 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. /// 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> { 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 // 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.: /// 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) } /// 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> { public func try<T>(function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__, try: NSErrorPointer -> T?) -> Result<T, NSError> {
var error: NSError? var error: NSError?
return `try`(&error).map(Result.Success) ?? .Failure(error ?? Result<T, NSError>.error(function: function, file: file, line: line)) 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. /// 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.: /// 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) } /// 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> { public func try(function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__, try: NSErrorPointer -> Bool) -> Result<(), NSError> {
var error: NSError? var error: NSError?
return `try`(&error) ? return try(&error) ?
.Success(()) .success(())
: .Failure(error ?? Result<(), NSError>.error(function: function, file: file, line: line)) : .failure(error ?? Result<(), NSError>.error(function: function, file: file, line: line))
} }
// MARK: - Operators // MARK: - Operators
infix operator >>- { infix operator >>- {
// Left-associativity so that chaining works like youd expect, and for consistency with Haskell, Runes, swiftz, etc. // Left-associativity so that chaining works like youd expect, and for consistency with Haskell, Runes, swiftz, etc.
associativity left associativity left
// Higher precedence than function application, but lower than function composition. // Higher precedence than function application, but lower than function composition.
precedence 100 precedence 100
} }
infix operator &&& { infix operator &&& {
/// Same associativity as &&. /// Same associativity as &&.
associativity left associativity left
/// Same precedence as &&. /// Same precedence as &&.
precedence 120 precedence 120
} }
/// Returns the result of applying `transform` to `Success`es values, or re-wrapping `Failure`s errors. /// Returns the result of applying `transform` to `Success`es values, or re-wrapping `Failure`s errors.
/// ///
/// This is a synonym for `flatMap`. /// This is a synonym for `flatMap`.
public func >>- <T, U, Error> (result: Result<T, Error>, @noescape transform: T -> Result<U, Error>) -> Result<U, Error> { 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`. /// 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> { 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

View file

@ -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 })
}
}

View file

@ -15,7 +15,6 @@
ED128ECE1B6C2A0B00C4050A /* Option.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EC71B6C2A0B00C4050A /* Option.swift */; }; ED128ECE1B6C2A0B00C4050A /* Option.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EC71B6C2A0B00C4050A /* Option.swift */; };
ED128ECF1B6C2A0B00C4050A /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EC81B6C2A0B00C4050A /* Switch.swift */; }; ED128ECF1B6C2A0B00C4050A /* Switch.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EC81B6C2A0B00C4050A /* Switch.swift */; };
ED128ED31B6C2AA200C4050A /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128ED21B6C2AA200C4050A /* Result.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 */; }; ED128EDC1B6C2B4400C4050A /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128ED91B6C2B4400C4050A /* Box.swift */; };
ED128EDD1B6C2B4400C4050A /* BoxType.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EDA1B6C2B4400C4050A /* BoxType.swift */; }; ED128EDD1B6C2B4400C4050A /* BoxType.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EDA1B6C2B4400C4050A /* BoxType.swift */; };
ED128EDE1B6C2B4400C4050A /* MutableBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED128EDB1B6C2B4400C4050A /* MutableBox.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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; ED128EDA1B6C2B4400C4050A /* BoxType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoxType.swift; sourceTree = "<group>"; };
@ -303,7 +301,6 @@
children = ( children = (
ED128ED11B6C2A8B00C4050A /* Result.h */, ED128ED11B6C2A8B00C4050A /* Result.h */,
ED128ED21B6C2AA200C4050A /* Result.swift */, ED128ED21B6C2AA200C4050A /* Result.swift */,
ED128ED41B6C2AB700C4050A /* ResultType.swift */,
); );
path = Result; path = Result;
sourceTree = "<group>"; sourceTree = "<group>";
@ -598,7 +595,6 @@
ED128EDE1B6C2B4400C4050A /* MutableBox.swift in Sources */, ED128EDE1B6C2B4400C4050A /* MutableBox.swift in Sources */,
ED128ECA1B6C2A0B00C4050A /* ArgumentParser.swift in Sources */, ED128ECA1B6C2A0B00C4050A /* ArgumentParser.swift in Sources */,
ED128ECB1B6C2A0B00C4050A /* Command.swift in Sources */, ED128ECB1B6C2A0B00C4050A /* Command.swift in Sources */,
ED128ED51B6C2AB700C4050A /* ResultType.swift in Sources */,
ED128ECE1B6C2A0B00C4050A /* Option.swift in Sources */, ED128ECE1B6C2A0B00C4050A /* Option.swift in Sources */,
ED128ECD1B6C2A0B00C4050A /* HelpCommand.swift in Sources */, ED128ECD1B6C2A0B00C4050A /* HelpCommand.swift in Sources */,
ED128ED31B6C2AA200C4050A /* Result.swift in Sources */, ED128ED31B6C2AA200C4050A /* Result.swift in Sources */,
@ -694,6 +690,7 @@
); );
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "mas-cli/mas-cli-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "mas-cli/mas-cli-Bridging-Header.h";
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/mas-cli/Headers/**";
}; };
name = Debug; name = Debug;
}; };
@ -706,6 +703,7 @@
); );
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "mas-cli/mas-cli-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "mas-cli/mas-cli-Bridging-Header.h";
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/mas-cli/Headers/**";
}; };
name = Release; name = Release;
}; };

View file

@ -24,7 +24,7 @@
- (BOOL)isTrialVersionOfBundleIdentifier:(id)arg1; - (BOOL)isTrialVersionOfBundleIdentifier:(id)arg1;
- (id)receiptFromBundleAtPath:(id)arg1; - (id)receiptFromBundleAtPath:(id)arg1;
- (id)productForPath:(id)arg1; - (id)productForPath:(id)arg1;
- (NSArray<CKSoftwareProduct *>*)allProducts; - (NSArray*)allProducts;
- (CKSoftwareProduct *)productForItemIdentifier:(unsigned long long)arg1; - (CKSoftwareProduct *)productForItemIdentifier:(unsigned long long)arg1;
- (CKSoftwareProduct *)productForBundleIdentifier:(NSString *)arg1; - (CKSoftwareProduct *)productForBundleIdentifier:(NSString *)arg1;
- (void)removeProductsObserver:(id)arg1; - (void)removeProductsObserver:(id)arg1;

View file

@ -20,7 +20,7 @@ func primaryAccount() -> ISStoreAccount {
if let activePhase = download.status.activePhase { if let activePhase = download.status.activePhase {
let percentage = String(Int(floor(download.status.percentComplete * 100))) + "%" let percentage = String(Int(floor(download.status.percentComplete * 100))) + "%"
// let phase = String(activePhase.phaseType) // 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: default:
break break
} }
return .Success(()) return .success(())
} }
} }
@ -102,13 +102,13 @@ struct InstallCommand: CommandType {
struct InstallOptions: OptionsType { struct InstallOptions: OptionsType {
let appId: UInt64 let appId: UInt64
static func create(appId: UInt64) -> InstallOptions { static func create(appId: Int) -> InstallOptions {
return InstallOptions(appId: appId) return InstallOptions(appId: UInt64(appId))
} }
static func evaluate(m: CommandMode) -> Result<InstallOptions, CommandantError<MASError>> { static func evaluate(m: CommandMode) -> Result<InstallOptions, CommandantError<MASError>> {
return create 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: default:
break break
} }
return .Success(()) return .success(())
} }
} }
@ -145,11 +145,11 @@ struct ListInstalledCommand: CommandType {
default: default:
break break
} }
return .Success(()) return .success(())
} }
} }
public enum MASError: ErrorType, Equatable { public enum MASError: Equatable {
public var description: String { public var description: String {
return "" return ""
} }