sai 0.1.0 → 0.2.0

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.
data/lib/sai/decorator.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'sai'
3
4
  require 'sai/ansi'
4
5
  require 'sai/conversion/color_sequence'
5
6
 
@@ -7,24 +8,24 @@ module Sai
7
8
  # A decorator for applying ANSI styles and colors to text
8
9
  #
9
10
  # @author {https://aaronmallen.me Aaron Allen}
10
- # @since unreleased
11
+ # @since 0.1.0
11
12
  #
12
13
  # @api public
13
14
  class Decorator
14
15
  # Initialize a new instance of Decorator
15
16
  #
16
17
  # @author {https://aaronmallen.me Aaron Allen}
17
- # @since unreleased
18
+ # @since 0.1.0
18
19
  #
19
20
  # @api private
20
21
  #
21
- # @param color_mode [Integer] the color mode to use
22
+ # @param mode [Integer] the color mode to use
22
23
  #
23
24
  # @return [Decorator] the new instance of Decorator
24
- # @rbs (Integer color_mode) -> void
25
- def initialize(color_mode)
25
+ # @rbs (?mode: Integer) -> void
26
+ def initialize(mode: Sai.mode.auto)
26
27
  @background = nil
27
- @color_mode = color_mode
28
+ @mode = mode
28
29
  @foreground = nil
29
30
  @styles = [] #: Array[Symbol]
30
31
  end
@@ -33,40 +34,40 @@ module Sai
33
34
  # Apply the named ANSI color "black" to the foreground
34
35
  #
35
36
  # @author {https://aaronmallen.me Aaron Allen}
36
- # @since unreleased
37
+ # @since 0.1.0
37
38
  #
38
39
  # @api public
39
40
  #
40
41
  # @example
41
42
  # decorator.black.decorate('Hello, world!') #=> "\e[30mHello, world!\e[0m"
42
43
  #
43
- # @return [self] the instance of Decorator for chaining
44
+ # @return [Decorator] a new instance of Decorator with the color applied
44
45
  #
45
46
  # @!method blue
46
47
  # Apply the named ANSI color "blue" to the foreground
47
48
  #
48
49
  # @author {https://aaronmallen.me Aaron Allen}
49
- # @since unreleased
50
+ # @since 0.1.0
50
51
  #
51
52
  # @api public
52
53
  #
53
54
  # @example
54
55
  # decorator.blue.decorate('Hello, world!') #=> "\e[34mHello, world!\e[0m"
55
56
  #
56
- # @return [self] the instance of Decorator for chaining
57
+ # @return [Decorator] a new instance of Decorator with the color applied
57
58
  #
58
59
  # @!method bright_black
59
60
  # Apply the named ANSI color "bright_black" to the foreground
60
61
  #
61
62
  # @author {https://aaronmallen.me Aaron Allen}
62
- # @since unreleased
63
+ # @since 0.1.0
63
64
  #
64
65
  # @api public
65
66
  #
66
67
  # @example
67
68
  # decorator.bright_black.decorate('Hello, world!') #=> "\e[90mHello, world!\e[0m"
68
69
  #
69
- # @return [self] the instance of Decorator for chaining
70
+ # @return [Decorator] a new instance of Decorator with the color applied
70
71
  #
71
72
  # @!method bright_blue
72
73
  # Apply the named ANSI color "bright_blue" to the foreground
@@ -76,7 +77,7 @@ module Sai
76
77
  # @example
77
78
  # decorator.bright_blue.decorate('Hello, world!') #=> "\e[94mHello, world!\e[0m"
78
79
  #
79
- # @return [self] the instance of Decorator for chaining
80
+ # @return [Decorator] a new instance of Decorator with the color applied
80
81
  #
81
82
  # @!method bright_cyan
82
83
  # Apply the named ANSI color "bright_cyan" to the foreground
@@ -86,7 +87,7 @@ module Sai
86
87
  # @example
87
88
  # decorator.bright_cyan.decorate('Hello, world!') #=> "\e[96mHello, world!\e[0m"
88
89
  #
89
- # @return [self] the instance of Decorator for chaining
90
+ # @return [Decorator] a new instance of Decorator with the color applied
90
91
  #
91
92
  # @!method bright_green
92
93
  # Apply the named ANSI color "bright_green" to the foreground
@@ -96,7 +97,7 @@ module Sai
96
97
  # @example
97
98
  # decorator.bright_green.decorate('Hello, world!') #=> "\e[92mHello, world!\e[0m"
98
99
  #
99
- # @return [self] the instance of Decorator for chaining
100
+ # @return [Decorator] a new instance of Decorator with the color applied
100
101
  #
101
102
  # @!method bright_magenta
102
103
  # Apply the named ANSI color "bright_magenta" to the foreground
@@ -106,7 +107,7 @@ module Sai
106
107
  # @example
107
108
  # decorator.bright_magenta.decorate('Hello, world!') #=> "\e[95mHello, world!\e[0m"
108
109
  #
109
- # @return [self] the instance of Decorator for chaining
110
+ # @return [Decorator] a new instance of Decorator with the color applied
110
111
  #
111
112
  # @!method bright_red
112
113
  # Apply the named ANSI color "bright_red" to the foreground
@@ -116,7 +117,7 @@ module Sai
116
117
  # @example
117
118
  # decorator.bright_red.decorate('Hello, world!') #=> "\e[91mHello, world!\e[0m"
118
119
  #
119
- # @return [self] the instance of Decorator for chaining
120
+ # @return [Decorator] a new instance of Decorator with the color applied
120
121
  #
121
122
  # @!method bright_white
122
123
  # Apply the named ANSI color "bright_white" to the foreground
@@ -126,7 +127,7 @@ module Sai
126
127
  # @example
127
128
  # decorator.bright_white.decorate('Hello, world!') #=> "\e[97mHello, world!\e[0m"
128
129
  #
129
- # @return [self] the instance of Decorator for chaining
130
+ # @return [Decorator] a new instance of Decorator with the color applied
130
131
  #
131
132
  # @!method bright_yellow
132
133
  # Apply the named ANSI color "bright_yellow" to the foreground
@@ -136,7 +137,7 @@ module Sai
136
137
  # @example
137
138
  # decorator.bright_yellow.decorate('Hello, world!') #=> "\e[93mHello, world!\e[0m"
138
139
  #
139
- # @return [self] the instance of Decorator for chaining
140
+ # @return [Decorator] a new instance of Decorator with the color applied
140
141
  #
141
142
  # @!method cyan
142
143
  # Apply the named ANSI color "cyan" to the foreground
@@ -146,7 +147,7 @@ module Sai
146
147
  # @example
147
148
  # decorator.cyan.decorate('Hello, world!') #=> "\e[36mHello, world!\e[0m"
148
149
  #
149
- # @return [self] the instance of Decorator for chaining
150
+ # @return [Decorator] a new instance of Decorator with the color applied
150
151
  #
151
152
  # @!method green
152
153
  # Apply the named ANSI color "green" to the foreground
@@ -156,7 +157,7 @@ module Sai
156
157
  # @example
157
158
  # decorator.green.decorate('Hello, world!') #=> "\e[32mHello, world!\e[0m"
158
159
  #
159
- # @return [self] the instance of Decorator for chaining
160
+ # @return [Decorator] a new instance of Decorator with the color applied
160
161
  #
161
162
  # @!method magenta
162
163
  # Apply the named ANSI color "magenta" to the foreground
@@ -166,215 +167,215 @@ module Sai
166
167
  # @example
167
168
  # decorator.magenta.decorate('Hello, world!') #=> "\e[35mHello, world!\e[0m"
168
169
  #
169
- # @return [self] the instance of Decorator for chaining
170
+ # @return [Decorator] a new instance of Decorator with the color applied
170
171
  #
171
172
  # @!method on_black
172
173
  # Apply the named ANSI color "black" to the background
173
174
  #
174
175
  # @author {https://aaronmallen.me Aaron Allen}
175
- # @since unreleased
176
+ # @since 0.1.0
176
177
  #
177
178
  # @api public
178
179
  #
179
180
  # @example
180
181
  # decorator.on_black.decorate('Hello, world!') #=> "\e[40mHello, world!\e[0m"
181
182
  #
182
- # @return [self] the instance of Decorator for chaining
183
+ # @return [Decorator] a new instance of Decorator with the color applied
183
184
  #
184
185
  # @!method on_blue
185
186
  # Apply the named ANSI color "blue" to the background
186
187
  #
187
188
  # @author {https://aaronmallen.me Aaron Allen}
188
- # @since unreleased
189
+ # @since 0.1.0
189
190
  #
190
191
  # @api public
191
192
  #
192
193
  # @example
193
194
  # decorator.on_blue.decorate('Hello, world!') #=> "\e[44mHello, world!\e[0m"
194
195
  #
195
- # @return [self] the instance of Decorator for chaining
196
+ # @return [Decorator] a new instance of Decorator with the color applied
196
197
  #
197
198
  # @!method on_bright_black
198
199
  # Apply the named ANSI color "bright_black" to the background
199
200
  #
200
201
  # @author {https://aaronmallen.me Aaron Allen}
201
- # @since unreleased
202
+ # @since 0.1.0
202
203
  #
203
204
  # @api public
204
205
  #
205
206
  # @example
206
207
  # decorator.on_bright_black.decorate('Hello, world!') #=> "\e[100mHello, world!\e[0m"
207
208
  #
208
- # @return [self] the instance of Decorator for chaining
209
+ # @return [Decorator] a new instance of Decorator with the color applied
209
210
  #
210
211
  # @!method on_bright_blue
211
212
  # Apply the named ANSI color "bright_blue" to the background
212
213
  #
213
214
  # @author {https://aaronmallen.me Aaron Allen}
214
- # @since unreleased
215
+ # @since 0.1.0
215
216
  #
216
217
  # @api public
217
218
  #
218
219
  # @example
219
220
  # decorator.on_bright_blue.decorate('Hello, world!') #=> "\e[104mHello, world!\e[0m"
220
221
  #
221
- # @return [self] the instance of Decorator for chaining
222
+ # @return [Decorator] a new instance of Decorator with the color applied
222
223
  #
223
224
  # @!method on_bright_cyan
224
225
  # Apply the named ANSI color "bright_cyan" to the background
225
226
  #
226
227
  # @author {https://aaronmallen.me Aaron Allen}
227
- # @since unreleased
228
+ # @since 0.1.0
228
229
  #
229
230
  # @api public
230
231
  #
231
232
  # @example
232
233
  # decorator.on_bright_cyan.decorate('Hello, world!') #=> "\e[106mHello, world!\e[0m"
233
234
  #
234
- # @return [self] the instance of Decorator for chaining
235
+ # @return [Decorator] a new instance of Decorator with the color applied
235
236
  #
236
237
  # @!method on_bright_green
237
238
  # Apply the named ANSI color "bright_green" to the background
238
239
  #
239
240
  # @author {https://aaronmallen.me Aaron Allen}
240
- # @since unreleased
241
+ # @since 0.1.0
241
242
  #
242
243
  # @api public
243
244
  #
244
245
  # @example
245
246
  # decorator.on_bright_green.decorate('Hello, world!') #=> "\e[102mHello, world!\e[0m"
246
247
  #
247
- # @return [self] the instance of Decorator for chaining
248
+ # @return [Decorator] a new instance of Decorator with the color applied
248
249
  #
249
250
  # @!method on_bright_magenta
250
251
  # Apply the named ANSI color "bright_magenta" to the background
251
252
  #
252
253
  # @author {https://aaronmallen.me Aaron Allen}
253
- # @since unreleased
254
+ # @since 0.1.0
254
255
  #
255
256
  # @api public
256
257
  #
257
258
  # @example
258
259
  # decorator.on_bright_magenta.decorate('Hello, world!') #=> "\e[105mHello, world!\e[0m"
259
260
  #
260
- # @return [self] the instance of Decorator for chaining
261
+ # @return [Decorator] a new instance of Decorator with the color applied
261
262
  #
262
263
  # @!method on_bright_red
263
264
  # Apply the named ANSI color "bright_red" to the background
264
265
  #
265
266
  # @author {https://aaronmallen.me Aaron Allen}
266
- # @since unreleased
267
+ # @since 0.1.0
267
268
  #
268
269
  # @api public
269
270
  #
270
271
  # @example
271
272
  # decorator.on_bright_red.decorate('Hello, world!') #=> "\e[101mHello, world!\e[0m"
272
273
  #
273
- # @return [self] the instance of Decorator for chaining
274
+ # @return [Decorator] a new instance of Decorator with the color applied
274
275
  #
275
276
  # @!method on_bright_white
276
277
  # Apply the named ANSI color "bright_white" to the background
277
278
  #
278
279
  # @author {https://aaronmallen.me Aaron Allen}
279
- # @since unreleased
280
+ # @since 0.1.0
280
281
  #
281
282
  # @api public
282
283
  #
283
284
  # @example
284
285
  # decorator.on_bright_white.decorate('Hello, world!') #=> "\e[107mHello, world!\e[0m"
285
286
  #
286
- # @return [self] the instance of Decorator for chaining
287
+ # @return [Decorator] a new instance of Decorator with the color applied
287
288
  #
288
289
  # @!method on_bright_yellow
289
290
  # Apply the named ANSI color "bright_yellow" to the background
290
291
  #
291
292
  # @author {https://aaronmallen.me Aaron Allen}
292
- # @since unreleased
293
+ # @since 0.1.0
293
294
  #
294
295
  # @api public
295
296
  #
296
297
  # @example
297
298
  # decorator.on_bright_yellow.decorate('Hello, world!') #=> "\e[103mHello, world!\e[0m"
298
299
  #
299
- # @return [self] the instance of Decorator for chaining
300
+ # @return [Decorator] a new instance of Decorator with the color applied
300
301
  #
301
302
  # @!method on_cyan
302
303
  # Apply the named ANSI color "cyan" to the background
303
304
  #
304
305
  # @author {https://aaronmallen.me Aaron Allen}
305
- # @since unreleased
306
+ # @since 0.1.0
306
307
  #
307
308
  # @api public
308
309
  #
309
310
  # @example
310
311
  # decorator.on_cyan.decorate('Hello, world!') #=> "\e[46mHello, world!\e[0m"
311
312
  #
312
- # @return [self] the instance of Decorator for chaining
313
+ # @return [Decorator] a new instance of Decorator with the color applied
313
314
  #
314
315
  # @!method on_green
315
316
  # Apply the named ANSI color "green" to the background
316
317
  #
317
318
  # @author {https://aaronmallen.me Aaron Allen}
318
- # @since unreleased
319
+ # @since 0.1.0
319
320
  #
320
321
  # @api public
321
322
  #
322
323
  # @example
323
324
  # decorator.on_green.decorate('Hello, world!') #=> "\e[42mHello, world!\e[0m"
324
325
  #
325
- # @return [self] the instance of Decorator for chaining
326
+ # @return [Decorator] a new instance of Decorator with the color applied
326
327
  #
327
328
  # @!method on_magenta
328
329
  # Apply the named ANSI color "magenta" to the background
329
330
  #
330
331
  # @author {https://aaronmallen.me Aaron Allen}
331
- # @since unreleased
332
+ # @since 0.1.0
332
333
  #
333
334
  # @api public
334
335
  #
335
336
  # @example
336
337
  # decorator.on_magenta.decorate('Hello, world!') #=> "\e[45mHello, world!\e[0m"
337
338
  #
338
- # @return [self] the instance of Decorator for chaining
339
+ # @return [Decorator] a new instance of Decorator with the color applied
339
340
  #
340
341
  # @!method on_red
341
342
  # Apply the named ANSI color "red" to the background
342
343
  #
343
344
  # @author {https://aaronmallen.me Aaron Allen}
344
- # @since unreleased
345
+ # @since 0.1.0
345
346
  #
346
347
  # @api public
347
348
  #
348
349
  # @example
349
350
  # decorator.on_red.decorate('Hello, world!') #=> "\e[41mHello, world!\e[0m"
350
351
  #
351
- # @return [self] the instance of Decorator for chaining
352
+ # @return [Decorator] a new instance of Decorator with the color applied
352
353
  #
353
354
  # @!method on_white
354
355
  # Apply the named ANSI color "white" to the background
355
356
  #
356
357
  # @author {https://aaronmallen.me Aaron Allen}
357
- # @since unreleased
358
+ # @since 0.1.0
358
359
  #
359
360
  # @api public
360
361
  #
361
362
  # @example
362
363
  # decorator.on_white.decorate('Hello, world!') #=> "\e[47mHello, world!\e[0m"
363
364
  #
364
- # @return [self] the instance of Decorator for chaining
365
+ # @return [Decorator] a new instance of Decorator with the color applied
365
366
  #
366
367
  # @!method on_yellow
367
368
  # Apply the named ANSI color "yellow" to the background
368
369
  #
369
370
  # @author {https://aaronmallen.me Aaron Allen}
370
- # @since unreleased
371
+ # @since 0.1.0
371
372
  #
372
373
  # @api public
373
374
  #
374
375
  # @example
375
376
  # decorator.on_yellow.decorate('Hello, world!') #=> "\e[43mHello, world!\e[0m"
376
377
  #
377
- # @return [self] the instance of Decorator for chaining
378
+ # @return [Decorator] a new instance of Decorator with the color applied
378
379
  #
379
380
  # @!method red
380
381
  # Apply the named ANSI color "red" to the foreground
@@ -384,7 +385,7 @@ module Sai
384
385
  # @example
385
386
  # decorator.red.decorate('Hello, world!') #=> "\e[31mHello, world!\e[0m"
386
387
  #
387
- # @return [self] the instance of Decorator for chaining
388
+ # @return [Decorator] a new instance of Decorator with the color applied
388
389
  #
389
390
  # @!method white
390
391
  # Apply the named ANSI color "white" to the foreground
@@ -394,7 +395,7 @@ module Sai
394
395
  # @example
395
396
  # decorator.white.decorate('Hello, world!') #=> "\e[37mHello, world!\e[0m"
396
397
  #
397
- # @return [self] the instance of Decorator for chaining
398
+ # @return [Decorator] a new instance of Decorator with the color applied
398
399
  #
399
400
  # @!method yellow
400
401
  # Apply the named ANSI color "yellow" to the foreground
@@ -404,7 +405,7 @@ module Sai
404
405
  # @example
405
406
  # decorator.yellow.decorate('Hello, world!') #=> "\e[33mHello, world!\e[0m"
406
407
  #
407
- # @return [self] the instance of Decorator for chaining
408
+ # @return [Decorator] a new instance of Decorator with the color applied
408
409
  ANSI::COLOR_NAMES.each_key do |color|
409
410
  define_method(color) do
410
411
  apply_named_color(:foreground, color)
@@ -414,246 +415,246 @@ module Sai
414
415
  end
415
416
  end
416
417
  # @rbs!
417
- # def black: () -> self
418
- # def blue: () -> self
419
- # def bright_black: () -> self
420
- # def bright_blue: () -> self
421
- # def bright_cyan: () -> self
422
- # def bright_green: () -> self
423
- # def bright_magenta: () -> self
424
- # def bright_red: () -> self
425
- # def bright_white: () -> self
426
- # def bright_yellow: () -> self
427
- # def cyan: () -> self
428
- # def green: () -> self
429
- # def magenta: () -> self
430
- # def on_black: () -> self
431
- # def on_blue: () -> self
432
- # def on_bright_black: () -> self
433
- # def on_bright_blue: () -> self
434
- # def on_bright_cyan: () -> self
435
- # def on_bright_green: () -> self
436
- # def on_bright_magenta: () -> self
437
- # def on_bright_red: () -> self
438
- # def on_bright_white: () -> self
439
- # def on_bright_yellow: () -> self
440
- # def on_cyan: () -> self
441
- # def on_green: () -> self
442
- # def on_magenta: () -> self
443
- # def on_red: () -> self
444
- # def on_white: () -> self
445
- # def on_yellow: () -> self
446
- # def red: () -> self
447
- # def white: () -> self
448
- # def yellow: () -> self
418
+ # def black: () -> Decorator
419
+ # def blue: () -> Decorator
420
+ # def bright_black: () -> Decorator
421
+ # def bright_blue: () -> Decorator
422
+ # def bright_cyan: () -> Decorator
423
+ # def bright_green: () -> Decorator
424
+ # def bright_magenta: () -> Decorator
425
+ # def bright_red: () -> Decorator
426
+ # def bright_white: () -> Decorator
427
+ # def bright_yellow: () -> Decorator
428
+ # def cyan: () -> Decorator
429
+ # def green: () -> Decorator
430
+ # def magenta: () -> Decorator
431
+ # def on_black: () -> Decorator
432
+ # def on_blue: () -> Decorator
433
+ # def on_bright_black: () -> Decorator
434
+ # def on_bright_blue: () -> Decorator
435
+ # def on_bright_cyan: () -> Decorator
436
+ # def on_bright_green: () -> Decorator
437
+ # def on_bright_magenta: () -> Decorator
438
+ # def on_bright_red: () -> Decorator
439
+ # def on_bright_white: () -> Decorator
440
+ # def on_bright_yellow: () -> Decorator
441
+ # def on_cyan: () -> Decorator
442
+ # def on_green: () -> Decorator
443
+ # def on_magenta: () -> Decorator
444
+ # def on_red: () -> Decorator
445
+ # def on_white: () -> Decorator
446
+ # def on_yellow: () -> Decorator
447
+ # def red: () -> Decorator
448
+ # def white: () -> Decorator
449
+ # def yellow: () -> Decorator
449
450
 
450
451
  # @!method blink
451
452
  # Apply the ANSI style "blink" to the text
452
453
  #
453
454
  # @author {https://aaronmallen.me Aaron Allen}
454
- # @since unreleased
455
+ # @since 0.1.0
455
456
  #
456
457
  # @api public
457
458
  #
458
459
  # @example
459
460
  # decorator.blink.decorate('Hello, world!') #=> "\e[5mHello, world!\e[0m"
460
461
  #
461
- # @return [self] the instance of Decorator for chaining
462
+ # @return [Decorator] a new instance of Decorator with the style applied
462
463
  #
463
464
  # @!method bold
464
465
  # Apply the ANSI style "bold" to the text
465
466
  #
466
467
  # @author {https://aaronmallen.me Aaron Allen}
467
- # @since unreleased
468
+ # @since 0.1.0
468
469
  #
469
470
  # @api public
470
471
  #
471
472
  # @example
472
473
  # decorator.bold.decorate('Hello, world!') #=> "\e[1mHello, world!\e[0m"
473
474
  #
474
- # @return [self] the instance of Decorator for chaining
475
+ # @return [Decorator] a new instance of Decorator with the style applied
475
476
  #
476
477
  # @!method conceal
477
478
  # Apply the ANSI style "conceal" to the text
478
479
  #
479
480
  # @author {https://aaronmallen.me Aaron Allen}
480
- # @since unreleased
481
+ # @since 0.1.0
481
482
  #
482
483
  # @api public
483
484
  #
484
485
  # @example
485
486
  # decorator.conceal.decorate('Hello, world!') #=> "\e[8mHello, world!\e[0m"
486
487
  #
487
- # @return [self] the instance of Decorator for chaining
488
+ # @return [Decorator] a new instance of Decorator with the style applied
488
489
  #
489
490
  # @!method dim
490
491
  # Apply the ANSI style "dim" to the text
491
492
  #
492
493
  # @author {https://aaronmallen.me Aaron Allen}
493
- # @since unreleased
494
+ # @since 0.1.0
494
495
  #
495
496
  # @api public
496
497
  #
497
498
  # @example
498
499
  # decorator.dim.decorate('Hello, world!') #=> "\e[2mHello, world!\e[0m"
499
500
  #
500
- # @return [self] the instance of Decorator for chaining
501
+ # @return [Decorator] a new instance of Decorator with the style applied
501
502
  #
502
503
  # @!method italic
503
504
  # Apply the ANSI style "italic" to the text
504
505
  #
505
506
  # @author {https://aaronmallen.me Aaron Allen}
506
- # @since unreleased
507
+ # @since 0.1.0
507
508
  #
508
509
  # @api public
509
510
  #
510
511
  # @example
511
512
  # decorator.italic.decorate('Hello, world!') #=> "\e[3mHello, world!\e[0m"
512
513
  #
513
- # @return [self] the instance of Decorator for chaining
514
+ # @return [Decorator] a new instance of Decorator with the style applied
514
515
  #
515
516
  # @!method no_blink
516
517
  # Remove the ANSI style "blink" from the text
517
518
  #
518
519
  # @author {https://aaronmallen.me Aaron Allen}
519
- # @since unreleased
520
+ # @since 0.1.0
520
521
  #
521
522
  # @api public
522
523
  #
523
524
  # @example
524
525
  # decorator.no_blink.decorate('Hello, world!') #=> "\e[25mHello, world!\e[0m"
525
526
  #
526
- # @return [self] the instance of Decorator for chaining
527
+ # @return [Decorator] a new instance of Decorator with the style applied
527
528
  #
528
529
  # @!method no_conceal
529
530
  # Remove the ANSI style "conceal" from the text
530
531
  #
531
532
  # @author {https://aaronmallen.me Aaron Allen}
532
- # @since unreleased
533
+ # @since 0.1.0
533
534
  #
534
535
  # @api public
535
536
  #
536
537
  # @example
537
538
  # decorator.no_conceal.decorate('Hello, world!') #=> "\e[28mHello, world!\e[0m"
538
539
  #
539
- # @return [self] the instance of Decorator for chaining
540
+ # @return [Decorator] a new instance of Decorator with the style applied
540
541
  #
541
542
  # @!method no_italic
542
543
  # Remove the ANSI style "italic" from the text
543
544
  #
544
545
  # @author {https://aaronmallen.me Aaron Allen}
545
- # @since unreleased
546
+ # @since 0.1.0
546
547
  #
547
548
  # @api public
548
549
  #
549
550
  # @example
550
551
  # decorator.no_italic.decorate('Hello, world!') #=> "\e[23mHello, world!\e[0m"
551
552
  #
552
- # @return [self] the instance of Decorator for chaining
553
+ # @return [Decorator] a new instance of Decorator with the style applied
553
554
  #
554
555
  # @!method no_reverse
555
556
  # Remove the ANSI style "reverse" from the text
556
557
  #
557
558
  # @author {https://aaronmallen.me Aaron Allen}
558
- # @since unreleased
559
+ # @since 0.1.0
559
560
  #
560
561
  # @api public
561
562
  #
562
563
  # @example
563
564
  # decorator.no_reverse.decorate('Hello, world!') #=> "\e[27mHello, world!\e[0m"
564
565
  #
565
- # @return [self] the instance of Decorator for chaining
566
+ # @return [Decorator] a new instance of Decorator with the style applied
566
567
  #
567
568
  # @!method no_strike
568
569
  # Remove the ANSI style "strike" from the text
569
570
  #
570
571
  # @author {https://aaronmallen.me Aaron Allen}
571
- # @since unreleased
572
+ # @since 0.1.0
572
573
  #
573
574
  # @api public
574
575
  #
575
576
  # @example
576
577
  # decorator.no_strike.decorate('Hello, world!') #=> "\e[29mHello, world!\e[0m"
577
578
  #
578
- # @return [self] the instance of Decorator for chaining
579
+ # @return [Decorator] a new instance of Decorator with the style applied
579
580
  #
580
581
  # @!method no_underline
581
582
  # Remove the ANSI style "underline" from the text
582
583
  #
583
584
  # @author {https://aaronmallen.me Aaron Allen}
584
- # @since unreleased
585
+ # @since 0.1.0
585
586
  #
586
587
  # @api public
587
588
  #
588
589
  # @example
589
590
  # decorator.no_underline.decorate('Hello, world!') #=> "\e[24mHello, world!\e[0m"
590
591
  #
591
- # @return [self] the instance of Decorator for chaining
592
+ # @return [Decorator] a new instance of Decorator with the style applied
592
593
  #
593
594
  # @!method normal_intensity
594
595
  # Remove any intensity styles (bold or dim) from the text
595
596
  #
596
597
  # @author {https://aaronmallen.me Aaron Allen}
597
- # @since unreleased
598
+ # @since 0.1.0
598
599
  #
599
600
  # @api public
600
601
  #
601
602
  # @example
602
603
  # decorator.normal_intensity.decorate('Hello, world!') #=> "\e[22mHello, world!\e[0m"
603
604
  #
604
- # @return [self] the instance of Decorator for chaining
605
+ # @return [Decorator] a new instance of Decorator with the style applied
605
606
  #
606
607
  # @!method rapid_blink
607
608
  # Apply the ANSI style "rapid_blink" to the text
608
609
  #
609
610
  # @author {https://aaronmallen.me Aaron Allen}
610
- # @since unreleased
611
+ # @since 0.1.0
611
612
  #
612
613
  # @api public
613
614
  #
614
615
  # @example
615
616
  # decorator.rapid_blink.decorate('Hello, world!') #=> "\e[6mHello, world!\e[0m"
616
617
  #
617
- # @return [self] the instance of Decorator for chaining
618
+ # @return [Decorator] a new instance of Decorator with the style applied
618
619
  #
619
620
  # @!method reverse
620
621
  # Apply the ANSI style "reverse" to the text
621
622
  #
622
623
  # @author {https://aaronmallen.me Aaron Allen}
623
- # @since unreleased
624
+ # @since 0.1.0
624
625
  #
625
626
  # @api public
626
627
  #
627
628
  # @example
628
629
  # decorator.reverse.decorate('Hello, world!') #=> "\e[7mHello, world!\e[0m"
629
630
  #
630
- # @return [self] the instance of Decorator for chaining
631
+ # @return [Decorator] a new instance of Decorator with the style applied
631
632
  #
632
633
  # @!method strike
633
634
  # Apply the ANSI style "strike" to the text
634
635
  #
635
636
  # @author {https://aaronmallen.me Aaron Allen}
636
- # @since unreleased
637
+ # @since 0.1.0
637
638
  #
638
639
  # @api public
639
640
  #
640
641
  # @example
641
642
  # decorator.strike.decorate('Hello, world!') #=> "\e[9mHello, world!\e[0m"
642
643
  #
643
- # @return [self] the instance of Decorator for chaining
644
+ # @return [Decorator] a new instance of Decorator with the style applied
644
645
  #
645
646
  # @!method underline
646
647
  # Apply the ANSI style "underline" to the text
647
648
  #
648
649
  # @author {https://aaronmallen.me Aaron Allen}
649
- # @since unreleased
650
+ # @since 0.1.0
650
651
  #
651
652
  # @api public
652
653
  #
653
654
  # @example
654
655
  # decorator.underline.decorate('Hello, world!') #=> "\e[4mHello, world!\e[0m"
655
656
  #
656
- # @return [self] the instance of Decorator for chaining
657
+ # @return [Decorator] a new instance of Decorator with the style applied
657
658
  ANSI::STYLES.each_key do |style|
658
659
  define_method(style) do
659
660
  apply_style(style)
@@ -661,27 +662,27 @@ module Sai
661
662
  end
662
663
 
663
664
  # @rbs!
664
- # def blink: () -> self
665
- # def bold: () -> self
666
- # def conceal: () -> self
667
- # def dim: () -> self
668
- # def italic: () -> self
669
- # def no_blink: () -> self
670
- # def no_conceal: () -> self
671
- # def no_italic: () -> self
672
- # def no_reverse: () -> self
673
- # def no_strike: () -> self
674
- # def no_underline: () -> self
675
- # def normal_intensity: () -> self
676
- # def rapid_blink: () -> self
677
- # def reverse: () -> self
678
- # def strike: () -> self
679
- # def underline: () -> self
665
+ # def blink: () -> Decorator
666
+ # def bold: () -> Decorator
667
+ # def conceal: () -> Decorator
668
+ # def dim: () -> Decorator
669
+ # def italic: () -> Decorator
670
+ # def no_blink: () -> Decorator
671
+ # def no_conceal: () -> Decorator
672
+ # def no_italic: () -> Decorator
673
+ # def no_reverse: () -> Decorator
674
+ # def no_strike: () -> Decorator
675
+ # def no_underline: () -> Decorator
676
+ # def normal_intensity: () -> Decorator
677
+ # def rapid_blink: () -> Decorator
678
+ # def reverse: () -> Decorator
679
+ # def strike: () -> Decorator
680
+ # def underline: () -> Decorator
680
681
 
681
682
  # Apply the styles and colors to the text
682
683
  #
683
684
  # @author {https://aaronmallen.me Aaron Allen}
684
- # @since unreleased
685
+ # @since 0.1.0
685
686
  #
686
687
  # @api public
687
688
  #
@@ -694,11 +695,11 @@ module Sai
694
695
  # @return [String] the decorated text
695
696
  # @rbs (String text) -> String
696
697
  def decorate(text)
697
- return text if @foreground.nil? && @background.nil? && @styles.empty?
698
+ return text unless should_decorate?
698
699
 
699
700
  sequences = [
700
- @foreground && Conversion::ColorSequence.resolve(@foreground, @color_mode),
701
- @background && Conversion::ColorSequence.resolve(@background, @color_mode, :background),
701
+ @foreground && Conversion::ColorSequence.resolve(@foreground, @mode),
702
+ @background && Conversion::ColorSequence.resolve(@background, @mode, :background),
702
703
  @styles.map { |style| "\e[#{ANSI::STYLES[style]}m" }.join
703
704
  ].compact.join
704
705
 
@@ -711,7 +712,7 @@ module Sai
711
712
  # Apply a hexadecimal color to the foreground
712
713
  #
713
714
  # @author {https://aaronmallen.me Aaron Allen}
714
- # @since unreleased
715
+ # @since 0.1.0
715
716
  #
716
717
  # @api public
717
718
  #
@@ -721,19 +722,18 @@ module Sai
721
722
  # @param code [String] the hex color code
722
723
  #
723
724
  # @raise [ArgumentError] if the hex code is invalid
724
- # @return [self] the instance of Decorator for chaining
725
- # @rbs (String code) -> self
725
+ # @return [Decorator] a new instance of Decorator with the hex color applied
726
+ # @rbs (String code) -> Decorator
726
727
  def hex(code)
727
728
  raise ArgumentError, "Invalid hex color code: #{code}" unless /^#?([A-Fa-f0-9]{6})$/.match?(code)
728
729
 
729
- @foreground = code
730
- self
730
+ dup.tap { |duped| duped.instance_variable_set(:@foreground, code) }
731
731
  end
732
732
 
733
733
  # Apply a hexadecimal color to the background
734
734
  #
735
735
  # @author {https://aaronmallen.me Aaron Allen}
736
- # @since unreleased
736
+ # @since 0.1.0
737
737
  #
738
738
  # @api public
739
739
  #
@@ -743,19 +743,18 @@ module Sai
743
743
  # @param code [String] the hex color code
744
744
  #
745
745
  # @raise [ArgumentError] if the hex code is invalid
746
- # @return [self] the instance of Decorator for chaining
747
- # @rbs (String code) -> self
746
+ # @return [Decorator] a new instance of Decorator with the hex color applied
747
+ # @rbs (String code) -> Decorator
748
748
  def on_hex(code)
749
749
  raise ArgumentError, "Invalid hex color code: #{code}" unless /^#?([A-Fa-f0-9]{6})$/.match?(code)
750
750
 
751
- @background = code
752
- self
751
+ dup.tap { |duped| duped.instance_variable_set(:@background, code) }
753
752
  end
754
753
 
755
754
  # Apply an RGB color to the background
756
755
  #
757
756
  # @author {https://aaronmallen.me Aaron Allen}
758
- # @since unreleased
757
+ # @since 0.1.0
759
758
  #
760
759
  # @api public
761
760
  #
@@ -767,21 +766,20 @@ module Sai
767
766
  # @param blue [Integer] the blue component
768
767
  #
769
768
  # @raise [ArgumentError] if the RGB values are out of range
770
- # @return [self] the instance of Decorator for chaining
771
- # @rbs (Integer red, Integer green, Integer blue) -> self
769
+ # @return [Decorator] a new instance of Decorator with the RGB color applied
770
+ # @rbs (Integer red, Integer green, Integer blue) -> Decorator
772
771
  def on_rgb(red, green, blue)
773
772
  [red, green, blue].each do |value|
774
773
  raise ArgumentError, "Invalid RGB value: #{red}, #{green}, #{blue}" unless value >= 0 && value <= 255
775
774
  end
776
775
 
777
- @background = [red, green, blue]
778
- self
776
+ dup.tap { |duped| duped.instance_variable_set(:@background, [red, green, blue]) }
779
777
  end
780
778
 
781
779
  # Apply an RGB color to the foreground
782
780
  #
783
781
  # @author {https://aaronmallen.me Aaron Allen}
784
- # @since unreleased
782
+ # @since 0.1.0
785
783
  #
786
784
  # @api public
787
785
  #
@@ -793,15 +791,32 @@ module Sai
793
791
  # @param blue [Integer] the blue component
794
792
  #
795
793
  # @raise [ArgumentError] if the RGB values are out of range
796
- # @return [self] the instance of Decorator for chaining
797
- # @rbs (Integer red, Integer green, Integer blue) -> self
794
+ # @return [Decorator] a new instance of Decorator with the RGB color applied
795
+ # @rbs (Integer red, Integer green, Integer blue) -> Decorator
798
796
  def rgb(red, green, blue)
799
797
  [red, green, blue].each do |value|
800
798
  raise ArgumentError, "Invalid RGB value: #{red}, #{green}, #{blue}" unless value >= 0 && value <= 255
801
799
  end
802
800
 
803
- @foreground = [red, green, blue]
804
- self
801
+ dup.tap { |duped| duped.instance_variable_set(:@foreground, [red, green, blue]) }
802
+ end
803
+
804
+ # Apply a specific color mode to the decorator
805
+ #
806
+ # @author {https://aaronmallen.me Aaron Allen}
807
+ # @since 0.2.0
808
+ #
809
+ # @api public
810
+ #
811
+ # @example
812
+ # decorator.with_mode(Sai.mode.basic_auto) #=> => #<Sai::Decorator:0x123 @mode=1>
813
+ #
814
+ # @param mode [Integer] the color mode to use
815
+ #
816
+ # @return [Decorator] a new instance of Decorator with the applied color mode
817
+ # @rbs (Integer mode) -> Decorator
818
+ def with_mode(mode)
819
+ dup.tap { |duped| duped.instance_variable_set(:@mode, mode) }
805
820
  end
806
821
 
807
822
  private
@@ -809,7 +824,7 @@ module Sai
809
824
  # Apply a named color to the specified style type
810
825
  #
811
826
  # @author {https://aaronmallen.me Aaron Allen}
812
- # @since unreleased
827
+ # @since 0.1.0
813
828
  #
814
829
  # @api private
815
830
  #
@@ -817,8 +832,8 @@ module Sai
817
832
  # @param color [Symbol] the color to apply
818
833
  #
819
834
  # @raise [ArgumentError] if the color is invalid
820
- # @return [self] the instance of Decorator for chaining
821
- # @rbs (Conversion::ColorSequence::style_type style_type, Symbol color) -> self
835
+ # @return [Decorator] a new instance of Decorator with the color applied
836
+ # @rbs (Conversion::ColorSequence::style_type style_type, Symbol color) -> Decorator
822
837
  def apply_named_color(style_type, color)
823
838
  unless ANSI::COLOR_NAMES.key?(color.to_s.downcase.to_sym)
824
839
  e = ArgumentError.new("Invalid color: #{color}")
@@ -826,31 +841,46 @@ module Sai
826
841
  raise e
827
842
  end
828
843
 
829
- instance_variable_set(:"@#{style_type}", color)
830
- self
844
+ dup.tap { |duped| duped.instance_variable_set(:"@#{style_type}", color) }
831
845
  end
832
846
 
833
847
  # Apply a style to the text
834
848
  #
835
849
  # @author {https://aaronmallen.me Aaron Allen}
836
- # @since unreleased
850
+ # @since 0.1.0
837
851
  #
838
852
  # @api private
839
853
  #
840
854
  # @param style [String, Symbol] the style to apply
841
855
  #
842
856
  # @raise [ArgumentError] if the style is invalid
843
- # @return [self] the instance of Decorator for chaining
857
+ # @return [Decorator] a new instance of Decorator with the style applied
844
858
  # @rbs (String | Symbol style) -> self
845
859
  def apply_style(style)
846
- unless ANSI::STYLES.key?(style.to_s.downcase.to_sym)
860
+ style = style.to_s.downcase.to_sym
861
+ unless ANSI::STYLES.key?(style)
847
862
  e = ArgumentError.new("Invalid style: #{style}")
848
863
  e.set_backtrace(caller_locations(1, 1)&.map(&:to_s)) # steep:ignore UnresolvedOverloading
849
864
  raise e
850
865
  end
851
866
 
852
- @styles = @styles.push(style.to_s.downcase.to_sym).uniq
853
- self
867
+ dup.tap { |duped| duped.instance_variable_set(:@styles, (@styles + [style]).uniq) }
868
+ end
869
+
870
+ # Check if text should be decorated
871
+ #
872
+ # @author {https://aaronmallen.me Aaron Allen}
873
+ # @since 0.2.0
874
+ #
875
+ # @api private
876
+ #
877
+ # @return [Boolean] `true` if text should be decorated, `false` otherwise
878
+ # @rbs () -> bool
879
+ def should_decorate?
880
+ return false if @mode == Terminal::ColorMode::NO_COLOR
881
+ return false if @foreground.nil? && @background.nil? && @styles.empty?
882
+
883
+ true
854
884
  end
855
885
  end
856
886
  end