├── Assets ├── AppXNumber.png ├── AppXPattern.png ├── ViewXNumber.gif └── ViewXPattern.gif ├── .gitignore ├── Apps └── DiffableTextAppXUIKit │ ├── App │ ├── Assets │ │ ├── Assets.xcassets │ │ │ ├── Contents.json │ │ │ ├── AccentColor.colorset │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ └── Preview Content │ │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── App.swift │ ├── Helpers │ │ ├── Random.swift │ │ ├── Range.swift │ │ ├── Twins.swift │ │ └── Bounds.swift │ ├── Models │ │ └── Constants.swift │ ├── Views │ │ ├── Scroller.swift │ │ ├── Action.swift │ │ ├── Screen.swift │ │ └── Interval.swift │ ├── Utilities │ │ ├── Observer.swift │ │ └── Observable.swift │ └── Screens │ │ ├── Number │ │ └── NumberScreenContext.swift │ │ └── Pattern │ │ ├── PatternScreenExample.swift │ │ └── PatternScreenContext.swift │ ├── Modules │ └── IntervalSliderViews │ │ ├── .gitignore │ │ ├── Package.swift │ │ └── Sources │ │ └── IntervalSliderViews │ │ └── Models │ │ ├── Values.swift │ │ ├── Layout.swift │ │ └── Context.swift │ ├── DiffableTextAppXUIKit.xcodeproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── Entitlements.entitlements ├── Sources ├── DiffableTextKitXNumber │ ├── Exports.swift │ ├── Models │ │ ├── Parser.swift │ │ ├── Count.swift │ │ ├── Attributes.swift │ │ ├── Preferences.swift │ │ ├── Clamp.swift │ │ └── Label.swift │ ├── Aliases.swift │ ├── Traits.swift │ ├── Tokens │ │ ├── Separator.swift │ │ ├── Digit.swift │ │ └── Sign.swift │ ├── Value.swift │ ├── Graphs │ │ └── Graph+Decimal.swift │ └── Graph.swift ├── DiffableTextKitXPattern │ └── Exports.swift ├── DiffableTextKitXUIKit │ ├── Exports.swift │ ├── Streams │ │ ├── Sidestream.swift │ │ └── Upstream.swift │ ├── Models │ │ ├── Intent.swift │ │ └── Alignment.swift │ ├── Environment+OnSubmit.swift │ ├── Environment+Tint.swift │ ├── Environment+SubmitLabel.swift │ ├── Environment+KeyboardType.swift │ ├── Environment+ForegroundColor.swift │ ├── Environment+MultilineTextAlignment.swift │ ├── Environment+AutocorrectionDisabled.swift │ ├── Environment+TextFieldStyle.swift │ ├── Environment+TextInputAutocapitalization.swift │ ├── Environment+TextContentType.swift │ ├── Environment+ToolbarDoneButton.swift │ └── Environment+Font.swift ├── DiffableTextKit │ ├── Utilities │ │ ├── Void.swift │ │ ├── Locale.swift │ │ ├── Count.swift │ │ ├── Slice.swift │ │ ├── Options.swift │ │ ├── Brrr.swift │ │ ├── Trigger.swift │ │ └── Lock.swift │ ├── Models │ │ ├── Focus.swift │ │ ├── Synchronize.swift │ │ ├── Changes.swift │ │ ├── Resolve.swift │ │ ├── Update.swift │ │ ├── Direction.swift │ │ ├── Index.swift │ │ └── Caret.swift │ └── Styles │ │ ├── Normal.swift │ │ └── Constant.swift └── DiffableTextViews │ └── Exports.swift └── Tests ├── DiffableTextKitTests ├── Aliases.swift ├── Constants.swift ├── Utilities │ ├── Slice.swift │ ├── Void.swift │ ├── Count.swift │ ├── Options.swift │ └── Info.swift ├── Models │ ├── Focus.swift │ ├── Proposal.swift │ ├── Resolve.swift │ ├── Update.swift │ ├── Changes.swift │ ├── Synchronize.swift │ ├── Index.swift │ ├── Attribute.swift │ ├── Direction.swift │ ├── Symbol.swift │ └── Commit.swift └── Styles │ ├── Constant.swift │ ├── Equals.swift │ ├── Normal.swift │ ├── Suffix.swift │ └── Prefix.swift ├── DiffableTextKitXNumberTests ├── Constants.swift ├── Models │ └── Links.swift ├── Comments+Percent.swift ├── Tokens │ ├── Sign.swift │ ├── Separator.swift │ └── Digit.swift ├── Graphs │ ├── Graph.swift │ ├── Graph+Floats.swift │ └── Graph+Integers.swift ├── Comments+Inaccurate.swift ├── Styles │ ├── Style.swift │ └── Style+Percent.swift ├── Comments+Currency.swift └── Comments.swift ├── DiffableTextKitXUIKitTests ├── Field.swift └── Font.swift └── DiffableTextKitXPatternTests ├── Style.swift ├── Style+Hidden.swift └── Style+Visible.swift /Assets/AppXNumber.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oscbyspro/DiffableTextViews/HEAD/Assets/AppXNumber.png -------------------------------------------------------------------------------- /Assets/AppXPattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oscbyspro/DiffableTextViews/HEAD/Assets/AppXPattern.png -------------------------------------------------------------------------------- /Assets/ViewXNumber.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oscbyspro/DiffableTextViews/HEAD/Assets/ViewXNumber.gif -------------------------------------------------------------------------------- /Assets/ViewXPattern.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oscbyspro/DiffableTextViews/HEAD/Assets/ViewXPattern.gif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/xcode/ -------------------------------------------------------------------------------- /Apps/DiffableTextAppXUIKit/App/Assets/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Apps/DiffableTextAppXUIKit/App/Assets/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Apps/DiffableTextAppXUIKit/Modules/IntervalSliderViews/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | DerivedData/ 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | -------------------------------------------------------------------------------- /Apps/DiffableTextAppXUIKit/DiffableTextAppXUIKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Apps/DiffableTextAppXUIKit/DiffableTextAppXUIKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Apps/DiffableTextAppXUIKit/Entitlements.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.network.client 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Apps/DiffableTextAppXUIKit/App/Assets/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "display-p3", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.708", 9 | "green" : "0.389", 10 | "red" : "0.206" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sources/DiffableTextKitXNumber/Exports.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Exports 12 | //*============================================================================* 13 | 14 | @_exported import protocol DiffableTextKit.DiffableTextStyle 15 | -------------------------------------------------------------------------------- /Sources/DiffableTextKitXPattern/Exports.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Exports 12 | //*============================================================================* 13 | 14 | @_exported import protocol DiffableTextKit.DiffableTextStyle 15 | -------------------------------------------------------------------------------- /Sources/DiffableTextKitXUIKit/Exports.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Exports 12 | //*============================================================================* 13 | 14 | @_exported import protocol DiffableTextKit.DiffableTextStyle 15 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Aliases.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | import DiffableTextKit 11 | 12 | //*============================================================================* 13 | // MARK: * Aliases 14 | //*============================================================================* 15 | 16 | typealias C = Offset 17 | -------------------------------------------------------------------------------- /Sources/DiffableTextKit/Utilities/Void.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Void [...] 12 | //*============================================================================* 13 | 14 | public struct _Void: Hashable { @inlinable @inline(__always) public init() { } } 15 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Constants.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | import Foundation 11 | 12 | //*============================================================================* 13 | // MARK: * Constants 14 | //*============================================================================* 15 | 16 | let en_US = Locale(identifier: "en_US") 17 | let sv_SE = Locale(identifier: "sv_SE") 18 | -------------------------------------------------------------------------------- /Sources/DiffableTextKit/Utilities/Locale.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | import struct Foundation.Locale 11 | 12 | //*============================================================================* 13 | // MARK: * Locale [...] 14 | //*============================================================================* 15 | 16 | public extension Locale { static let en_US_POSIX = Locale(identifier: "en_US_POSIX") } 17 | -------------------------------------------------------------------------------- /Apps/DiffableTextAppXUIKit/App/App.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | import SwiftUI 11 | 12 | //*============================================================================* 13 | // MARK: * App 14 | //*============================================================================* 15 | 16 | @main struct App: SwiftUI.App { 17 | 18 | //=------------------------------------------------------------------------= 19 | // MARK: Body 20 | //=------------------------------------------------------------------------= 21 | 22 | var body: some Scene { 23 | WindowGroup { 24 | Tabs().preferredColorScheme(.dark) 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Sources/DiffableTextKit/Models/Focus.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Focus [...] 12 | //*============================================================================* 13 | 14 | @frozen public struct Focus: Equatable, ExpressibleByBooleanLiteral { 15 | 16 | //=------------------------------------------------------------------------= 17 | 18 | public let value: Bool 19 | 20 | //=------------------------------------------------------------------------= 21 | 22 | @inlinable public init(_ value: Bool) { self.value = value } 23 | 24 | @inlinable public init(booleanLiteral value: Bool) { self.value = value } 25 | } 26 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Utilities/Slice.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKit 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Slice x Tests 18 | //*============================================================================* 19 | 20 | final class SliceTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: Tests x Suffix 24 | //=------------------------------------------------------------------------= 25 | 26 | func testSuffixWhile() { 27 | XCTAssert("0123456789".suffix(while: { "4" < $0 }).elementsEqual("56789")) 28 | } 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitXNumberTests/Constants.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | import DiffableTextKitXNumber 11 | 12 | import Foundation 13 | 14 | //*============================================================================* 15 | // MARK: * Constants 16 | //*============================================================================* 17 | 18 | let USD: String = "USD" 19 | 20 | let en_US: Locale = Locale(identifier: "en_US") 21 | 22 | let currencyCodes: [String] = Locale 23 | .isoCurrencyCodes 24 | 25 | let locales: [Locale] = Locale 26 | .availableIdentifiers.lazy.map(Locale.init) 27 | .sorted(by: { $0.identifier < $1.identifier }) 28 | 29 | let numbers: [NumberTextStyle.Cache] = locales.lazy 30 | .map(NumberTextStyle.init).map({ $0.cache() }) 31 | -------------------------------------------------------------------------------- /Apps/DiffableTextAppXUIKit/App/Helpers/Random.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Random 12 | //*============================================================================* 13 | 14 | extension Character { 15 | 16 | //=------------------------------------------------------------------------= 17 | // MARK: Utilitis 18 | //=------------------------------------------------------------------------= 19 | 20 | static func random(in bounds: ClosedRange) -> Character? { 21 | let bounds = ClosedRange(uncheckedBounds: 22 | (bounds.lowerBound.value, bounds.upperBound.value)) 23 | return UnicodeScalar(UInt32.random(in: bounds)).map(Character.init) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Apps/DiffableTextAppXUIKit/App/Helpers/Range.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Range 12 | //*============================================================================* 13 | 14 | extension ClosedRange where Bound: Comparable { 15 | 16 | //=------------------------------------------------------------------------= 17 | // MARK: Initializers 18 | //=------------------------------------------------------------------------= 19 | 20 | init(_ unordered: (Bound, Bound)) { 21 | switch unordered.0 <= unordered.1 { 22 | case true: self.init(uncheckedBounds: (unordered.0, unordered.1)) 23 | case false: self.init(uncheckedBounds: (unordered.1, unordered.0)) 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Sources/DiffableTextKit/Models/Synchronize.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Synchronize [...] 12 | //*============================================================================* 13 | 14 | /// A message describing synchronization behavior. 15 | @frozen public struct Synchronize: OptionSet { 16 | 17 | /// Requires that input and output values are equal. 18 | public static let acyclical = Self(rawValue: 1 << 0) 19 | 20 | //=------------------------------------------------------------------------= 21 | 22 | public let rawValue: UInt8 23 | 24 | //=------------------------------------------------------------------------= 25 | 26 | @inlinable public init(rawValue: UInt8) { self.rawValue = rawValue } 27 | } 28 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitXNumberTests/Models/Links.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKitXNumber 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Links x Tests 18 | //*============================================================================* 19 | 20 | final class LinksTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: Tests 24 | //=------------------------------------------------------------------------= 25 | 26 | func testIsBidirectional() { 27 | let links = Links.ascii() 28 | for token in Digit.allCases { 29 | XCTAssertEqual(token, links[links[token]]) 30 | } 31 | } 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /Sources/DiffableTextKitXUIKit/Streams/Sidestream.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if canImport(UIKit) 11 | 12 | import DiffableTextKit 13 | import SwiftUI 14 | 15 | //*============================================================================* 16 | // MARK: * Sidestream [...] 17 | //*============================================================================* 18 | 19 | @usableFromInline struct Sidestream { 20 | 21 | //=------------------------------------------------------------------------= 22 | 23 | @usableFromInline var onSubmit: Trigger? 24 | 25 | //=------------------------------------------------------------------------= 26 | 27 | @inlinable init() { } 28 | 29 | @inlinable init(_ environment: EnvironmentValues) { 30 | self.onSubmit = environment.diffableTextViews_onSubmit 31 | } 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /Sources/DiffableTextKit/Models/Changes.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Changes [...] 12 | //*============================================================================* 13 | 14 | /// A model used to capture comparison results. 15 | @frozen @usableFromInline struct Changes: OptionSet { 16 | 17 | public static let style = Self(rawValue: 1 << 0) 18 | public static let value = Self(rawValue: 1 << 1) 19 | public static let focus = Self(rawValue: 1 << 2) 20 | 21 | //=------------------------------------------------------------------------= 22 | 23 | public var rawValue: UInt8 24 | 25 | //=------------------------------------------------------------------------= 26 | 27 | @inlinable init(rawValue: UInt8) { self.rawValue = rawValue } 28 | } 29 | -------------------------------------------------------------------------------- /Apps/DiffableTextAppXUIKit/App/Models/Constants.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | import Foundation 11 | 12 | //*============================================================================* 13 | // MARK: * Constants 14 | //*============================================================================* 15 | 16 | enum Constants { 17 | 18 | //=------------------------------------------------------------------------= 19 | // MARK: State 20 | //=------------------------------------------------------------------------= 21 | 22 | static let currencies: [String] = Locale.Currency 23 | .isoCurrencies 24 | .map(\.identifier) 25 | 26 | static let locales: [Locale] = Locale 27 | .availableIdentifiers 28 | .lazy.map(Locale.init) 29 | .reduce(into: Set()) { $0.insert($1) } 30 | .sorted(by: { $0.identifier < $1.identifier }) 31 | } 32 | -------------------------------------------------------------------------------- /Sources/DiffableTextKit/Models/Resolve.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*========================================================================* 11 | // MARK: * Resolve [...] 12 | //*========================================================================* 13 | 14 | /// A message describing selection behavior. 15 | @frozen public struct Resolve: OptionSet { 16 | 17 | /// Resolve max selection. 18 | public static let max = Self(rawValue: 1 << 0) 19 | 20 | /// Resolve selection by using caret momentums. 21 | public static let momentums = Self(rawValue: 1 << 1) 22 | 23 | //=--------------------------------------------------------------------= 24 | 25 | public var rawValue: UInt8 26 | 27 | //=--------------------------------------------------------------------= 28 | 29 | @inlinable public init(rawValue: UInt8) { self.rawValue = rawValue } 30 | } 31 | -------------------------------------------------------------------------------- /Sources/DiffableTextKitXNumber/Models/Parser.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Parser [...] 12 | //*============================================================================* 13 | 14 | @usableFromInline struct Parser { 15 | 16 | //=------------------------------------------------------------------------= 17 | 18 | @usableFromInline let base: Format.Strategy 19 | 20 | //=------------------------------------------------------------------------= 21 | 22 | @inlinable init(initial: Format) { 23 | self.base = initial.locale(.en_US_POSIX).parseStrategy 24 | } 25 | 26 | @inlinable func parse(_ number: Number) throws -> Format.FormatInput { 27 | try base.parse(String.init(bytes: number.ascii, encoding: .ascii)!) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Sources/DiffableTextKit/Utilities/Count.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Count 12 | //*============================================================================* 13 | 14 | public extension Sequence { 15 | 16 | //=------------------------------------------------------------------------= 17 | // MARK: Predicate 18 | //=------------------------------------------------------------------------= 19 | 20 | @inlinable func count(where predicate: (Element) throws -> Bool) rethrows -> Int { 21 | var S0 = 0; for S1 in self { if try predicate(S1) { S0 += 1 } }; return S0 22 | } 23 | 24 | @inlinable func count(while predicate: (Element) throws -> Bool) rethrows -> Int { 25 | var S0 = 0; for S1 in self { if try predicate(S1) { S0 += 1 } else { break } }; return S0 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Utilities/Void.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKit 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Void x Tests 18 | //*============================================================================* 19 | 20 | final class _VoidTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: Tests 24 | //=------------------------------------------------------------------------= 25 | 26 | func testIsSimilarToVoid() { 27 | XCTAssertEqual(MemoryLayout<_Void>.size, MemoryLayout.size) 28 | XCTAssertEqual(MemoryLayout<_Void>.stride, MemoryLayout.stride) 29 | XCTAssertEqual(MemoryLayout<_Void>.alignment, MemoryLayout.alignment) 30 | } 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Models/Focus.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKit 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Focus x Tests 18 | //*============================================================================* 19 | 20 | final class FocusTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: Tests x Initializers 24 | //=------------------------------------------------------------------------= 25 | 26 | func testInit() { 27 | XCTAssertEqual(Focus( true).value, true) 28 | XCTAssertEqual(Focus(false).value, false) 29 | } 30 | 31 | func testInitAsBooleanLiteral() { 32 | XCTAssertEqual(Focus( true), true) 33 | XCTAssertEqual(Focus(false), false) 34 | } 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /Apps/DiffableTextAppXUIKit/App/Views/Scroller.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | import SwiftUI 11 | 12 | //*============================================================================* 13 | // MARK: * Scroller 14 | //*============================================================================* 15 | 16 | struct Scroller: View { 17 | 18 | //=------------------------------------------------------------------------= 19 | // MARK: State 20 | //=------------------------------------------------------------------------= 21 | 22 | @ViewBuilder let content: () -> Content 23 | 24 | //=------------------------------------------------------------------------= 25 | // MARK: Body 26 | //=------------------------------------------------------------------------= 27 | 28 | var body: some View { 29 | ScrollView(showsIndicators: false) { 30 | content().padding() 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Models/Proposal.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKit 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Proposal x Tests 18 | //*============================================================================* 19 | 20 | final class ProposalTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: Tests 24 | //=------------------------------------------------------------------------= 25 | 26 | func testMerged() { 27 | let proposal = Proposal("AxE", with: "BCD", in: C(1) ..< 2) 28 | XCTAssertEqual(proposal.merged(), "ABCDE") 29 | } 30 | 31 | func testLazyMerged() { 32 | let proposal = Proposal("AxE", with: "BCD", in: C(1) ..< 2) 33 | XCTAssertEqual(Snapshot(proposal.lazy.merged()), "ABCDE") 34 | } 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /Apps/DiffableTextAppXUIKit/Modules/IntervalSliderViews/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.5 2 | //=----------------------------------------------------------------------------= 3 | // This source file is part of the DiffableTextViews open source project. 4 | // 5 | // Copyright (c) 2022 Oscar Byström Ericsson 6 | // Licensed under Apache License, Version 2.0 7 | // 8 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 9 | //=----------------------------------------------------------------------------= 10 | 11 | import PackageDescription 12 | 13 | //*============================================================================* 14 | // MARK: IntervalSliderViews 15 | //*============================================================================* 16 | 17 | let package = Package( 18 | name: "IntervalSliderViews", 19 | platforms: [ 20 | .iOS(.v15), 21 | ], 22 | products: [ 23 | //=--------------------------------------= 24 | // IntervalSliderViews 25 | //=--------------------------------------= 26 | .library( 27 | name: "IntervalSliderViews", 28 | targets: ["IntervalSliderViews"]) 29 | ], 30 | targets: [ 31 | //=--------------------------------------= 32 | // IntervalSliderViews 33 | //=--------------------------------------= 34 | .target(name: "IntervalSliderViews"), 35 | ] 36 | ) 37 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitXNumberTests/Comments+Percent.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKitXNumber 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Comments x Percent 18 | //*============================================================================* 19 | 20 | final class CommentsOnPercent: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: Tests 24 | //=------------------------------------------------------------------------= 25 | 26 | func testPercentLabelsAreAlwaysVirtual() { 27 | for cache in numbers { 28 | let components = cache.interpreter.components 29 | let percent = IntegerFormatStyle.Percent(locale:cache.style.locale) 30 | XCTAssertEqual(1, percent.format(0).filter(components.nonvirtual).count) 31 | } 32 | } 33 | } 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Models/Resolve.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKit 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Resolve x Tests 18 | //*============================================================================* 19 | 20 | final class ResolveTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: State 24 | //=------------------------------------------------------------------------= 25 | 26 | let all: [Resolve] = [.max, .momentums] 27 | 28 | //=------------------------------------------------------------------------= 29 | // MARK: Tests x Instances 30 | //=------------------------------------------------------------------------= 31 | 32 | func testInstancesAreUnique() { 33 | XCTAssertEqual(Set(all.map(\.rawValue)).count, all.count) 34 | } 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Models/Update.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKit 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Update x Tests 18 | //*============================================================================* 19 | 20 | final class UpdateTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: State 24 | //=------------------------------------------------------------------------= 25 | 26 | let all: [Update] = [.value, .text, .selection] 27 | 28 | //=------------------------------------------------------------------------= 29 | // MARK: Tests x Instances 30 | //=------------------------------------------------------------------------= 31 | 32 | func testInstancesAreUnique() { 33 | XCTAssertEqual(Set(all.map(\.rawValue)).count, all.count) 34 | } 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /Apps/DiffableTextAppXUIKit/Modules/IntervalSliderViews/Sources/IntervalSliderViews/Models/Values.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | import SwiftUI 11 | 12 | //*============================================================================* 13 | // MARK: Declaration 14 | //*============================================================================* 15 | 16 | struct Values { 17 | 18 | //=------------------------------------------------------------------------= 19 | // MARK: State 20 | //=------------------------------------------------------------------------= 21 | 22 | let limits: ClosedRange 23 | @Binding var remote: (CGFloat, CGFloat) 24 | 25 | //=------------------------------------------------------------------------= 26 | // MARK: Initializers 27 | //=------------------------------------------------------------------------= 28 | 29 | init(_ remote: Binding<(CGFloat, CGFloat)>, in limits: ClosedRange) { 30 | self.limits = limits; self._remote = remote 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Models/Changes.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKit 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Changes x Tests 18 | //*============================================================================* 19 | 20 | final class ChangesTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: State 24 | //=------------------------------------------------------------------------= 25 | 26 | let all: [Changes] = [.style, .value, .focus] 27 | 28 | //=------------------------------------------------------------------------= 29 | // MARK: Tests x Instances 30 | //=------------------------------------------------------------------------= 31 | 32 | func testInstancesAreUnique() { 33 | XCTAssertEqual(Set(all.map(\.rawValue)).count, all.count) 34 | } 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Models/Synchronize.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKit 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Synchronize x Tests 18 | //*============================================================================* 19 | 20 | final class SynchronizeTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: State 24 | //=------------------------------------------------------------------------= 25 | 26 | let all: [Synchronize] = [.acyclical] 27 | 28 | //=------------------------------------------------------------------------= 29 | // MARK: Tests x Instances 30 | //=------------------------------------------------------------------------= 31 | 32 | func testInstancesAreUnique() { 33 | XCTAssertEqual(Set(all.map(\.rawValue)).count, all.count) 34 | } 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /Sources/DiffableTextKit/Models/Update.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Update [...] 12 | //*============================================================================* 13 | 14 | /// A message describing which properties should be updated. 15 | /// 16 | /// It is recommended to update the value first, then the text before selection. 17 | /// 18 | /// - Implement reentrant updates by only updating the value until it stabilizes. 19 | /// 20 | @frozen public struct Update: OptionSet { 21 | 22 | public static let value = Self(rawValue: 1 << 0) 23 | public static let text = Self(rawValue: 1 << 1) 24 | public static let selection = Self(rawValue: 1 << 2) 25 | 26 | //=------------------------------------------------------------------------= 27 | 28 | public let rawValue: UInt8 29 | 30 | //=------------------------------------------------------------------------= 31 | 32 | @inlinable public init(rawValue: UInt8) { self.rawValue = rawValue } 33 | } 34 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Styles/Constant.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKit 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Constant x Tests 18 | //*============================================================================* 19 | 20 | final class ConstantTextStyleTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: Tests 24 | //=------------------------------------------------------------------------= 25 | 26 | func test() { 27 | //=--------------------------------------= 28 | // Setup 29 | //=--------------------------------------= 30 | let mock0 = Mock(locale: en_US).constant() 31 | let mock1 = mock0.locale(sv_SE) 32 | //=--------------------------------------= 33 | // Assert 34 | //=--------------------------------------= 35 | XCTAssertEqual(mock0, mock1) 36 | } 37 | } 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /Sources/DiffableTextKit/Utilities/Slice.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Slice 12 | //*============================================================================* 13 | 14 | extension BidirectionalCollection { 15 | 16 | //=------------------------------------------------------------------------= 17 | // MARK: Suffix 18 | //=------------------------------------------------------------------------= 19 | 20 | @inlinable public func suffix(while predicate: (Element) throws -> Bool) rethrows -> SubSequence { 21 | try self[startOfSuffix(while: predicate)...] 22 | } 23 | 24 | @inlinable func startOfSuffix(while predicate: (Element) throws -> Bool) rethrows -> Index { 25 | var position = endIndex 26 | 27 | backwards: while position != startIndex { 28 | let after = position; formIndex(before: &position) 29 | if try !predicate(self[position]) { return after } 30 | } 31 | 32 | return position 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitXNumberTests/Tokens/Sign.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKitXNumber 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Sign x Tests 18 | //*============================================================================* 19 | 20 | final class SignTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: Assertions 24 | //=------------------------------------------------------------------------= 25 | 26 | func XCTAssertASCII(_ sign: Sign, _ character: Character) { 27 | XCTAssertEqual(sign.character, character) 28 | } 29 | 30 | //=------------------------------------------------------------------------= 31 | // MARK: Tests 32 | //=------------------------------------------------------------------------= 33 | 34 | func testASCII() { 35 | XCTAssertASCII(.positive, "+") 36 | XCTAssertASCII(.negative, "-") 37 | } 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitXNumberTests/Tokens/Separator.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKitXNumber 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Separator x Tests 18 | //*============================================================================* 19 | 20 | final class SeparatorTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: Assertions 24 | //=------------------------------------------------------------------------= 25 | 26 | func XCTAssertASCII(_ separator: Separator, _ character: Character) { 27 | XCTAssertEqual(separator.character, character) 28 | } 29 | 30 | //=------------------------------------------------------------------------= 31 | // MARK: Tests 32 | //=------------------------------------------------------------------------= 33 | 34 | func testASCII() { 35 | XCTAssertASCII(.fraction, ".") 36 | XCTAssertASCII(.grouping, ",") 37 | } 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Models/Index.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKit 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Index x Tests 18 | //*============================================================================* 19 | 20 | final class IndexTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: State 24 | //=------------------------------------------------------------------------= 25 | 26 | let characters = "ABC" 27 | 28 | //=------------------------------------------------------------------------= 29 | // MARK: Tests x Utilities 30 | //=------------------------------------------------------------------------= 31 | 32 | func testComparableUsesOnlyAttribute() { 33 | XCTAssertEqual( 34 | Index(characters .endIndex, as: 0), 35 | Index(characters.startIndex, as: 0)) 36 | 37 | XCTAssertLessThan( 38 | Index(characters .endIndex, as: 0), 39 | Index(characters.startIndex, as: 1)) 40 | } 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Styles/Equals.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKit 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Equals x Tests 18 | //*============================================================================* 19 | 20 | final class EqualsTextStyleTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: Tests 24 | //=------------------------------------------------------------------------= 25 | 26 | func test() { 27 | //=--------------------------------------= 28 | // Setup 29 | //=--------------------------------------= 30 | let mock0 = Mock(locale: en_US).equals(0) 31 | let mock1 = Mock(locale: sv_SE).equals(0) 32 | let mock2 = Mock(locale: en_US).equals(1) 33 | //=--------------------------------------= 34 | // Assert 35 | //=--------------------------------------= 36 | XCTAssertEqual( mock0, mock1) 37 | XCTAssertNotEqual(mock0, mock2) 38 | XCTAssertNotEqual(mock1, mock2) 39 | } 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /Sources/DiffableTextKitXUIKit/Models/Intent.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if canImport(UIKit) 11 | 12 | import UIKit 13 | 14 | //*============================================================================* 15 | // MARK: * Intent [...] 16 | //*============================================================================* 17 | 18 | @usableFromInline struct Intent { 19 | 20 | @usableFromInline typealias Key = UIKeyboardHIDUsage 21 | 22 | //=------------------------------------------------------------------------= 23 | 24 | @usableFromInline private(set) var latest: Key? 25 | 26 | //=------------------------------------------------------------------------= 27 | 28 | @inlinable mutating func insert(_ presses: Set) { 29 | parse(presses).map({ latest = $0 }) 30 | } 31 | 32 | @inlinable mutating func remove(_ presses: Set) { 33 | parse(presses).map({ latest == $0 ? latest = nil : () }) 34 | } 35 | 36 | @inlinable func parse(_ presses: Set) -> Key? { 37 | if let key = presses.first?.key?.keyCode, 38 | key == .keyboardLeftArrow || 39 | key == .keyboardRightArrow { return key }; return nil 40 | } 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /Sources/DiffableTextKitXNumber/Aliases.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | import Foundation 11 | 12 | //*============================================================================* 13 | // MARK: * Aliases 14 | //*============================================================================* 15 | 16 | public typealias NumberTextStyle = 17 | Value.NumberTextGraph.Number where 18 | Value.NumberTextGraph: _Numberable 19 | 20 | public typealias NumberTextBounds = _Bounds 21 | public typealias NumberTextPrecision = _Precision 22 | 23 | //*============================================================================* 24 | // MARK: * Aliases x Internal 25 | //*============================================================================* 26 | 27 | public typealias _FPRR = FloatingPointRoundingRule 28 | 29 | public typealias _NFSC = NumberFormatStyleConfiguration 30 | public typealias _CFSC = CurrencyFormatStyleConfiguration 31 | 32 | public typealias _NFSC_SignDS = _NFSC.SignDisplayStrategy 33 | public typealias _CFSC_SignDS = _CFSC.SignDisplayStrategy 34 | 35 | public typealias _NFSC_SeparatorDS = _NFSC.DecimalSeparatorDisplayStrategy 36 | public typealias _CFSC_SeparatorDS = _CFSC.DecimalSeparatorDisplayStrategy 37 | -------------------------------------------------------------------------------- /Sources/DiffableTextKitXUIKit/Models/Alignment.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if canImport(UIKit) 11 | 12 | import SwiftUI 13 | import UIKit 14 | 15 | //*============================================================================* 16 | // MARK: * Alignment x UIKit 17 | //*============================================================================* 18 | 19 | extension NSTextAlignment { 20 | 21 | //=------------------------------------------------------------------------= 22 | // MARK: Initializers 23 | //=------------------------------------------------------------------------= 24 | 25 | @inlinable init(_ alignment: TextAlignment, relativeTo layout: LayoutDirection) { 26 | switch alignment { 27 | case .leading: self.init(layout, leftToRight: .left, rightToLeft: .right) 28 | case .trailing: self.init(layout, leftToRight: .right, rightToLeft: .left) 29 | case .center: self = .center } 30 | } 31 | 32 | @inlinable init(_ layout: LayoutDirection, leftToRight: Self, rightToLeft: Self) { 33 | switch layout { 34 | case .rightToLeft: self = rightToLeft 35 | case .leftToRight: self = leftToRight 36 | @unknown default: self = leftToRight } 37 | } 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Utilities/Count.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKit 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Count x Tests 18 | //*============================================================================* 19 | 20 | final class CountTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: Tests x Where 24 | //=------------------------------------------------------------------------= 25 | 26 | func testCountWhere() { 27 | let numbers = "22122" 28 | XCTAssertEqual(numbers.count(where: { $0 == "1" }), 1) 29 | XCTAssertEqual(numbers.count(where: { $0 == "2" }), 4) 30 | } 31 | 32 | //=------------------------------------------------------------------------= 33 | // MARK: Tests x While 34 | //=------------------------------------------------------------------------= 35 | 36 | func testCountWhile() { 37 | let numbers = "22122" 38 | XCTAssertEqual(numbers.count(while: { $0 == "1" }), 0) 39 | XCTAssertEqual(numbers.count(while: { $0 == "2" }), 2) 40 | } 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitXNumberTests/Graphs/Graph.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKitXNumber 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Graph x Tests 18 | //*============================================================================* 19 | 20 | final class GraphTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: Tests 24 | //=------------------------------------------------------------------------= 25 | 26 | func testBounds_Decimal_Double_Int64() { 27 | XCTAssertEqual(Decimal._NumberTextGraph.max, Decimal(string: String(repeating: "9", count: 38))!) 28 | XCTAssertEqual(Double ._NumberTextGraph.max, Double .init(String(repeating: "9", count: 15))!) 29 | XCTAssertEqual(Int64 ._NumberTextGraph.max, Int64 .init(String(repeating: "9", count: 18))!) 30 | } 31 | 32 | func testPrecision_Decimal_Double_Int64() { 33 | XCTAssertEqual(Decimal._NumberTextGraph.precision, 38) 34 | XCTAssertEqual(Double ._NumberTextGraph.precision, 15) 35 | XCTAssertEqual(Int64 ._NumberTextGraph.precision, 18) 36 | } 37 | } 38 | 39 | #endif 40 | 41 | -------------------------------------------------------------------------------- /Sources/DiffableTextKit/Utilities/Options.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Options 12 | //*============================================================================* 13 | 14 | public extension OptionSet { 15 | 16 | //=------------------------------------------------------------------------= 17 | // MARK: Transformations 18 | //=------------------------------------------------------------------------= 19 | 20 | @inlinable @inline(__always) func callAsFunction(_ mask: Bool) -> Self { 21 | mask ? self : Self() 22 | } 23 | 24 | @inlinable @inline(__always) static prefix func !(options: Self) -> Bool { 25 | options.isEmpty 26 | } 27 | 28 | @inlinable @inline(__always) static func + (lhs: Self, rhs: Self) -> Self { 29 | lhs.union(rhs) 30 | } 31 | 32 | @inlinable @inline(__always) static func += (lhs: inout Self, rhs: Self) { 33 | lhs.formUnion(rhs) 34 | } 35 | 36 | @inlinable @inline(__always) static func - (lhs: Self, rhs: Self) -> Self { 37 | lhs.subtracting(rhs) 38 | } 39 | 40 | @inlinable @inline(__always) static func -= (lhs: inout Self, rhs: Self) { 41 | lhs.subtract(rhs) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Sources/DiffableTextKitXNumber/Models/Count.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Count [...] 12 | //*============================================================================* 13 | 14 | /// A count of a number's components. 15 | /// 16 | /// - It SHOULD NOT include leading integer zeros. 17 | /// 18 | @usableFromInline struct Count: CustomStringConvertible, Equatable { 19 | 20 | //=------------------------------------------------------------------------= 21 | 22 | @usableFromInline let digits: Int 23 | @usableFromInline let integer: Int 24 | @usableFromInline let fraction: Int 25 | 26 | //=------------------------------------------------------------------------= 27 | 28 | @inlinable init(digits: Int, integer: Int, fraction: Int) { 29 | self.digits = digits; self.integer = integer; self.fraction = fraction 30 | } 31 | 32 | @inlinable init( _ number: Number) { 33 | self.integer = number.integer .count - number.integer.count(prefix:{$0 == .zero}) 34 | self.fraction = number.fraction.count; self.digits = self.integer + self.fraction 35 | } 36 | 37 | public var description: String { 38 | "\((digits, integer, fraction))" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitXUIKitTests/Field.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG && canImport(UIKit) 11 | 12 | @testable import DiffableTextKitXUIKit 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Field x Tests 18 | //*============================================================================* 19 | 20 | final class FieldTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: State 24 | //=------------------------------------------------------------------------= 25 | 26 | lazy var field = Field() 27 | 28 | //=------------------------------------------------------------------------= 29 | // MARK: Tests 30 | //=------------------------------------------------------------------------= 31 | 32 | func testForceUnwrappingTextIsOK() { 33 | field.text = nil 34 | XCTAssertNotNil(field.text) 35 | } 36 | 37 | func testForceUnwrappingSelectedTextRangeIsOK() { 38 | field.selectedTextRange = nil 39 | XCTAssertNotNil(field.selectedTextRange) 40 | } 41 | 42 | func testForceUnwrappingMarkedTextRangeIsBad() { 43 | XCTAssertNil(field.markedTextRange) 44 | } 45 | } 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Models/Attribute.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKit 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Attribute x Tests 18 | //*============================================================================* 19 | 20 | final class AttributeTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: State 24 | //=------------------------------------------------------------------------= 25 | 26 | let all: [Attribute] = [.virtual, .insertable, .removable, .passthrough] 27 | 28 | //=------------------------------------------------------------------------= 29 | // MARK: Tests x Instances 30 | //=------------------------------------------------------------------------= 31 | 32 | func testContentIsEmpty() { 33 | XCTAssert(Attribute.content.isEmpty) 34 | XCTAssertEqual(Attribute.content,[]) 35 | } 36 | 37 | func testPhantomIsFull() { 38 | XCTAssertEqual(Attribute.phantom, Attribute(all)) 39 | } 40 | 41 | func testInstancesAreUnique() { 42 | XCTAssertEqual(Set(all.map(\.rawValue)).count, all.count) 43 | } 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitXNumberTests/Comments+Inaccurate.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | import XCTest 13 | 14 | //*============================================================================* 15 | // MARK: * Comments x Tests x Inaccurate 16 | //*============================================================================* 17 | 18 | final class CommentsOnInaccurate: XCTestCase { 19 | 20 | //=------------------------------------------------------------------------= 21 | // MARK: Assertions 22 | //=------------------------------------------------------------------------= 23 | 24 | func XCTAssert(_ value: T, result: String) { 25 | let style = FloatingPointFormatStyle(locale: en_US) 26 | XCTAssertEqual(style.precision(.fractionLength(0...)).format(value), result) 27 | } 28 | 29 | //=------------------------------------------------------------------------= 30 | // MARK: Tests 31 | //=------------------------------------------------------------------------= 32 | 33 | func testFloat16IsInaccurate() { 34 | XCTAssert(-1.23 as Float16, result: "-1.23046875") 35 | } 36 | 37 | func testFloat32IsInaccurate() { 38 | XCTAssert(-1.23 as Float32, result: "-1.2300000190734863") 39 | } 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /Sources/DiffableTextKit/Utilities/Brrr.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Brrr [...] 12 | //*============================================================================* 13 | 14 | /// A model that prints messages in DEBUG mode. 15 | /// 16 | /// It uses conditional compilation such that it has no size or cost in RELEASE mode. 17 | /// 18 | public struct Brrr: Equatable { 19 | 20 | public static let cancellation = Self("cancellation") 21 | public static let autocorrection = Self("autocorrection") 22 | public static let unsynchronizable = Self("unsynchronizable") 23 | 24 | //=------------------------------------------------------------------------= 25 | 26 | #if DEBUG 27 | @usableFromInline let context: String 28 | #endif 29 | 30 | //=------------------------------------------------------------------------= 31 | 32 | @inlinable @inline(__always) public init(_ context: @autoclosure () -> String) { 33 | #if DEBUG 34 | self.context = context() 35 | #endif 36 | } 37 | 38 | @inlinable @inline(__always) public static func << (brrr: Self, message: @autoclosure () -> Any) { 39 | #if DEBUG 40 | Swift.print("[DiffableTextViews] \(brrr.context): \(message())") 41 | #endif 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitXNumberTests/Styles/Style.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | import DiffableTextKitXNumber 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Style 18 | //*============================================================================* 19 | 20 | class StyleTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: Overrides 24 | //=------------------------------------------------------------------------= 25 | 26 | override func setUp() { 27 | super.setUp(); self.continueAfterFailure = false 28 | } 29 | 30 | //=------------------------------------------------------------------------= 31 | // MARK: Assertions 32 | //=------------------------------------------------------------------------= 33 | 34 | func XCTAssert(_ value: S.Value, with style: S) { 35 | let style = style.precision(fraction: 0...) 36 | var cache = style.cache() 37 | 38 | let commit = style.interpret(value, with: &cache) 39 | XCTAssertEqual(commit.value, value, "\(style) x \(value)") 40 | 41 | let characters = style.format(value, with: &cache) 42 | XCTAssertEqual(commit.snapshot.characters, characters, "\(style) x \(value)") 43 | } 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitXNumberTests/Tokens/Digit.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKitXNumber 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Digit x Tests 18 | //*============================================================================* 19 | 20 | final class DigitTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: Assertions 24 | //=------------------------------------------------------------------------= 25 | 26 | func XCTAssertASCII(_ digit: Digit, _ value: UInt8) { 27 | XCTAssertEqual(digit.character, Character(String(value))) 28 | } 29 | 30 | //=------------------------------------------------------------------------= 31 | // MARK: Tests 32 | //=------------------------------------------------------------------------= 33 | 34 | func testASCII() { 35 | XCTAssertASCII(.zero, 0) 36 | XCTAssertASCII(.one, 1) 37 | XCTAssertASCII(.two, 2) 38 | XCTAssertASCII(.three, 3) 39 | XCTAssertASCII(.four, 4) 40 | XCTAssertASCII(.five, 5) 41 | XCTAssertASCII(.six, 6) 42 | XCTAssertASCII(.seven, 7) 43 | XCTAssertASCII(.eight, 8) 44 | XCTAssertASCII(.nine, 9) 45 | } 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /Apps/DiffableTextAppXUIKit/App/Views/Action.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | import SwiftUI 11 | 12 | //*============================================================================* 13 | // MARK: * Action 14 | //*============================================================================* 15 | 16 | struct Action: View { 17 | 18 | //=------------------------------------------------------------------------= 19 | // MARK: State 20 | //=------------------------------------------------------------------------= 21 | 22 | let title: String 23 | let action: () -> Void 24 | 25 | //=------------------------------------------------------------------------= 26 | // MARK: Initializers 27 | //=------------------------------------------------------------------------= 28 | 29 | init(_ title: String, action: @escaping () -> Void) { 30 | self.title = title 31 | self.action = action 32 | } 33 | 34 | //=------------------------------------------------------------------------= 35 | // MARK: Body 36 | //=------------------------------------------------------------------------= 37 | 38 | var body: some View { 39 | Button(action: action) { 40 | Text(title) 41 | .font(.subheadline) 42 | .frame(height: 16) 43 | .frame(maxWidth: .infinity) 44 | } 45 | .tint(Color.gray.opacity(2/3)) 46 | .buttonStyle(.borderedProminent) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Sources/DiffableTextKitXNumber/Models/Attributes.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | import DiffableTextKit 11 | 12 | //*============================================================================* 13 | // MARK: * Attributes 14 | //*============================================================================* 15 | 16 | @usableFromInline struct Attributes { 17 | 18 | //=------------------------------------------------------------------------= 19 | // MARK: State 20 | //=------------------------------------------------------------------------= 21 | 22 | @usableFromInline private(set) var map = [Character: Attribute]() 23 | 24 | //=------------------------------------------------------------------------= 25 | // MARK: Initializers 26 | //=------------------------------------------------------------------------= 27 | 28 | @inlinable init(_ components: Components) { 29 | self.map[components.separators[.fraction/*------*/]] = .removable 30 | components.digits.tokens.keys.forEach { self.map[$0] = .content } 31 | components.signs .tokens.keys.forEach { self.map[$0] = .phantom - .virtual } 32 | } 33 | 34 | //=------------------------------------------------------------------------= 35 | // MARK: Accessors 36 | //=------------------------------------------------------------------------= 37 | 38 | @inlinable subscript(character: Character) -> Attribute { 39 | map[character] ?? .phantom 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/DiffableTextKit/Models/Direction.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Direction 12 | //*============================================================================* 13 | 14 | /// A forwards/backwards model. 15 | @frozen public enum Direction { 16 | 17 | //=------------------------------------------------------------------------= 18 | // MARK: Instances 19 | //=------------------------------------------------------------------------= 20 | 21 | case forwards 22 | case backwards 23 | 24 | //=------------------------------------------------------------------------= 25 | // MARK: Initializers 26 | //=------------------------------------------------------------------------= 27 | 28 | @inlinable public init?(from start: T, to end: T) where T: Comparable { 29 | if start < end { self = .forwards } 30 | else if start > end { self = .backwards } 31 | else { return nil } 32 | } 33 | 34 | //=------------------------------------------------------------------------= 35 | // MARK: Transformations 36 | //=------------------------------------------------------------------------= 37 | 38 | @inlinable mutating public func reverse() { 39 | self = reversed() 40 | } 41 | 42 | @inlinable public func reversed() -> Self { 43 | self == .forwards ? .backwards : .forwards 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Tests/DiffableTextKitTests/Styles/Normal.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if DEBUG 11 | 12 | @testable import DiffableTextKit 13 | 14 | import XCTest 15 | 16 | //*============================================================================* 17 | // MARK: * Normal x Tests 18 | //*============================================================================* 19 | 20 | final class NormalTextStyleTests: XCTestCase { 21 | 22 | //=------------------------------------------------------------------------= 23 | // MARK: State 24 | //=------------------------------------------------------------------------= 25 | 26 | let normal = NormalTextStyle() 27 | 28 | //=------------------------------------------------------------------------= 29 | // MARK: Tests 30 | //=------------------------------------------------------------------------= 31 | 32 | func testFormat() { 33 | XCTAssertEqual(normal.format("2"), "2") 34 | } 35 | 36 | func testInterpret() { 37 | XCTAssertEqual(normal.interpret("3"), Commit("3", "3")) 38 | } 39 | 40 | func testResolve() { 41 | let snapshot = Snapshot("13") + Snapshot("o(><)o", as: .phantom) 42 | let proposal = Proposal(snapshot, with: "2", in: C(1) ..< C(1)) 43 | 44 | let resolved = try! normal.resolve(proposal) 45 | 46 | XCTAssertEqual(resolved.value, "123") 47 | XCTAssertEqual(resolved.snapshot, "123") 48 | } 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /Sources/DiffableTextKit/Models/Index.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | //*============================================================================* 11 | // MARK: * Index [...] 12 | //*============================================================================* 13 | 14 | /// A character encoded index and offset. 15 | public struct Index: Comparable, CustomStringConvertible { 16 | 17 | //=------------------------------------------------------------------------= 18 | 19 | @usableFromInline let character: String.Index 20 | @usableFromInline let attribute: Int 21 | 22 | //=------------------------------------------------------------------------= 23 | 24 | /// Creates an instance describing a character's position. 25 | /// 26 | /// - Parameters: 27 | /// - character: The character encoded index. 28 | /// - attribute: The character encoded offset. 29 | /// 30 | @inlinable @inline(__always) init(_ character: String.Index, as attribute: Int) { 31 | self.character = character 32 | self.attribute = attribute 33 | } 34 | 35 | public var description: String { 36 | String(describing: attribute) 37 | } 38 | 39 | @inlinable @inline(__always) public static func == (lhs: Self, rhs: Self) -> Bool { 40 | lhs.attribute == rhs.attribute 41 | } 42 | 43 | @inlinable @inline(__always) public static func < (lhs: Self, rhs: Self) -> Bool { 44 | lhs.attribute < rhs.attribute 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Sources/DiffableTextKitXUIKit/Streams/Upstream.swift: -------------------------------------------------------------------------------- 1 | //=----------------------------------------------------------------------------= 2 | // This source file is part of the DiffableTextViews open source project. 3 | // 4 | // Copyright (c) 2022 Oscar Byström Ericsson 5 | // Licensed under Apache License, Version 2.0 6 | // 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. 8 | //=----------------------------------------------------------------------------= 9 | 10 | #if canImport(UIKit) 11 | 12 | import DiffableTextKit 13 | import SwiftUI 14 | 15 | //*============================================================================* 16 | // MARK: * Upstream 17 | //*============================================================================* 18 | 19 | @usableFromInline struct Upstream { 20 | 21 | //=------------------------------------------------------------------------= 22 | // MARK: State 23 | //=------------------------------------------------------------------------= 24 | 25 | @usableFromInline let style: Style 26 | @usableFromInline let proxy: Binding 27 | 28 | //=------------------------------------------------------------------------= 29 | // MARK: Initializers 30 | //=------------------------------------------------------------------------= 31 | 32 | @inlinable init(_ view: DiffableTextField