sai 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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