1+ //
2+ // ConditionalStyleBuilder.swift
3+ // Rainbow
4+ //
5+ // Created by Wei Wang on 15/12/23.
6+ //
7+ // Copyright (c) 2018 Wei Wang <onevcat@gmail.com>
8+ //
9+ // Permission is hereby granted, free of charge, to any person obtaining a copy
10+ // of this software and associated documentation files (the "Software"), to deal
11+ // in the Software without restriction, including without limitation the rights
12+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+ // copies of the Software, and to permit persons to whom the Software is
14+ // furnished to do so, subject to the following conditions:
15+ //
16+ // The above copyright notice and this permission notice shall be included in
17+ // all copies or substantial portions of the Software.
18+ //
19+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+ // THE SOFTWARE.
26+
27+ /// A builder for applying multiple conditional styles to a string.
28+ /// This class provides a fluent interface for building complex conditional styling scenarios.
29+ public class ConditionalStyleBuilder {
30+ private let text : String
31+ private var steps : [ ( condition: Bool , transform: ( String ) -> String ) ] = [ ]
32+
33+ /// Initializes a new conditional style builder with the given text.
34+ /// - Parameter text: The text to apply conditional styles to.
35+ init ( text: String ) {
36+ self . text = text
37+ }
38+
39+ /// Creates a conditional step that will apply transformations if the condition is true.
40+ /// - Parameter condition: The condition to evaluate.
41+ /// - Returns: A `ConditionalStyleStep` for chaining style applications.
42+ public func when( _ condition: Bool ) -> ConditionalStyleStep {
43+ return ConditionalStyleStep ( builder: self , condition: condition)
44+ }
45+
46+ /// Creates a conditional step based on a closure predicate.
47+ /// - Parameter predicate: A closure that returns true if the styles should be applied.
48+ /// - Returns: A `ConditionalStyleStep` for chaining style applications.
49+ public func when( _ predicate: ( ) -> Bool ) -> ConditionalStyleStep {
50+ return ConditionalStyleStep ( builder: self , condition: predicate ( ) )
51+ }
52+
53+ /// Adds a transformation step to the builder.
54+ /// - Parameters:
55+ /// - condition: The condition for applying the transformation.
56+ /// - transform: The transformation to apply if the condition is true.
57+ func addStep( condition: Bool , transform: @escaping ( String ) -> String ) {
58+ steps. append ( ( condition, transform) )
59+ }
60+
61+ /// Builds the final string by applying all conditional transformations.
62+ /// - Returns: The string with all applicable conditional styles applied.
63+ public func build( ) -> String {
64+ var result = text
65+ for step in steps {
66+ if step. condition {
67+ result = step. transform ( result)
68+ }
69+ }
70+ return result
71+ }
72+ }
73+
74+ /// Represents a conditional step in the style building process.
75+ /// This class provides methods to apply various styles when a condition is met.
76+ public class ConditionalStyleStep {
77+ private let builder : ConditionalStyleBuilder
78+ private let condition : Bool
79+
80+ /// Initializes a new conditional style step.
81+ /// - Parameters:
82+ /// - builder: The parent builder.
83+ /// - condition: The condition for this step.
84+ init ( builder: ConditionalStyleBuilder , condition: Bool ) {
85+ self . builder = builder
86+ self . condition = condition
87+ }
88+
89+ /// Applies a color if the condition is true.
90+ /// - Parameter color: The named color to apply.
91+ /// - Returns: The parent builder for method chaining.
92+ @discardableResult
93+ public func color( _ color: NamedColor ) -> ConditionalStyleBuilder {
94+ builder. addStep ( condition: condition) { $0. applyingColor ( color) }
95+ return builder
96+ }
97+
98+ /// Applies a color type if the condition is true.
99+ /// - Parameter color: The color type to apply.
100+ /// - Returns: The parent builder for method chaining.
101+ @discardableResult
102+ public func color( _ color: ColorType ) -> ConditionalStyleBuilder {
103+ builder. addStep ( condition: condition) { $0. applyingColor ( color) }
104+ return builder
105+ }
106+
107+ /// Applies a background color if the condition is true.
108+ /// - Parameter color: The named background color to apply.
109+ /// - Returns: The parent builder for method chaining.
110+ @discardableResult
111+ public func backgroundColor( _ color: NamedBackgroundColor ) -> ConditionalStyleBuilder {
112+ builder. addStep ( condition: condition) { $0. applyingBackgroundColor ( . named( color) ) }
113+ return builder
114+ }
115+
116+ /// Applies a background color type if the condition is true.
117+ /// - Parameter color: The background color type to apply.
118+ /// - Returns: The parent builder for method chaining.
119+ @discardableResult
120+ public func backgroundColor( _ color: BackgroundColorType ) -> ConditionalStyleBuilder {
121+ builder. addStep ( condition: condition) { $0. applyingBackgroundColor ( color) }
122+ return builder
123+ }
124+
125+ /// Applies a style if the condition is true.
126+ /// - Parameter style: The style to apply.
127+ /// - Returns: The parent builder for method chaining.
128+ @discardableResult
129+ public func style( _ style: Style ) -> ConditionalStyleBuilder {
130+ builder. addStep ( condition: condition) { $0. applyingStyle ( style) }
131+ return builder
132+ }
133+
134+ /// Applies multiple styles if the condition is true.
135+ /// - Parameter styles: The styles to apply.
136+ /// - Returns: The parent builder for method chaining.
137+ @discardableResult
138+ public func styles( _ styles: Style ... ) -> ConditionalStyleBuilder {
139+ builder. addStep ( condition: condition) { $0. applyingStyles ( styles) }
140+ return builder
141+ }
142+
143+ /// Applies multiple styles from an array if the condition is true.
144+ /// - Parameter styles: The array of styles to apply.
145+ /// - Returns: The parent builder for method chaining.
146+ @discardableResult
147+ public func styles( _ styles: [ Style ] ) -> ConditionalStyleBuilder {
148+ builder. addStep ( condition: condition) { $0. applyingStyles ( styles) }
149+ return builder
150+ }
151+
152+ /// Applies a custom transformation if the condition is true.
153+ /// - Parameter transform: A closure that transforms the string.
154+ /// - Returns: The parent builder for method chaining.
155+ @discardableResult
156+ public func transform( _ transform: @escaping ( String ) -> String ) -> ConditionalStyleBuilder {
157+ builder. addStep ( condition: condition, transform: transform)
158+ return builder
159+ }
160+
161+ // Convenience methods for common colors
162+ public var black : ConditionalStyleStep {
163+ builder. addStep ( condition: condition) { $0. applyingColor ( . black) }
164+ return self
165+ }
166+ public var red : ConditionalStyleStep {
167+ builder. addStep ( condition: condition) { $0. applyingColor ( . red) }
168+ return self
169+ }
170+ public var green : ConditionalStyleStep {
171+ builder. addStep ( condition: condition) { $0. applyingColor ( . green) }
172+ return self
173+ }
174+ public var yellow : ConditionalStyleStep {
175+ builder. addStep ( condition: condition) { $0. applyingColor ( . yellow) }
176+ return self
177+ }
178+ public var blue : ConditionalStyleStep {
179+ builder. addStep ( condition: condition) { $0. applyingColor ( . blue) }
180+ return self
181+ }
182+ public var magenta : ConditionalStyleStep {
183+ builder. addStep ( condition: condition) { $0. applyingColor ( . magenta) }
184+ return self
185+ }
186+ public var cyan : ConditionalStyleStep {
187+ builder. addStep ( condition: condition) { $0. applyingColor ( . cyan) }
188+ return self
189+ }
190+ public var white : ConditionalStyleStep {
191+ builder. addStep ( condition: condition) { $0. applyingColor ( . white) }
192+ return self
193+ }
194+
195+ // Convenience methods for common styles
196+ public var bold : ConditionalStyleStep {
197+ builder. addStep ( condition: condition) { $0. applyingStyle ( . bold) }
198+ return self
199+ }
200+ public var dim : ConditionalStyleStep {
201+ builder. addStep ( condition: condition) { $0. applyingStyle ( . dim) }
202+ return self
203+ }
204+ public var italic : ConditionalStyleStep {
205+ builder. addStep ( condition: condition) { $0. applyingStyle ( . italic) }
206+ return self
207+ }
208+ public var underline : ConditionalStyleStep {
209+ builder. addStep ( condition: condition) { $0. applyingStyle ( . underline) }
210+ return self
211+ }
212+ public var blink : ConditionalStyleStep {
213+ builder. addStep ( condition: condition) { $0. applyingStyle ( . blink) }
214+ return self
215+ }
216+ public var swap : ConditionalStyleStep {
217+ builder. addStep ( condition: condition) { $0. applyingStyle ( . swap) }
218+ return self
219+ }
220+ public var strikethrough : ConditionalStyleStep {
221+ builder. addStep ( condition: condition) { $0. applyingStyle ( . strikethrough) }
222+ return self
223+ }
224+
225+ // Methods to transition back to builder for new conditions
226+ public func when( _ condition: Bool ) -> ConditionalStyleStep {
227+ return builder. when ( condition)
228+ }
229+
230+ public func when( _ predicate: ( ) -> Bool ) -> ConditionalStyleStep {
231+ return builder. when ( predicate)
232+ }
233+
234+ public func build( ) -> String {
235+ return builder. build ( )
236+ }
237+ }
0 commit comments