sai 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/CHANGELOG.md +38 -1
  4. data/README.md +39 -241
  5. data/docs/USAGE.md +351 -0
  6. data/lib/sai/ansi/color_parser.rb +109 -0
  7. data/lib/sai/ansi/sequence_processor.rb +269 -0
  8. data/lib/sai/ansi/sequenced_string.rb +475 -0
  9. data/lib/sai/ansi/style_parser.rb +66 -0
  10. data/lib/sai/ansi.rb +0 -27
  11. data/lib/sai/conversion/color_sequence.rb +4 -4
  12. data/lib/sai/conversion/rgb/color_classifier.rb +209 -0
  13. data/lib/sai/conversion/rgb/color_indexer.rb +48 -0
  14. data/lib/sai/conversion/rgb/color_space.rb +192 -0
  15. data/lib/sai/conversion/rgb/color_transformer.rb +140 -0
  16. data/lib/sai/conversion/rgb.rb +23 -269
  17. data/lib/sai/decorator/color_manipulations.rb +157 -0
  18. data/lib/sai/decorator/delegation.rb +84 -0
  19. data/lib/sai/decorator/gradients.rb +363 -0
  20. data/lib/sai/decorator/hex_colors.rb +56 -0
  21. data/lib/sai/decorator/named_colors.rb +780 -0
  22. data/lib/sai/decorator/named_styles.rb +276 -0
  23. data/lib/sai/decorator/rgb_colors.rb +64 -0
  24. data/lib/sai/decorator.rb +35 -795
  25. data/lib/sai/mode_selector.rb +19 -19
  26. data/lib/sai/named_colors.rb +437 -0
  27. data/lib/sai.rb +753 -23
  28. data/sig/manifest.yaml +3 -0
  29. data/sig/sai/ansi/color_parser.rbs +77 -0
  30. data/sig/sai/ansi/sequence_processor.rbs +178 -0
  31. data/sig/sai/ansi/sequenced_string.rbs +380 -0
  32. data/sig/sai/ansi/style_parser.rbs +59 -0
  33. data/sig/sai/ansi.rbs +0 -10
  34. data/sig/sai/conversion/rgb/color_classifier.rbs +165 -0
  35. data/sig/sai/conversion/rgb/color_indexer.rbs +41 -0
  36. data/sig/sai/conversion/rgb/color_space.rbs +129 -0
  37. data/sig/sai/conversion/rgb/color_transformer.rbs +99 -0
  38. data/sig/sai/conversion/rgb.rbs +15 -198
  39. data/sig/sai/decorator/color_manipulations.rbs +125 -0
  40. data/sig/sai/decorator/delegation.rbs +47 -0
  41. data/sig/sai/decorator/gradients.rbs +267 -0
  42. data/sig/sai/decorator/hex_colors.rbs +48 -0
  43. data/sig/sai/decorator/named_colors.rbs +1491 -0
  44. data/sig/sai/decorator/named_styles.rbs +72 -0
  45. data/sig/sai/decorator/rgb_colors.rbs +52 -0
  46. data/sig/sai/decorator.rbs +25 -202
  47. data/sig/sai/mode_selector.rbs +19 -19
  48. data/sig/sai/named_colors.rbs +65 -0
  49. data/sig/sai.rbs +1485 -44
  50. metadata +38 -4
@@ -0,0 +1,276 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sai
4
+ class Decorator
5
+ # Named style methods for the {Decorator} class
6
+ #
7
+ # @author {https://aaronmallen.me Aaron Allen}
8
+ # @since 0.3.1
9
+ #
10
+ # @abstract This module is meant to be included in the {Decorator} class to provide named style methods
11
+ # @api private
12
+ module NamedStyles
13
+ # @rbs!
14
+ # def blink: () -> Decorator
15
+ # def bold: () -> Decorator
16
+ # def conceal: () -> Decorator
17
+ # def dim: () -> Decorator
18
+ # def italic: () -> Decorator
19
+ # def no_blink: () -> Decorator
20
+ # def no_conceal: () -> Decorator
21
+ # def no_italic: () -> Decorator
22
+ # def no_reverse: () -> Decorator
23
+ # def no_strike: () -> Decorator
24
+ # def no_underline: () -> Decorator
25
+ # def normal_intensity: () -> Decorator
26
+ # def rapid_blink: () -> Decorator
27
+ # def reverse: () -> Decorator
28
+ # def strike: () -> Decorator
29
+ # def underline: () -> Decorator
30
+
31
+ # @!method blink
32
+ # Apply the ANSI style "blink" to the text
33
+ #
34
+ # @author {https://aaronmallen.me Aaron Allen}
35
+ # @since 0.1.0
36
+ #
37
+ # @api public
38
+ #
39
+ # @example
40
+ # decorator.blink.decorate('Hello, world!').to_s #=> "\e[5mHello, world!\e[0m"
41
+ #
42
+ # @return [Decorator] a new instance of Decorator with the style applied
43
+ #
44
+ # @!method bold
45
+ # Apply the ANSI style "bold" to the text
46
+ #
47
+ # @author {https://aaronmallen.me Aaron Allen}
48
+ # @since 0.1.0
49
+ #
50
+ # @api public
51
+ #
52
+ # @example
53
+ # decorator.bold.decorate('Hello, world!').to_s #=> "\e[1mHello, world!\e[0m"
54
+ #
55
+ # @return [Decorator] a new instance of Decorator with the style applied
56
+ #
57
+ # @!method conceal
58
+ # Apply the ANSI style "conceal" to the text
59
+ #
60
+ # @author {https://aaronmallen.me Aaron Allen}
61
+ # @since 0.1.0
62
+ #
63
+ # @api public
64
+ #
65
+ # @example
66
+ # decorator.conceal.decorate('Hello, world!').to_s #=> "\e[8mHello, world!\e[0m"
67
+ #
68
+ # @return [Decorator] a new instance of Decorator with the style applied
69
+ #
70
+ # @!method dim
71
+ # Apply the ANSI style "dim" to the text
72
+ #
73
+ # @author {https://aaronmallen.me Aaron Allen}
74
+ # @since 0.1.0
75
+ #
76
+ # @api public
77
+ #
78
+ # @example
79
+ # decorator.dim.decorate('Hello, world!').to_s #=> "\e[2mHello, world!\e[0m"
80
+ #
81
+ # @return [Decorator] a new instance of Decorator with the style applied
82
+ #
83
+ # @!method italic
84
+ # Apply the ANSI style "italic" to the text
85
+ #
86
+ # @author {https://aaronmallen.me Aaron Allen}
87
+ # @since 0.1.0
88
+ #
89
+ # @api public
90
+ #
91
+ # @example
92
+ # decorator.italic.decorate('Hello, world!').to_s #=> "\e[3mHello, world!\e[0m"
93
+ #
94
+ # @return [Decorator] a new instance of Decorator with the style applied
95
+ #
96
+ # @!method no_blink
97
+ # Remove the ANSI style "blink" from the text
98
+ #
99
+ # @author {https://aaronmallen.me Aaron Allen}
100
+ # @since 0.1.0
101
+ #
102
+ # @api public
103
+ #
104
+ # @example
105
+ # decorator.no_blink.decorate('Hello, world!').to_s #=> "\e[25mHello, world!\e[0m"
106
+ #
107
+ # @return [Decorator] a new instance of Decorator with the style applied
108
+ #
109
+ # @!method no_conceal
110
+ # Remove the ANSI style "conceal" from the text
111
+ #
112
+ # @author {https://aaronmallen.me Aaron Allen}
113
+ # @since 0.1.0
114
+ #
115
+ # @api public
116
+ #
117
+ # @example
118
+ # decorator.no_conceal.decorate('Hello, world!').to_s #=> "\e[28mHello, world!\e[0m"
119
+ #
120
+ # @return [Decorator] a new instance of Decorator with the style applied
121
+ #
122
+ # @!method no_italic
123
+ # Remove the ANSI style "italic" from the text
124
+ #
125
+ # @author {https://aaronmallen.me Aaron Allen}
126
+ # @since 0.1.0
127
+ #
128
+ # @api public
129
+ #
130
+ # @example
131
+ # decorator.no_italic.decorate('Hello, world!').to_s #=> "\e[23mHello, world!\e[0m"
132
+ #
133
+ # @return [Decorator] a new instance of Decorator with the style applied
134
+ #
135
+ # @!method no_reverse
136
+ # Remove the ANSI style "reverse" from the text
137
+ #
138
+ # @author {https://aaronmallen.me Aaron Allen}
139
+ # @since 0.1.0
140
+ #
141
+ # @api public
142
+ #
143
+ # @example
144
+ # decorator.no_reverse.decorate('Hello, world!').to_s #=> "\e[27mHello, world!\e[0m"
145
+ #
146
+ # @return [Decorator] a new instance of Decorator with the style applied
147
+ #
148
+ # @!method no_strike
149
+ # Remove the ANSI style "strike" from the text
150
+ #
151
+ # @author {https://aaronmallen.me Aaron Allen}
152
+ # @since 0.1.0
153
+ #
154
+ # @api public
155
+ #
156
+ # @example
157
+ # decorator.no_strike.decorate('Hello, world!').to_s #=> "\e[29mHello, world!\e[0m"
158
+ #
159
+ # @return [Decorator] a new instance of Decorator with the style applied
160
+ #
161
+ # @!method no_underline
162
+ # Remove the ANSI style "underline" from the text
163
+ #
164
+ # @author {https://aaronmallen.me Aaron Allen}
165
+ # @since 0.1.0
166
+ #
167
+ # @api public
168
+ #
169
+ # @example
170
+ # decorator.no_underline.decorate('Hello, world!').to_s #=> "\e[24mHello, world!\e[0m"
171
+ #
172
+ # @return [Decorator] a new instance of Decorator with the style applied
173
+ #
174
+ # @!method normal_intensity
175
+ # Remove any intensity styles (bold or dim) from the text
176
+ #
177
+ # @author {https://aaronmallen.me Aaron Allen}
178
+ # @since 0.1.0
179
+ #
180
+ # @api public
181
+ #
182
+ # @example
183
+ # decorator.normal_intensity.decorate('Hello, world!').to_s #=> "\e[22mHello, world!\e[0m"
184
+ #
185
+ # @return [Decorator] a new instance of Decorator with the style applied
186
+ #
187
+ # @!method rapid_blink
188
+ # Apply the ANSI style "rapid_blink" to the text
189
+ #
190
+ # @author {https://aaronmallen.me Aaron Allen}
191
+ # @since 0.1.0
192
+ #
193
+ # @api public
194
+ #
195
+ # @example
196
+ # decorator.rapid_blink.decorate('Hello, world!').to_s #=> "\e[6mHello, world!\e[0m"
197
+ #
198
+ # @return [Decorator] a new instance of Decorator with the style applied
199
+ #
200
+ # @!method reverse
201
+ # Apply the ANSI style "reverse" to the text
202
+ #
203
+ # @author {https://aaronmallen.me Aaron Allen}
204
+ # @since 0.1.0
205
+ #
206
+ # @api public
207
+ #
208
+ # @example
209
+ # decorator.reverse.decorate('Hello, world!').to_s #=> "\e[7mHello, world!\e[0m"
210
+ #
211
+ # @return [Decorator] a new instance of Decorator with the style applied
212
+ #
213
+ # @!method strike
214
+ # Apply the ANSI style "strike" to the text
215
+ #
216
+ # @author {https://aaronmallen.me Aaron Allen}
217
+ # @since 0.1.0
218
+ #
219
+ # @api public
220
+ #
221
+ # @example
222
+ # decorator.strike.decorate('Hello, world!').to_s #=> "\e[9mHello, world!\e[0m"
223
+ #
224
+ # @return [Decorator] a new instance of Decorator with the style applied
225
+ #
226
+ # @!method underline
227
+ # Apply the ANSI style "underline" to the text
228
+ #
229
+ # @author {https://aaronmallen.me Aaron Allen}
230
+ # @since 0.1.0
231
+ #
232
+ # @api public
233
+ #
234
+ # @example
235
+ # decorator.underline.decorate('Hello, world!').to_s #=> "\e[4mHello, world!\e[0m"
236
+ #
237
+ # @return [Decorator] a new instance of Decorator with the style applied
238
+ ANSI::STYLES.each_key do |style|
239
+ define_method(style) do
240
+ apply_style(style)
241
+ end
242
+ end
243
+
244
+ private
245
+
246
+ # Apply a style to the text
247
+ #
248
+ # @author {https://aaronmallen.me Aaron Allen}
249
+ # @since 0.1.0
250
+ #
251
+ # @api private
252
+ #
253
+ # @param style [String, Symbol] the style to apply
254
+ #
255
+ # @return [Decorator] a new instance of Decorator with the style applied
256
+ # @rbs (String | Symbol style) -> Decorator
257
+ def apply_style(style)
258
+ style = style.to_s.downcase.to_sym
259
+ dup.tap { |duped| duped.instance_variable_set(:@styles, (@styles + [style]).uniq) } #: Decorator
260
+ end
261
+
262
+ # Get style sequences
263
+ #
264
+ # @author {https://aaronmallen.me Aaron Allen}
265
+ # @since 0.3.1
266
+ #
267
+ # @api private
268
+ #
269
+ # @return [Array<String>] ANSI sequences for styles
270
+ # @rbs () -> Array[String]
271
+ def style_sequences
272
+ @styles.map { |style| "\e[#{ANSI::STYLES[style]}m" }
273
+ end
274
+ end
275
+ end
276
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sai
4
+ class Decorator
5
+ # RGB color methods for the {Decorator} class
6
+ #
7
+ # @author {https://aaronmallen.me Aaron Allen}
8
+ # @since 0.3.1
9
+ #
10
+ # @abstract This module is meant to be included in the {Decorator} class to provide RGB color methods
11
+ # @api private
12
+ module RGBColors
13
+ # Apply an RGB color to the background
14
+ #
15
+ # @author {https://aaronmallen.me Aaron Allen}
16
+ # @since 0.1.0
17
+ #
18
+ # @api public
19
+ #
20
+ # @example
21
+ # decorator.on_rgb(235, 65, 51).decorate('Hello, world!').to_s #=> "\e[48;2;235;65;51mHello, world!\e[0m"
22
+ #
23
+ # @param red [Integer] the red component
24
+ # @param green [Integer] the green component
25
+ # @param blue [Integer] the blue component
26
+ #
27
+ # @raise [ArgumentError] if the RGB values are out of range
28
+ # @return [Decorator] a new instance of Decorator with the RGB color applied
29
+ # @rbs (Integer red, Integer green, Integer blue) -> Decorator
30
+ def on_rgb(red, green, blue)
31
+ [red, green, blue].each do |value|
32
+ raise ArgumentError, "Invalid RGB value: #{red}, #{green}, #{blue}" unless value >= 0 && value <= 255
33
+ end
34
+
35
+ dup.tap { |duped| duped.instance_variable_set(:@background, [red, green, blue]) } #: Decorator
36
+ end
37
+
38
+ # Apply an RGB color to the foreground
39
+ #
40
+ # @author {https://aaronmallen.me Aaron Allen}
41
+ # @since 0.1.0
42
+ #
43
+ # @api public
44
+ #
45
+ # @example
46
+ # decorator.rgb(235, 65, 51).decorate('Hello, world!').to_s #=> "\e[38;2;235;65;51mHello, world!\e[0m"
47
+ #
48
+ # @param red [Integer] the red component
49
+ # @param green [Integer] the green component
50
+ # @param blue [Integer] the blue component
51
+ #
52
+ # @raise [ArgumentError] if the RGB values are out of range
53
+ # @return [Decorator] a new instance of Decorator with the RGB color applied
54
+ # @rbs (Integer red, Integer green, Integer blue) -> Decorator
55
+ def rgb(red, green, blue)
56
+ [red, green, blue].each do |value|
57
+ raise ArgumentError, "Invalid RGB value: #{red}, #{green}, #{blue}" unless value >= 0 && value <= 255
58
+ end
59
+
60
+ dup.tap { |duped| duped.instance_variable_set(:@foreground, [red, green, blue]) } #: Decorator
61
+ end
62
+ end
63
+ end
64
+ end