reinbow 1.0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 69438e1edc5e95b825cfa550e4f155c466f589e5c508044fcd0bd899909ab3c3
4
+ data.tar.gz: '08d9c79a2febc6442188448a102992245f1662bd4e1d1f8cb7c34ef3c07634e7'
5
+ SHA512:
6
+ metadata.gz: 05dac3da8bae727186d85ba4e384d419b70d117eb38bfbfd0c72dc8a19ede36d6a88984ec392433a1249e550c9d329201bf0fc540579747d13a0473f5d51c659
7
+ data.tar.gz: 487f3373a77c698899a0aa9822366fe53391ff511add8141a7b818258a055cd5bbc41522acd8d2d66ff9b22481c6c3df4a119d8e1433ef332def6c3de26b0110
data/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2024, MidAutumnMoon
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,196 @@
1
+ # Reinbow
2
+
3
+ Reinbow is a Ruby gem for colorizing printed text on terminal.
4
+
5
+ It was original a fork of the great gem [ku1ik/rainbow](https://github.com/ku1ik/rainbow), but the old codebase took way too much efforts to overhaul, so instead this project was built from ground up.
6
+
7
+ That means this project has **no relationship** with the original `rainbow` beyond inspiration, **does not** contain codes from it, and **is not** compatible with it either.
8
+
9
+ ```ruby
10
+ require "reinbow"
11
+
12
+ using Reinbow
13
+
14
+ puts "Blue cat".blue + " " \
15
+ + "jumps over".on_yellow + " " \
16
+ + "big".bold + " " \
17
+ + "lazy meatball".rgb( "#f9e02e" )
18
+ ```
19
+
20
+ ![screenshot of output of above code](./assets/readme.png)
21
+
22
+
23
+ ## Installation
24
+
25
+ Using Gemfile:
26
+
27
+ ```ruby
28
+ gem 'reinbow'
29
+ ```
30
+
31
+ Using gem CLI:
32
+
33
+ ```ruby
34
+ gem install reinbow
35
+ ```
36
+
37
+
38
+ ## Usage
39
+
40
+ The intended way to use `reinbow` is by using [*refinement*](https://docs.ruby-lang.org/en/master/Refinement.html) and calling *coloring methods* on String instances. But there's also a method for constructing the underlying `Reinbow::Painter` instances manually.
41
+
42
+ By default, coloring are enabled or disabled based on [*Standard for ANSI Colors in Terminals*](https://bixense.com/clicolors/), but methods are provided to toggle it manually.
43
+
44
+ ### Refinement
45
+
46
+ Simply do:
47
+
48
+ ```ruby
49
+ # 1) import the gem
50
+ require "reinbow"
51
+
52
+ module DesiredModule
53
+ # 2) "using" the Reinbow refinement in some module
54
+ using Reinbow
55
+
56
+ # 3) all string instances in this scope
57
+ # will have coloring methods
58
+ def colored = @message.blue
59
+ end
60
+ ```
61
+
62
+ Such way `reinbow` doesn't pollute the precious method namespace.
63
+
64
+ ### API
65
+
66
+ Reinbow by default defines several methods to colorize or style strings, which have their names matching the [*SGR*](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR) counterparts.
67
+
68
+ Full list of methods for applying terminal effects:
69
+
70
+ * `#reset`
71
+ * `#bold`
72
+ * `#dim`
73
+ * `#italic`
74
+ * `#underline`
75
+ * `#blink` *a lot of terminals ignore this for accessability reasons*
76
+ * `#invert`
77
+ * `#hide`
78
+ * `#strike`
79
+
80
+ Demo:
81
+
82
+ ```ruby
83
+ puts "strike bold and underline".strike.bold.underline
84
+ ```
85
+
86
+ ![screenshot of above code](./assets/strike-bold-underline.png)
87
+
88
+ Full list of methods for coloring foreground and background, with the background ones having `on_` prefix. Note that their *bright* variants are **not yet** supported.
89
+
90
+ * `#black`
91
+ * `#red`
92
+ * `#green`
93
+ * `#yellow`
94
+ * `#blue`
95
+ * `#magenta`
96
+ * `#cyan`
97
+ * `#white`
98
+ * `#default`
99
+ * `#on_black`
100
+ * `#on_red`
101
+ * `#on_green`
102
+ * `#on_yellow`
103
+ * `#on_blue`
104
+ * `#on_magenta`
105
+ * `#on_cyan`
106
+ * `#on_white`
107
+ * `#on_default`
108
+
109
+ Demo:
110
+
111
+ ```ruby
112
+ puts "red on white".red.on_white
113
+ ```
114
+ ![screenshot of above code](./assets/red-on-white.png)
115
+
116
+
117
+ The API also supports coloring with RGB values, and has a shorthand for using HEX string. Reinbow also comes with a full list of [*X11 Color Names*](https://en.wikipedia.org/wiki/X11_color_names). The detailed usage of both of them can be found in the *Examples* section below:
118
+
119
+ * `#rgb( Reinbow::Rgb | String )`
120
+ * `#on_rgb( Reinbow::Rgb | String )`
121
+
122
+ Demo:
123
+
124
+ ```ruby
125
+ puts "great readability" \
126
+ .rgb( X11_COLORS[:lawngreen] ) \
127
+ .on_rgb( "#faf0e6" )
128
+ ```
129
+ ![screenshot of above code](./assets/great-readability.png)
130
+
131
+
132
+ All coloring methods return `self` so that all method calls are chainable.
133
+
134
+ ```ruby
135
+ puts "well, your terminal, your land" \
136
+ .rgb( X11_COLORS[:coral] ).on_magenta \
137
+ .strike.italic.underline.bold
138
+ ```
139
+ ![screenshot of above code](./assets/what.png)
140
+
141
+
142
+ There's also a method for turning reinbow functionality on and off. But note, unlike `rainbow`, there's **no global switch** for toggling it:
143
+
144
+ * `#reinbow!( boolean )`
145
+
146
+ And also a method for querying the on-off status:
147
+
148
+ * `#reinbow?`
149
+
150
+
151
+ ### `Reinbow::Painter` Class
152
+
153
+ `T.B.D.`
154
+
155
+
156
+ ## Examples
157
+
158
+ ### RGB Colors and X11 Color Names
159
+
160
+ `Reinbow::Rgb` is a Data class for holding RGB values. It has following class methods:
161
+
162
+ * `::new( red: 0..255, green: 0..255, blue: 0..255 )`
163
+ * `::[]( 0..255, 0..255, 0..255 )`
164
+ * `::hex( String )`
165
+
166
+ Where `::[]` is a shorthand for the keyword based constructor, and `::hex` is for making `Rgb` instance from plain string HEX, which is case-insensitive and also supports 3-letter HEX.
167
+
168
+ Example:
169
+
170
+ ```ruby
171
+ Rgb.new( red: 1, green: 133, blue: 0 )
172
+ # or
173
+ Rgb[1, 133, 0]
174
+ # or
175
+ Rgb.hex( "#0b8500" )
176
+
177
+ # 3-letter HEX
178
+ Rgb.hex( "#abc" ) # => <... red=170, green=187, blue=204>
179
+ ```
180
+
181
+ `Reinbow::X11_COLORS` is a predefined hash of [*X11 Colors Names*](https://en.wikipedia.org/wiki/X11_color_names) to their corresponding RGB values. The X11 colors are not provided as coloring methods because there are whopping 130+ of them, which will pollute the instance methods.
182
+
183
+ Example:
184
+
185
+ ```ruby
186
+ X11 = Reinbow::X11_COLORS
187
+
188
+ puts "crimson line".rgb( X11[:crimson] ).underline
189
+ ```
190
+
191
+ ![screenshot of above code](./assets/crimson-line.png)
192
+
193
+
194
+ ## License
195
+
196
+ [BSD-3-Clause](./LICENSE)
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reinbow
4
+
5
+ Ansi = Data.define( :raw_code ) do
6
+ def initialize( raw_code: )
7
+ raise ArgumentError, "ANSI color code should be in range 0..9" \
8
+ unless raw_code in 0..9
9
+
10
+ super
11
+ end
12
+ end
13
+
14
+ ANSI_COLORS = {
15
+ black: 0,
16
+ red: 1,
17
+ green: 2,
18
+ yellow: 3,
19
+ blue: 4,
20
+ magenta: 5,
21
+ cyan: 6,
22
+ white: 7,
23
+ # spcial code to reset colors to their defaults
24
+ default: 9,
25
+ }.transform_values { Ansi.new( _1 ) }.freeze
26
+
27
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reinbow
4
+
5
+ # The range of "code" is deliberately not checked
6
+ # so that the user can use non common codes.
7
+ Effect = Data.define( :code )
8
+
9
+ # Explaination from Wikipedia
10
+ # https://en.wikipedia.org/wiki/ANSI_escape_code#SGR
11
+ EFFECTS = {
12
+ # Reset or normal
13
+ reset: 0,
14
+
15
+ # Bold or increased intensity
16
+ bold: 1,
17
+
18
+ # Faint, decreased intensity, or dim
19
+ dim: 2,
20
+
21
+ # Italic
22
+ italic: 3,
23
+
24
+ # Underline
25
+ underline: 4,
26
+
27
+ # Slow blink and Rapid blink
28
+ # (may have no effect due to accessibility reasons)
29
+ blink: 5,
30
+ # rapid_blink: 6,
31
+
32
+ # Reverse video or invert
33
+ invert: 7,
34
+
35
+ # Conceal or hide
36
+ # (Windows Terminal do support this effect,
37
+ # a bit suprised)
38
+ hide: 8,
39
+
40
+ # Crossed-out, or strike
41
+ strike: 9,
42
+ }.transform_values { Effect.new( _1 ) }
43
+
44
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reinbow
4
+
5
+ Rgb = Data.define( :red, :green, :blue ) do
6
+ def initialize( red:, green:, blue: )
7
+ raise ArgumentError, "RGB values should be in range 0..255" \
8
+ unless [ red, green, blue ].all? { _1 in 0..255 }
9
+
10
+ super
11
+ end
12
+
13
+ # Shortcut for initializing RGB without specifing
14
+ # keyword arguments.
15
+ def self.[]( red, green, blue )
16
+ new red:, green:, blue:
17
+ end
18
+
19
+ # Convert HEX value to RGB.
20
+ # HEX string is case insensetive and with or without the leading "#".
21
+ # See also https://github.com/devrieda/color_conversion/
22
+ def self.hex( str )
23
+ # remove "#"s
24
+ str = str.gsub( "#", "" ).downcase
25
+
26
+ # ensure it's actually a hex
27
+ raise ArgumentError, "Input contains non HEX characters" \
28
+ unless str.match?( /^[a-f0-9]+$/i )
29
+
30
+ # ensure the hex is either 6 or 3 letters
31
+ raise ArgumentError, "HEX color has wrong length that is nither 6 nor 3" \
32
+ unless str.size in 3 | 6
33
+
34
+ # padding 3 letter hex by repeating each character
35
+ str = str.chars.map { _1 * 2 }.join( nil ) \
36
+ if str.size == 3
37
+
38
+ # rubocop:disable Layout/EmptyLinesAroundArguments
39
+ self[
40
+ # "aabbcc"
41
+ # ^^
42
+ str[0, 2].hex,
43
+
44
+ # "aabbcc"
45
+ # ^^
46
+ str[2, 2].hex,
47
+
48
+ # "aabbcc"
49
+ # ^^
50
+ str[4, 2].hex,
51
+ ]
52
+ # rubocop:enable Layout/EmptyLinesAroundArguments
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./rgb.rb"
4
+
5
+ module Reinbow
6
+
7
+ # List of predefined X11 colors.
8
+ # See also https://en.wikipedia.org/wiki/X11_color_names
9
+ X11_COLORS = {
10
+
11
+ aliceblue: Rgb[240, 248, 255],
12
+ antiquewhite: Rgb[250, 235, 215],
13
+ aqua: Rgb[0, 255, 255],
14
+ aquamarine: Rgb[127, 255, 212],
15
+ azure: Rgb[240, 255, 255],
16
+
17
+ beige: Rgb[245, 245, 220],
18
+ bisque: Rgb[255, 228, 196],
19
+ black: Rgb[0, 0, 0],
20
+ blanchedalmond: Rgb[255, 235, 205],
21
+ blue: Rgb[0, 0, 255],
22
+ blueviolet: Rgb[138, 43, 226],
23
+ brown: Rgb[165, 42, 42],
24
+ burlywood: Rgb[222, 184, 135],
25
+
26
+ cadetblue: Rgb[95, 158, 160],
27
+ chartreuse: Rgb[127, 255, 0],
28
+ chocolate: Rgb[210, 105, 30],
29
+ coral: Rgb[255, 127, 80],
30
+ cornflower: Rgb[100, 149, 237],
31
+ cornsilk: Rgb[255, 248, 220],
32
+ crimson: Rgb[220, 20, 60],
33
+ cyan: Rgb[0, 255, 255],
34
+
35
+ darkblue: Rgb[0, 0, 139],
36
+ darkcyan: Rgb[0, 139, 139],
37
+ darkgoldenrod: Rgb[184, 134, 11],
38
+ darkgray: Rgb[169, 169, 169],
39
+ darkgreen: Rgb[0, 100, 0],
40
+ darkkhaki: Rgb[189, 183, 107],
41
+ darkmagenta: Rgb[139, 0, 139],
42
+ darkolivegreen: Rgb[85, 107, 47],
43
+ darkorange: Rgb[255, 140, 0],
44
+ darkorchid: Rgb[153, 50, 204],
45
+ darkred: Rgb[139, 0, 0],
46
+ darksalmon: Rgb[233, 150, 122],
47
+ darkseagreen: Rgb[143, 188, 143],
48
+ darkslateblue: Rgb[72, 61, 139],
49
+ darkslategray: Rgb[47, 79, 79],
50
+ darkturquoise: Rgb[0, 206, 209],
51
+ darkviolet: Rgb[148, 0, 211],
52
+ deeppink: Rgb[255, 20, 147],
53
+ deepskyblue: Rgb[0, 191, 255],
54
+ dimgray: Rgb[105, 105, 105],
55
+ dodgerblue: Rgb[30, 144, 255],
56
+
57
+ firebrick: Rgb[178, 34, 34],
58
+ floralwhite: Rgb[255, 250, 240],
59
+ forestgreen: Rgb[34, 139, 34],
60
+ fuchsia: Rgb[255, 0, 255],
61
+
62
+ gainsboro: Rgb[220, 220, 220],
63
+ ghostwhite: Rgb[248, 248, 255],
64
+ gold: Rgb[255, 215, 0],
65
+ goldenrod: Rgb[218, 165, 32],
66
+ gray: Rgb[190, 190, 190],
67
+ webgray: Rgb[128, 128, 128],
68
+ green: Rgb[0, 255, 0],
69
+ webgreen: Rgb[0, 128, 0],
70
+ greenyellow: Rgb[173, 255, 47],
71
+
72
+ honeydew: Rgb[240, 255, 240],
73
+ hotpink: Rgb[255, 105, 180],
74
+
75
+ indianred: Rgb[205, 92, 92],
76
+ indigo: Rgb[75, 0, 130],
77
+ ivory: Rgb[255, 255, 240],
78
+
79
+ khaki: Rgb[240, 230, 140],
80
+
81
+ lavender: Rgb[230, 230, 250],
82
+ lavenderblush: Rgb[255, 240, 245],
83
+ lawngreen: Rgb[124, 252, 0],
84
+ lemonchiffon: Rgb[255, 250, 205],
85
+ lightblue: Rgb[173, 216, 230],
86
+ lightcoral: Rgb[240, 128, 128],
87
+ lightcyan: Rgb[224, 255, 255],
88
+ lightgoldenrod: Rgb[250, 250, 210],
89
+ lightgray: Rgb[211, 211, 211],
90
+ lightgreen: Rgb[144, 238, 144],
91
+ lightpink: Rgb[255, 182, 193],
92
+ lightsalmon: Rgb[255, 160, 122],
93
+ lightseagreen: Rgb[32, 178, 170],
94
+ lightskyblue: Rgb[135, 206, 250],
95
+ lightslategray: Rgb[119, 136, 153],
96
+ lightsteelblue: Rgb[176, 196, 222],
97
+ lightyellow: Rgb[255, 255, 224],
98
+ lime: Rgb[0, 255, 0],
99
+ limegreen: Rgb[50, 205, 50],
100
+ linen: Rgb[250, 240, 230],
101
+
102
+ magenta: Rgb[255, 0, 255],
103
+ maroon: Rgb[176, 48, 96],
104
+ webmaroon: Rgb[127, 0, 0],
105
+
106
+ mediumaquamarine: Rgb[102, 205, 170],
107
+ mediumblue: Rgb[0, 0, 205],
108
+ mediumorchid: Rgb[186, 85, 211],
109
+ mediumpurple: Rgb[147, 112, 219],
110
+ mediumseagreen: Rgb[60, 179, 113],
111
+ mediumslateblue: Rgb[123, 104, 238],
112
+ mediumspringgreen: Rgb[0, 250, 154],
113
+ mediumturquoise: Rgb[72, 209, 204],
114
+ mediumvioletred: Rgb[199, 21, 133],
115
+ midnightblue: Rgb[25, 25, 112],
116
+ mintcream: Rgb[245, 255, 250],
117
+ mistyrose: Rgb[255, 228, 225],
118
+ moccasin: Rgb[255, 228, 181],
119
+
120
+ navajowhite: Rgb[255, 222, 173],
121
+ navyblue: Rgb[0, 0, 128],
122
+
123
+ oldlace: Rgb[253, 245, 230],
124
+ olive: Rgb[128, 128, 0],
125
+ olivedrab: Rgb[107, 142, 35],
126
+ orange: Rgb[255, 165, 0],
127
+ orangered: Rgb[255, 69, 0],
128
+ orchid: Rgb[218, 112, 214],
129
+
130
+ palegoldenrod: Rgb[238, 232, 170],
131
+ palegreen: Rgb[152, 251, 152],
132
+ paleturquoise: Rgb[175, 238, 238],
133
+ palevioletred: Rgb[219, 112, 147],
134
+ papayawhip: Rgb[255, 239, 213],
135
+ peachpuff: Rgb[255, 218, 185],
136
+ peru: Rgb[205, 133, 63],
137
+ pink: Rgb[255, 192, 203],
138
+ plum: Rgb[221, 160, 221],
139
+ powderblue: Rgb[176, 224, 230],
140
+ purple: Rgb[160, 32, 240],
141
+ webpurple: Rgb[127, 0, 127],
142
+
143
+ rebeccapurple: Rgb[102, 51, 153],
144
+ red: Rgb[255, 0, 0],
145
+ rosybrown: Rgb[188, 143, 143],
146
+ royalblue: Rgb[65, 105, 225],
147
+
148
+ saddlebrown: Rgb[139, 69, 19],
149
+ salmon: Rgb[250, 128, 114],
150
+ sandybrown: Rgb[244, 164, 96],
151
+ seagreen: Rgb[46, 139, 87],
152
+ seashell: Rgb[255, 245, 238],
153
+ sienna: Rgb[160, 82, 45],
154
+ silver: Rgb[192, 192, 192],
155
+ skyblue: Rgb[135, 206, 235],
156
+ slateblue: Rgb[106, 90, 205],
157
+ slategray: Rgb[112, 128, 144],
158
+ snow: Rgb[255, 250, 250],
159
+ springgreen: Rgb[0, 255, 127],
160
+ steelblue: Rgb[70, 130, 180],
161
+
162
+ tan: Rgb[210, 180, 140],
163
+ teal: Rgb[0, 128, 128],
164
+ thistle: Rgb[216, 191, 216],
165
+ tomato: Rgb[255, 99, 71],
166
+ turquoise: Rgb[64, 224, 208],
167
+
168
+ violet: Rgb[238, 130, 238],
169
+
170
+ wheat: Rgb[245, 222, 179],
171
+ white: Rgb[255, 255, 255],
172
+ whitesmoke: Rgb[245, 245, 245],
173
+
174
+ yellow: Rgb[255, 255, 0],
175
+ yellowgreen: Rgb[154, 205, 50],
176
+
177
+ }.freeze
178
+
179
+ end
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./color/effects.rb"
4
+ require_relative "./color/rgb.rb"
5
+ require_relative "./color/x11.rb"
6
+ require_relative "./color/ansi.rb"
7
+
8
+ module Reinbow
9
+
10
+ class Painter
11
+
12
+ attr_reader :raw
13
+
14
+ # Accepts all parameters that String.new accepts.
15
+ def initialize( input )
16
+ @raw = input.to_s
17
+ @sgr_stack = []
18
+
19
+ # Ref: https://bixense.com/clicolors/
20
+ @enable = if ENV.key?( "NO_COLOR" )
21
+ false
22
+ elsif ENV.key?( "CLICOLOR_FORCE" )
23
+ true
24
+ else
25
+ $stdout.tty?
26
+ end
27
+ end
28
+
29
+ def reinbow? = @enable
30
+
31
+ def reinbow!( status = true )
32
+ @enable = status
33
+ self
34
+ end
35
+
36
+
37
+ #
38
+ # Define method for various color names
39
+ #
40
+
41
+ EFFECTS.each_pair do |name, effect|
42
+ define_method( name ) do
43
+ paint!( layer: :effect, data: effect )
44
+ end
45
+ end
46
+
47
+ ANSI_COLORS.each_pair do |name, color|
48
+ # e.g. "str".blue
49
+ define_method( name ) { fg color }
50
+
51
+ # e.g. "str".on_blue
52
+ define_method( "on_#{name}" ) { bg color }
53
+ end
54
+
55
+ def rgb( input )
56
+ fg ( input in Rgb ) ? input : Rgb.hex( input.to_s )
57
+ end
58
+
59
+ def on_rgb( input )
60
+ bg ( input in Rgb ) ? input : Rgb.hex( input.to_s )
61
+ end
62
+
63
+
64
+ #
65
+ # The actual painting methods
66
+ #
67
+
68
+ def fg( color ) = paint!( layer: :fg, data: color )
69
+
70
+ def bg( color ) = paint!( layer: :bg, data: color )
71
+
72
+ def paint!( data:, layer: :fg )
73
+ raise ArgumentError, "Type #{data.class} can not be used for painting" \
74
+ unless data in Effect | Rgb | Ansi
75
+
76
+ raise ArgumentError, "layer should be one of :fg, :bg or :effect" \
77
+ unless layer in :fg | :bg | :effect
78
+
79
+ case data
80
+ in Effect
81
+ data => { code: }
82
+ @sgr_stack.push( "\e[#{code}m" )
83
+ in Ansi
84
+ data => { raw_code: }
85
+ code = raw_code + ( layer == :fg ? 30 : 40 )
86
+ @sgr_stack.push( "\e[#{code}m" )
87
+ in Rgb
88
+ data => { red:, green:, blue: }
89
+ ground = layer == :fg ? 38 : 48
90
+ @sgr_stack.push( "\e[#{ground};2;#{red};#{green};#{blue}m" )
91
+ else
92
+ raise NotImplementedError, "Can't paint #{code.class}"
93
+ end
94
+
95
+ self
96
+ end
97
+
98
+
99
+ #
100
+ # String behaviours
101
+ #
102
+
103
+ def to_s
104
+ if @enable
105
+ sgr = @sgr_stack.join( nil )
106
+ "#{sgr}#{@raw}\e[0m"
107
+ else
108
+ @raw
109
+ end
110
+ end
111
+
112
+ def +( other ) = to_s + other.to_s
113
+
114
+ end
115
+
116
+ end
data/lib/reinbow.rb ADDED
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./reinbow/painter.rb"
4
+
5
+ module Reinbow
6
+
7
+ VERSION = "1.0.0"
8
+
9
+ refine String do
10
+ Painter.instance_methods( false ).each do |name|
11
+ define_method( name ) do |*args|
12
+ Painter.new( self ).send( name, *args )
13
+ end
14
+ end
15
+ end
16
+
17
+ end
18
+
19
+
20
+ # rubocop:disable Naming/MethodName
21
+
22
+ def Reinbow( content, enable_color: true )
23
+ Reinbow::Painter.new( content ).reinbow!( enable_color )
24
+ end
25
+
26
+ # rubocop:enable Naming/MethodName
metadata ADDED
@@ -0,0 +1,51 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: reinbow
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - MidAutumnMoon
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-09-04 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Ruby gem for colorizing text in terminal
14
+ email:
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - LICENSE
20
+ - README.md
21
+ - lib/reinbow.rb
22
+ - lib/reinbow/color/ansi.rb
23
+ - lib/reinbow/color/effects.rb
24
+ - lib/reinbow/color/rgb.rb
25
+ - lib/reinbow/color/x11.rb
26
+ - lib/reinbow/painter.rb
27
+ homepage: https://github.com/MidAutumnMoon/Reinbow
28
+ licenses:
29
+ - BSD-3-Clause
30
+ metadata:
31
+ rubygems_mfa_required: 'true'
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 3.3.0
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubygems_version: 3.5.16
48
+ signing_key:
49
+ specification_version: 4
50
+ summary: Ruby gem for colorizing text in terminal
51
+ test_files: []