diff --git a/README.md b/README.md index 9bda7a0..acce05a 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ [![ci](https://github.com/MFB-Technologies-Inc/swift-argument-encoding/actions/workflows/ci.yml/badge.svg)](https://github.com/MFB-Technologies-Inc/swift-argument-encoding/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/MFB-Technologies-Inc/swift-argument-encoding/branch/main/graph/badge.svg?token=UU95IDUXAX)](https://codecov.io/gh/MFB-Technologies-Inc/swift-argument-encoding) +[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FMFB-Technologies-Inc%2Fswift-argument-encoding%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/MFB-Technologies-Inc/swift-argument-encoding) +[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FMFB-Technologies-Inc%2Fswift-argument-encoding%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/MFB-Technologies-Inc/swift-argument-encoding) A library for encoding types into an Array of Strings, or 'arguments'. diff --git a/Sources/ArgumentEncoding/CommandRepresentable.swift b/Sources/ArgumentEncoding/CommandRepresentable.swift index 3399259..cd8c09f 100644 --- a/Sources/ArgumentEncoding/CommandRepresentable.swift +++ b/Sources/ArgumentEncoding/CommandRepresentable.swift @@ -35,8 +35,8 @@ import Dependencies /// let arguments = container.arguments() /// ``` /// -/// `CommandRepresentable` inherits from ``ArgumentGroup`` and ``FormatterNode`` -public protocol CommandRepresentable: ArgumentGroup, FormatterNode {} +/// `CommandRepresentable` inherits from ``ArgumentGroup`` +public protocol CommandRepresentable: ArgumentGroup {} extension CommandRepresentable { /// Prefixes the child arguments with an explicit command value. diff --git a/Sources/ArgumentEncoding/Option.swift b/Sources/ArgumentEncoding/Option.swift index 260269d..c0d05f8 100644 --- a/Sources/ArgumentEncoding/Option.swift +++ b/Sources/ArgumentEncoding/Option.swift @@ -127,32 +127,6 @@ extension Option where Value: CustomStringConvertible { } } -// MARK: Convenience initializers when Value: RawRepresentable and Value.RawValue == String - -extension Option where Value: RawRepresentable, Value.RawValue == String { - /// Initializes a new option when not used as a `@propertyWrapper` - /// - /// - Parameters - /// - key: Explicit key value - /// - wrappedValue: The underlying value - public init(key: some CustomStringConvertible, value: Value) { - keyOverride = key.description - wrappedValue = value - unwrap = { [$0.rawValue] } - } - - /// Initializes a new option when used as a `@propertyWrapper` - /// - /// - Parameters - /// - wrappedValue: The underlying value - /// - _ key: Optional explicit key value - public init(wrappedValue: Value, _ key: String? = nil) { - keyOverride = key - self.wrappedValue = wrappedValue - unwrap = { [$0.rawValue] } - } -} - // MARK: Convenience initializers when Value == Optional extension Option { @@ -181,32 +155,6 @@ extension Option { self.wrappedValue = wrappedValue unwrap = { [$0?.description].compactMap { $0 } } } - - /// Initializes a new option when not used as a `@propertyWrapper` - /// - /// - Parameters - /// - key: Explicit key value - /// - wrappedValue: The underlying value - public init(key: some CustomStringConvertible, value: Wrapped?) where Wrapped: RawRepresentable, - Wrapped.RawValue == String, Value == Wrapped? - { - keyOverride = key.description - wrappedValue = value - unwrap = { [$0?.rawValue].compactMap { $0 } } - } - - /// Initializes a new option when used as a `@propertyWrapper` - /// - /// - Parameters - /// - wrappedValue: The underlying value - /// - _ key: Optional explicit key value - public init(wrappedValue: Wrapped?, _ key: String? = nil) where Wrapped: RawRepresentable, - Wrapped.RawValue == String, Value == Wrapped? - { - keyOverride = key - self.wrappedValue = wrappedValue - unwrap = { [$0?.rawValue].compactMap { $0 } } - } } // MARK: Convenience initializers when Value == Sequence @@ -237,32 +185,6 @@ extension Option { self.wrappedValue = wrappedValue unwrap = { $0.map(\E.description) } } - - /// Initializes a new option when not used as a `@propertyWrapper` - /// - /// - Parameters - /// - key: Explicit key value - /// - wrappedValue: The underlying value - public init(key: some CustomStringConvertible, values: Value) where Value: Sequence, Value.Element == E, - E: RawRepresentable, E.RawValue == String - { - keyOverride = key.description - wrappedValue = values - unwrap = { $0.map(\E.rawValue) } - } - - /// Initializes a new option when used as a `@propertyWrapper` - /// - /// - Parameters - /// - wrappedValue: The underlying value - /// - _ key: Optional explicit key value - public init(wrappedValue: Value, _ key: String? = nil) where Value: Sequence, Value.Element == E, - E: RawRepresentable, E.RawValue == String - { - keyOverride = key - self.wrappedValue = wrappedValue - unwrap = { $0.map(\E.rawValue) } - } } // MARK: ExpressibleBy...Literal conformances @@ -305,6 +227,20 @@ extension Option: ExpressibleByStringInterpolation where Value: StringProtocol { } } +extension Option: Decodable where Value: Decodable & CustomStringConvertible { + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + self.init(wrappedValue: try container.decode(Value.self)) + } +} + +extension Option: Encodable where Value: Encodable { + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(wrappedValue) + } +} + // MARK: Internal Types /* diff --git a/Sources/ArgumentEncoding/TopLevelCommandRepresentable.swift b/Sources/ArgumentEncoding/TopLevelCommandRepresentable.swift index 92857ef..fe7ec0b 100644 --- a/Sources/ArgumentEncoding/TopLevelCommandRepresentable.swift +++ b/Sources/ArgumentEncoding/TopLevelCommandRepresentable.swift @@ -34,7 +34,7 @@ /// ``` /// /// `TopLevelCommandRepresentable` inherits from ``ArgumentGroup``, ``FormatterNode``, and ``CommandRepresentable`` -public protocol TopLevelCommandRepresentable: CommandRepresentable { +public protocol TopLevelCommandRepresentable: CommandRepresentable, FormatterNode { func commandValue() -> Command } diff --git a/Tests/ArgumentEncodingTests/ArgumentGroupTests.swift b/Tests/ArgumentEncodingTests/ArgumentGroupTests.swift index b826ef6..313a5cb 100644 --- a/Tests/ArgumentEncodingTests/ArgumentGroupTests.swift +++ b/Tests/ArgumentEncodingTests/ArgumentGroupTests.swift @@ -75,9 +75,11 @@ final class ArgumentGroupTests: XCTestCase { self.buildTests = buildTests } - enum Configuration: String { + enum Configuration: String, CustomStringConvertible { case arm64 case x86_64 + + var description: String { rawValue } } } diff --git a/Tests/ArgumentEncodingTests/CommandRepresentableTests.swift b/Tests/ArgumentEncodingTests/CommandRepresentableTests.swift index f0d625b..d6b98b6 100644 --- a/Tests/ArgumentEncodingTests/CommandRepresentableTests.swift +++ b/Tests/ArgumentEncodingTests/CommandRepresentableTests.swift @@ -7,9 +7,9 @@ import ArgumentEncoding import XCTest final class CommandRepresentableTests: XCTestCase { - private struct Container: ArgumentGroup where T: CommandRepresentable { - static var flagFormatter: FlagFormatter { .doubleDashPrefix } - static var optionFormatter: OptionFormatter { .doubleDashPrefix } + private struct Container: ArgumentGroup, FormatterNode where T: CommandRepresentable { + var flagFormatter: FlagFormatter { .doubleDashPrefix } + var optionFormatter: OptionFormatter { .doubleDashPrefix } var command: T @@ -18,7 +18,7 @@ final class CommandRepresentableTests: XCTestCase { } } - private struct EmptyCommand: CommandRepresentable { + private struct EmptyCommand: CommandRepresentable, FormatterNode { let flagFormatter: FlagFormatter = .doubleDashPrefix let optionFormatter: OptionFormatter = .doubleDashPrefix } @@ -29,7 +29,7 @@ final class CommandRepresentableTests: XCTestCase { XCTAssertEqual(args, ["command"]) } - private struct CommandGroup: CommandRepresentable { + private struct CommandGroup: CommandRepresentable, FormatterNode { let flagFormatter: FlagFormatter = .doubleDashPrefix let optionFormatter: OptionFormatter = .doubleDashPrefix @@ -67,7 +67,7 @@ final class CommandRepresentableTests: XCTestCase { ) } - private struct ParentCommand: CommandRepresentable { + private struct ParentCommand: CommandRepresentable, FormatterNode { let flagFormatter: FlagFormatter = .doubleDashPrefix let optionFormatter: OptionFormatter = .doubleDashPrefix @@ -82,7 +82,7 @@ final class CommandRepresentableTests: XCTestCase { } } - private struct ChildCommand: CommandRepresentable { + private struct ChildCommand: CommandRepresentable, FormatterNode { let flagFormatter: FlagFormatter = .singleDashPrefix let optionFormatter: OptionFormatter = .singleDashPrefix @@ -94,9 +94,13 @@ final class CommandRepresentableTests: XCTestCase { self.buildTests = buildTests } - enum Configuration: String { + enum Configuration: String, CustomStringConvertible { case arm64 case x86_64 + + var description: String { + rawValue + } } } @@ -126,7 +130,7 @@ final class CommandRepresentableTests: XCTestCase { ) } - private enum ParentEnumCommand: CommandRepresentable { + private enum ParentEnumCommand: CommandRepresentable, FormatterNode { var flagFormatter: FlagFormatter { .singleDashPrefix } var optionFormatter: OptionFormatter { .singleDashPrefix } diff --git a/Tests/ArgumentEncodingTests/TopLevelCommandRepresentableTests.swift b/Tests/ArgumentEncodingTests/TopLevelCommandRepresentableTests.swift index 25f62e3..54d0b09 100644 --- a/Tests/ArgumentEncodingTests/TopLevelCommandRepresentableTests.swift +++ b/Tests/ArgumentEncodingTests/TopLevelCommandRepresentableTests.swift @@ -73,7 +73,7 @@ final class TopLevelCommandRepresentableTests: XCTestCase { self.child = child } - struct ChildCommand: CommandRepresentable { + struct ChildCommand: CommandRepresentable, FormatterNode { func commandValue() -> Command { "child" } let flagFormatter: FlagFormatter = .singleDashPrefix let optionFormatter: OptionFormatter = .singleDashPrefix @@ -86,9 +86,11 @@ final class TopLevelCommandRepresentableTests: XCTestCase { self.buildTests = buildTests } - enum Configuration: String { + enum Configuration: String, CustomStringConvertible { case arm64 case x86_64 + + var description: String { rawValue } } } } @@ -142,9 +144,11 @@ final class TopLevelCommandRepresentableTests: XCTestCase { self.buildTests = buildTests } - enum Configuration: String { + enum Configuration: String, CustomStringConvertible { case arm64 case x86_64 + + var description: String { rawValue } } } diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..bda61f3 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,3 @@ +coverage: + status: + patch: false \ No newline at end of file