diff --git a/Sources/DiffableTextKitXPattern/Placeholders.swift b/Sources/DiffableTextKitXPattern/Placeholders.swift index 1047a0d0..5edafc1f 100644 --- a/Sources/DiffableTextKitXPattern/Placeholders.swift +++ b/Sources/DiffableTextKitXPattern/Placeholders.swift @@ -11,7 +11,7 @@ // MARK: * Placeholders //*============================================================================* -public struct PatternTextPlaceholders: Equatable { +public struct PatternTextPlaceholders: Equatable, ExpressibleByDictionaryLiteral { @usableFromInline typealias Predicate = (Character) -> Bool @@ -41,6 +41,13 @@ public struct PatternTextPlaceholders: Equatable { self.option = .many(Many(many)) } + @inlinable public init(dictionaryLiteral elements: (Character, (Character) -> Bool)...) { + switch elements.count /* O(1) */ { + case 0: self.init() + case 1: self.init(elements[0]) + default: self.init(Dictionary(elements, uniquingKeysWith: { $1 })) } + } + //=------------------------------------------------------------------------= // MARK: Accessors //=------------------------------------------------------------------------= diff --git a/Sources/DiffableTextKitXPattern/Style.swift b/Sources/DiffableTextKitXPattern/Style.swift index 44c090ee..791a958c 100644 --- a/Sources/DiffableTextKitXPattern/Style.swift +++ b/Sources/DiffableTextKitXPattern/Style.swift @@ -24,14 +24,14 @@ Value: RangeReplaceableCollection, Value.Element == Character { public var pattern: String public var placeholders: Placeholders - public var hidden: Bool = false + public var hidden: Bool //=------------------------------------------------------------------------= // MARK: Initializers //=------------------------------------------------------------------------= - @inlinable public init(_ pattern: String, placeholders: Placeholders = .init()) { - self.pattern = pattern; self.placeholders = placeholders + @inlinable public init(_ pattern: String, placeholders: Placeholders = .init(), hidden: Bool = false) { + self.pattern = pattern; self.placeholders = placeholders; self.hidden = hidden } //=------------------------------------------------------------------------= diff --git a/Sources/DiffableTextKitXUIKit/Environment+AutocorrectionDisabled.swift b/Sources/DiffableTextKitXUIKit/Environment+AutocorrectionDisabled.swift index ee864fa3..5ab2cfb2 100644 --- a/Sources/DiffableTextKitXUIKit/Environment+AutocorrectionDisabled.swift +++ b/Sources/DiffableTextKitXUIKit/Environment+AutocorrectionDisabled.swift @@ -44,7 +44,7 @@ public extension View { /// It is similar to `View/autocorrectionDisabled(_:)`. /// /// ``` - /// DiffableTextField("Text", value: $text, style: .normal) + /// DiffableTextField("Text...", value: $text, style: .normal) /// .diffableTextViews_autocorrectionDisabled(true) /// ``` /// diff --git a/Sources/DiffableTextKitXUIKit/Environment+Font.swift b/Sources/DiffableTextKitXUIKit/Environment+Font.swift index 0747b342..396b1f69 100644 --- a/Sources/DiffableTextKitXUIKit/Environment+Font.swift +++ b/Sources/DiffableTextKitXUIKit/Environment+Font.swift @@ -44,7 +44,7 @@ public extension View { /// It is similar to `View/font(_:)` but uses a SwiftUI-esque system font type. /// /// ``` - /// DiffableTextField("Monospaced", value: $value, style: style) + /// DiffableTextField("Amount", value: $amount, style: .number) /// .diffableTextViews_font(.body.monospaced()) /// ``` /// diff --git a/Sources/DiffableTextKitXUIKit/Environment+KeyboardType.swift b/Sources/DiffableTextKitXUIKit/Environment+KeyboardType.swift index df96d5c1..e0446907 100644 --- a/Sources/DiffableTextKitXUIKit/Environment+KeyboardType.swift +++ b/Sources/DiffableTextKitXUIKit/Environment+KeyboardType.swift @@ -44,7 +44,7 @@ public extension View { /// It is similar to `View/keyboardType(_:)`. /// /// ``` - /// TextField("Amount", value: $amount, style: .currency("USD")) + /// DiffableTextField("Amount", value: $amount, style: .number) /// .diffableTextViews_keyboardType(.decimalPad) /// ``` /// diff --git a/Sources/DiffableTextKitXUIKit/Environment+MultilineTextAlignment.swift b/Sources/DiffableTextKitXUIKit/Environment+MultilineTextAlignment.swift index f37f1392..a7724377 100644 --- a/Sources/DiffableTextKitXUIKit/Environment+MultilineTextAlignment.swift +++ b/Sources/DiffableTextKitXUIKit/Environment+MultilineTextAlignment.swift @@ -44,7 +44,7 @@ public extension View { /// It is similar to `View/multilineTextAlignment(_:)`. /// /// ``` - /// DiffableTextField("Amount", value: $value, style: .number) + /// DiffableTextField("Amount", value: $amount, style: .number) /// .diffableTextViews_multilineTextAlignment(.trailing) /// ``` /// diff --git a/Sources/DiffableTextKitXUIKit/Environment+SubmitLabel.swift b/Sources/DiffableTextKitXUIKit/Environment+SubmitLabel.swift index 0a150808..d44a1c96 100644 --- a/Sources/DiffableTextKitXUIKit/Environment+SubmitLabel.swift +++ b/Sources/DiffableTextKitXUIKit/Environment+SubmitLabel.swift @@ -44,8 +44,8 @@ public extension View { /// It is similar to `View/submitLabel(_:)`. /// /// ``` - /// DiffableTextField("Prints on submit...", value: $value, style: style) - /// .diffableTextViews_submitLabel(.return) + /// DiffableTextField("Search", value: $text, style: .normal) + /// .diffableTextViews_submitLabel(.search) /// ``` /// /// **Notes** diff --git a/Sources/DiffableTextKitXUIKit/Environment+TextContentType.swift b/Sources/DiffableTextKitXUIKit/Environment+TextContentType.swift index f457c31c..11a1dd45 100644 --- a/Sources/DiffableTextKitXUIKit/Environment+TextContentType.swift +++ b/Sources/DiffableTextKitXUIKit/Environment+TextContentType.swift @@ -45,8 +45,12 @@ public extension View { /// It is similar to `View/textContentType(_:)`. /// /// ``` - /// DiffableTextField("Enter your email", text: $emailAddress) - /// .diffableTextViews_textContentTypetextContentType(.emailAddress) + /// DiffableTextField("Phone", value: $address) { + /// .pattern("+## (###) ###-##-##") + /// .placeholders("#") { $0.isASCII && $0.isNumber } + /// .equals(()) + /// } + /// .diffableTextViews_textContentType(.telephoneNumber) /// ``` /// /// **Notes** diff --git a/Sources/DiffableTextKitXUIKit/Environment+TextFieldStyle.swift b/Sources/DiffableTextKitXUIKit/Environment+TextFieldStyle.swift index 7ee6d66e..9602fb30 100644 --- a/Sources/DiffableTextKitXUIKit/Environment+TextFieldStyle.swift +++ b/Sources/DiffableTextKitXUIKit/Environment+TextFieldStyle.swift @@ -41,7 +41,7 @@ public extension View { /// Sets the text field style for diffable text views. /// - /// It is similar to View/textFieldStyle, but based on UIKit. + /// It is similar to `View/textFieldStyle(_:), but based on UIKit. /// /// ``` /// DiffableTextField("Bordered", value: $value, style: style) @@ -52,7 +52,7 @@ public extension View { /// /// - The value is read when the view is set up. /// - The default value is `UITextField.BorderStyle.none`. - /// - The `View/textFieldStyle` environment value is inaccessible. + /// - The `View/textFieldStyle(_:)` environment value is inaccessible. /// @inlinable func diffableTextViews_textFieldStyle(_ style: UITextField.BorderStyle) -> some View { self.environment(\.diffableTextViews_textFieldStyle, style) diff --git a/Sources/DiffableTextKitXUIKit/Environment+Tint.swift b/Sources/DiffableTextKitXUIKit/Environment+Tint.swift index 59796543..fe9d260c 100644 --- a/Sources/DiffableTextKitXUIKit/Environment+Tint.swift +++ b/Sources/DiffableTextKitXUIKit/Environment+Tint.swift @@ -44,8 +44,8 @@ public extension View { /// It is similar to `View/tint(_:)` and affects text selection. /// /// ``` - /// DiffableTextField("Look, selection is green!", value: $value) - /// .diffableTextViews_tint(.green) + /// DiffableTextField("Tinted", value: $value, style: style) + /// .diffableTextViews_tint(.gray) /// ``` /// /// **Notes** diff --git a/Sources/DiffableTextKitXUIKit/Environment+ToolbarDoneButton.swift b/Sources/DiffableTextKitXUIKit/Environment+ToolbarDoneButton.swift index cf98132b..bbb80a1b 100644 --- a/Sources/DiffableTextKitXUIKit/Environment+ToolbarDoneButton.swift +++ b/Sources/DiffableTextKitXUIKit/Environment+ToolbarDoneButton.swift @@ -59,7 +59,7 @@ public extension View { /// /// - The value is read when the view is set up. /// - The default value is `nil` (no toolbar installed). - /// - The `SwiftUI/toolbar` environment value is inaccessible. + /// - The `View/toolbar(_:)` environment value is inaccessible. /// @inlinable func diffableTextViews_toolbarDoneButton(_ style: UIBarButtonItem.Style = .plain) -> some View { self.environment(\.diffableTextViews_toolbarDoneButton, style) diff --git a/Tests/DiffableTextKitXPatternTests/Placeholders.swift b/Tests/DiffableTextKitXPatternTests/Placeholders.swift index 32b3b68e..1fb7c896 100644 --- a/Tests/DiffableTextKitXPatternTests/Placeholders.swift +++ b/Tests/DiffableTextKitXPatternTests/Placeholders.swift @@ -30,14 +30,13 @@ final class PlaceholdersTests: XCTestCase { lazy var many = Placeholders(["#": \.isNumber, "@": \.isLetter]) //=------------------------------------------------------------------------= - // MARK: Assertions + // MARK: Tests x Init //=------------------------------------------------------------------------= - func AssertSubscriptResults(_ instance: Placeholders, - _ scenarios: () -> [(Character, Character, Bool?)]) { - for scenario in scenarios() { - XCTAssertEqual(instance[scenario.0]?(scenario.1), scenario.2) - } + func testExpressibleByDictionaryLiteral() { + XCTAssertEqual(none, [:]) + XCTAssertEqual(some, ["#": \.isNumber]) + XCTAssertEqual(many, ["#": \.isNumber, "@": \.isLetter]) } //=------------------------------------------------------------------------= @@ -91,6 +90,16 @@ final class PlaceholdersTests: XCTestCase { Placeholders(["A": { _ in true }, "B": { _ in true }]), Placeholders(["A": { _ in true }, "_": { _ in true }])) } + + //=------------------------------------------------------------------------= + // MARK: Assertions + //=------------------------------------------------------------------------= + + func AssertSubscriptResults(_ instance: Placeholders, _ scenarios: () -> [(Character, Character, Bool?)]) { + for scenario in scenarios() { + XCTAssertEqual(instance[scenario.0]?(scenario.1), scenario.2) + } + } } #endif diff --git a/Tests/DiffableTextKitXPatternTests/Style+Hidden.swift b/Tests/DiffableTextKitXPatternTests/Style+Hidden.swift index 7340832e..4f45b96e 100644 --- a/Tests/DiffableTextKitXPatternTests/Style+Hidden.swift +++ b/Tests/DiffableTextKitXPatternTests/Style+Hidden.swift @@ -24,7 +24,7 @@ final class StyleTestsOnHidden: XCTestCase, StyleTests { //=------------------------------------------------------------------------= let style = PatternTextStyle - .pattern("+### (###) ##-##-##") + .pattern("+## (###) ###-##-##") .placeholders("#") { $0.isASCII && $0.isNumber } .hidden(true) @@ -33,37 +33,33 @@ final class StyleTestsOnHidden: XCTestCase, StyleTests { //=------------------------------------------------------------------------= func testNone() { - XCTFormat___("", format: "+") - XCTInterpret("", format: "+", value: "") + OKFormat___("", format: "+") + OKInterpret("", format: "+", value: "") } func testSome() { - XCTFormat___("12300045", format: "+123 (000) 45") - XCTInterpret("12300045", format: "+123 (000) 45", value: "12300045") + OKFormat___("12000345", format: "+12 (000) 345") + OKInterpret("12000345", format: "+12 (000) 345", value: "12000345") } func testFull() { - XCTFormat___("123000456789", format: "+123 (000) 45-67-89") - XCTInterpret("123000456789", format: "+123 (000) 45-67-89", value: "123000456789") + OKFormat___("120003456789", format: "+12 (000) 345-67-89") + OKInterpret("120003456789", format: "+12 (000) 345-67-89", value: "120003456789") } func testMore() { - XCTFormat___("123000456789000", format: "+123 (000) 45-67-89|000") - XCTInterpret("123000456789000", format: "+123 (000) 45-67-89", value: "123000456789") + OKFormat___("120003456789000", format: "+12 (000) 345-67-89|000") + OKInterpret("120003456789000", format: "+12 (000) 345-67-89", value: "120003456789") } - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - func testNoneMismatch() { - XCTFormat___("ABC", format: "+|ABC") - XCTInterpret("ABC", format: "+", value: "") + OKFormat___("ABC", format: "+|ABC") + OKInterpret("ABC", format: "+", value: "") } func testSomeMismatch() { - XCTFormat___("12300045ABC", format: "+123 (000) 45|ABC") - XCTInterpret("12300045ABC", format: "+123 (000) 45", value: "12300045") + OKFormat___("12000345ABC", format: "+12 (000) 345|ABC") + OKInterpret("12000345ABC", format: "+12 (000) 345", value: "12000345") } } diff --git a/Tests/DiffableTextKitXPatternTests/Style+Visible.swift b/Tests/DiffableTextKitXPatternTests/Style+Visible.swift index ec66fcc1..1ee4813e 100644 --- a/Tests/DiffableTextKitXPatternTests/Style+Visible.swift +++ b/Tests/DiffableTextKitXPatternTests/Style+Visible.swift @@ -24,7 +24,7 @@ final class StyleTestsOnVisible: XCTestCase, StyleTests { //=------------------------------------------------------------------------= let style = PatternTextStyle - .pattern("+### (###) ##-##-##") + .pattern("+## (###) ###-##-##") .placeholders("#") { $0.isASCII && $0.isNumber } .hidden(false) @@ -33,37 +33,33 @@ final class StyleTestsOnVisible: XCTestCase, StyleTests { //=------------------------------------------------------------------------= func testNone() { - XCTFormat___("", format: "+### (###) ##-##-##") - XCTInterpret("", format: "+### (###) ##-##-##", value: "") + OKFormat___("", format: "+## (###) ###-##-##") + OKInterpret("", format: "+## (###) ###-##-##", value: "") } func testSome() { - XCTFormat___("12300045", format: "+123 (000) 45-##-##") - XCTInterpret("12300045", format: "+123 (000) 45-##-##", value: "12300045") + OKFormat___("12000345", format: "+12 (000) 345-##-##") + OKInterpret("12000345", format: "+12 (000) 345-##-##", value: "12000345") } func testFull() { - XCTFormat___("123000456789", format: "+123 (000) 45-67-89") - XCTInterpret("123000456789", format: "+123 (000) 45-67-89", value: "123000456789") + OKFormat___("120003456789", format: "+12 (000) 345-67-89") + OKInterpret("120003456789", format: "+12 (000) 345-67-89", value: "120003456789") } func testMore() { - XCTFormat___("123000456789000", format: "+123 (000) 45-67-89|000") - XCTInterpret("123000456789000", format: "+123 (000) 45-67-89", value: "123000456789") + OKFormat___("120003456789000", format: "+12 (000) 345-67-89|000") + OKInterpret("120003456789000", format: "+12 (000) 345-67-89", value: "120003456789") } - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= - func testNoneMismatch() { - XCTFormat___("ABC", format: "+### (###) ##-##-##|ABC") - XCTInterpret("ABC", format: "+### (###) ##-##-##", value: "") + OKFormat___("ABC", format: "+## (###) ###-##-##|ABC") + OKInterpret("ABC", format: "+## (###) ###-##-##", value: "") } func testSomeMismatch() { - XCTFormat___("12300045ABC", format: "+123 (000) 45-##-##|ABC") - XCTInterpret("12300045ABC", format: "+123 (000) 45-##-##", value: "12300045") + OKFormat___("12000345ABC", format: "+12 (000) 345-##-##|ABC") + OKInterpret("12000345ABC", format: "+12 (000) 345-##-##", value: "12000345") } } diff --git a/Tests/DiffableTextKitXPatternTests/Style.swift b/Tests/DiffableTextKitXPatternTests/Style.swift index 5123c830..03b0a501 100644 --- a/Tests/DiffableTextKitXPatternTests/Style.swift +++ b/Tests/DiffableTextKitXPatternTests/Style.swift @@ -33,10 +33,6 @@ protocol StyleTests: XCTestCase { func testSome() func testFull() func testMore() - - //=------------------------------------------------------------------------= - // MARK: Tests - //=------------------------------------------------------------------------= func testNoneMismatch() func testSomeMismatch() @@ -52,11 +48,11 @@ extension StyleTests { // MARK: Assertions //=------------------------------------------------------------------------= - func XCTFormat___(_ input: String, format: String) { + func OKFormat___(_ input: String, format: String) { XCTAssertEqual(style.format(input), format) } - func XCTInterpret(_ input: String, format: String, value: String) { + func OKInterpret(_ input: String, format: String, value: String) { let testable = style.interpret(input) XCTAssertEqual(testable.value, value) XCTAssertEqual(testable.snapshot.characters, format)