ex_aequo_color 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e4fb0fe9a73d4ee09f3ad5ff391b59a8b2b753c7cc62b8fd0077cf61159ee35c
4
- data.tar.gz: 5b7974683fff4c51c8afa3611de4b46fe6b23216ee174e6e875dad02810757c8
3
+ metadata.gz: d4bf66e8c2104db21c5fc0de8ddc8304ca2bf12ae15a49802f6a39ffa807491e
4
+ data.tar.gz: 6d85820b12b893b6e3b1f732aae7104fc8caee4c4929b3ea69cdfe9475274d5f
5
5
  SHA512:
6
- metadata.gz: 69980440123726d3039c73d348b626c61878c0c1cfce528c06ac3c4d2157c6046bb4d5d2db4bb35b7907c7bcc44238e8c0f701c15ba98d72155acab82458788d
7
- data.tar.gz: 05ab4096da95f7b4c3109451372e2c265f88a43e6fc69a75d6afa20fd87548b9eb54a6049ea6ecc2b91d3ebd246c62bb6313527f36e406decc68bab7c0293a2a
6
+ metadata.gz: e40bffec0f9703a82b346d3bb3ca7be75838ffecf8c9aad17027593e7d66164e5fbeef53fa5cce3d0c1086d96e33f3ff5d783a0662614b6ccca39ab38bdb9c28
7
+ data.tar.gz: 23f5f88a6eb25e1e819e9d527391cb40f670cbf8f71e7678e5729e48276d6251a470801020e8adc0e68c795be5c6502d396add9f8a87275fe484b5aa040b817d
data/README.md CHANGED
@@ -1,52 +1,369 @@
1
- [![Gem Version](https://badge.fury.io/rb/ex_aequo_color.svg)](http://badge.fury.io/rb/ex_aequo_color)
2
- [![Gem Downloads](https://img.shields.io/gem/dt/ex_aequo_color.svg)](https://rubygems.org/gems/ex_aequo_color)
1
+ [![Gem Version](https://badge.fury.io/rb/lab42_color.svg)](http://badge.fury.io/rb/lab42_color)
2
+ [![Gem Downloads](https://img.shields.io/gem/dt/lab42_color.svg)](https://rubygems.org/gems/lab42_color)
3
3
 
4
4
 
5
5
  # ExAequo::Color
6
6
 
7
- Describing how this gem works with some [speculations](https://github.com/RobertDober/speculate_about)...
7
+ ## Usage
8
8
 
9
+ ```sh
10
+ gem install ex_aequo_color
11
+ ```
12
+
13
+ With bundler
14
+
15
+ ```ruby
16
+ gem 'ex_aequo_color'
17
+ ```
18
+
19
+ In your code
20
+
21
+ ```ruby
22
+ require 'ex_aequo/color'
23
+ # or
24
+ require 'ex_aequo/color/all'
25
+ ```
9
26
 
10
- The `ExAequo::Color` module exposes three methods
27
+ ## Synopsis
28
+
29
+ The `ex_aequo_color` gem exposes the `ExAequo::Color` module.
30
+
31
+ It can be uses as a receiver or to extend a module or
32
+ to be included.
33
+
34
+ ## Speculations (literate specs)
35
+
36
+ The following specs are executed with the [speculate about](https://github.com/RobertDober/speculate_about) gem.
37
+
38
+ These specs assume the following setup code
39
+
40
+ ```ruby
41
+ require 'ex_aequo/color/all'
42
+ Color = ExAequo::Color
43
+ ```
11
44
 
12
- - `colorize`
13
- - `colorize_file`
14
- - `colorize_lines`
45
+ ## Context: #color using symbols for colors, strings for text
15
46
 
47
+ ### Context: using `Color` as receiver
16
48
 
17
- ## Context: `colorize`, returning a result
49
+ Then we can get a color code, with or without the reset
50
+ ```ruby
51
+ Color.color(:red, "hello") ==> "\e[31mhello\e[0m"
52
+ Color.color(:color253, "hello", reset: false) ==> "\e[38;5;253mhello"
53
+ ```
54
+
55
+ And we can combine different colors, fg and bg, as well as bold, dim, etc.
56
+ ```ruby
57
+ Color.color(:bg_red, :bold, :dark_sea_green, "text", reset: false) ==> "\e[41m\e[1m\e[38;2;135;175;135mtext"
58
+ ```
59
+
60
+ And we are also protected against typos
61
+ ```ruby
62
+ expect {
63
+ Color.color(:bg_red, :bold, :dark_see_green, "text", reset: false)
64
+ }.to raise_error(Color::BadColorSpecification, "bad color specification: dark_see_green")
65
+ ```
66
+
67
+ Or just the ANSI SGC code
68
+ ```ruby
69
+ Color.sgc(31) ==> "\e[31m"
70
+ ```
71
+
72
+ And we can observe that the NO_COLOR environnement variable is respected
73
+ ```ruby
74
+ original = ENV['NO_COLOR']
75
+ ENV['NO_COLOR'] = 'true'
76
+ # ENV['NO_COLOR'] is cached though
77
+ ExAequo::Color.instance_variable_set("@___no_color__", true)
78
+
79
+ Color.color(:red, "hello") ==> "hello"
80
+ Color.sgc(31) ==> ""
81
+
82
+ ensure
83
+ ENV['NO_COLOR'] = original
84
+ ExAequo::Color.instance_variable_set("@___no_color__", false)
85
+ ```
18
86
 
19
- Given we inlude `ExAequo::Color`
87
+ And we can also output directly
20
88
  ```ruby
21
- require 'ex_aequo/color'
22
- include ExAequo::Color
89
+ expect { Color.putc(:yellow, 'yellow') }.to output("\e[33myellow").to_stdout
90
+ expect { Color.putcs(:green, 'green', device: $stderr) }.to output("\e[32mgreen\e[0m\n").to_stderr
23
91
  ```
24
92
 
25
- Then we can colorize some strings
93
+ And we can override the default `reset:` argument of the two output methods
26
94
  ```ruby
27
- expect(colorize('hello')).to eq(ok: true, result: 'hello')
95
+ expect { Color.putcs(:green, 'green', device: $stderr, reset: false) }.to output("\e[32mgreen\n").to_stderr
28
96
  ```
29
97
 
30
- And we can also colorize it with colors
98
+ And we can write to any IO device
31
99
  ```ruby
32
- expect(colorize('<bold>world$!')).to eq(ok: true, result: "\e[1mworld\e[0m!")
100
+ out = StringIO.new
101
+ Color.putc(:magenta, 'magenta', device: out, reset: true)
102
+ out.rewind
103
+ expect(out.string).to eq("\e[35mmagenta\e[0m")
33
104
  ```
34
105
 
35
- And of course we obey the POSIX rule for the `$NO_COLOR` environment variable
106
+ ### Context: Including `Color`
107
+
108
+ As `Color` is a module we can just include it
109
+ Given a class including `Color`
110
+ ```ruby
111
+ class IncludingColor
112
+ include Color
113
+ end
114
+
115
+ let(:colorizer) { IncludingColor.new }
116
+ ```
117
+
118
+ Then we can use the included methods
119
+ ```ruby
120
+ colorizer.color(:aquamarine1, "hello") ==> "\e[38;2;95;255;215mhello\e[0m"
121
+ colorizer.color(:light_coral, "hello", reset: false) ==> "\e[38;2;255;135;135mhello"
122
+ ```
123
+
124
+ And there are some ways to reset
125
+ ```ruby
126
+ colorizer.color(:fuchsia, "hello", reset:true) ==> "\e[38;2;255;0;255mhello\e[0m"
127
+ # And being lazy ;) instead of reset: true
128
+ colorizer.color(:fuchsia, "hello", :reset) ==> "\e[38;2;255;0;255mhello\e[0m"
129
+ colorizer.color(:fuchsia, "hello", 0) ==> "\e[38;2;255;0;255mhello\e[0m"
130
+
131
+ ```
132
+ But we need to be carful with errors
133
+ ```ruby
134
+ expect { colorizer.color(42) }
135
+ .to raise_error(
136
+ ArgumentError, "need a colorspec by symbol, a string or 0 (short for :reset), but got 42"
137
+ )
138
+ ```
139
+
140
+ ### Context: Selective Inclusion
141
+
142
+ Given two classes with different selective inclusion
143
+ ```ruby
144
+ class OnlyOutput
145
+ include Color::Output
146
+ end
147
+
148
+ class OnlyEncode
149
+ include Color::Encode
150
+ end
151
+
152
+ let(:oo) { OnlyOutput.new }
153
+ let(:oe) { OnlyEncode.new }
154
+ ```
155
+
156
+ Then we can use the representivly included methods
157
+ ```ruby
158
+ expect { oo.putc('something') }.to output('something').to_stdout
159
+ expect { oo.putcs(:red, 'red', device: $stderr) }.to output("\e[31mred\e[0m\n").to_stderr
160
+ ```
161
+
162
+ And also
163
+ ```ruby
164
+ expect(oe.color(:dim)).to eq("\e[2m\e[0m")
165
+ expect(oe.sgc(45)).to eq("\e[45m")
166
+ ```
167
+
168
+ But we will see that
169
+ ```ruby
170
+ expect {
171
+ oo.color(:bold)
172
+ }.to raise_error(NoMethodError, "undefined method 'color' for an instance of OnlyOutput")
173
+ expect {
174
+ oo.sgc(0)
175
+ }.to raise_error(NoMethodError, "undefined method 'sgc' for an instance of OnlyOutput")
176
+ ```
177
+
178
+ And about the same for `OnlyEncode` instances
179
+ ```ruby
180
+ # Yeah this might need a name change because of possible interfearence with the private method
181
+ expect {
182
+ oe.putc("hello")
183
+ }.to raise_error(NoMethodError, "private method 'putc' called for an instance of OnlyEncode")
184
+ expect {
185
+ oe.putcs("hello", reset: false)
186
+ }.to raise_error(NoMethodError, "undefined method 'putcs' for an instance of OnlyEncode")
187
+ ```
188
+
189
+ ### Context: But all I need is `#putcs`
190
+
191
+ Well that is easy, use `Forwardable`
192
+
193
+ Given a class only using `#putcs`
36
194
  ```ruby
37
- expect(ENV).to receive(:fetch).with('NO_COLOR', false).and_return(true)
38
- expect(colorize('<bold>world$!')).to eq(ok: true, result: "world!")
39
-
195
+ class OnlyPutcs
196
+ extend Forwardable
197
+ def_delegators Color::Output, :putcs
198
+ end
199
+
200
+ let(:op) { OnlyPutcs.new }
40
201
  ```
41
202
 
42
- ## Context: `colorize_lines`
203
+ Then we can call `#putcs` from an instance, of course
204
+ ```ruby
205
+ expect {
206
+ op.putcs(:bold, "Greetings", reset: false)
207
+ }.to output("\e[1mGreetings\n").to_stdout
208
+
209
+ ```
43
210
 
44
- Given that you might not just get a result but just a colorized string
45
- Then you can do the following
211
+ But we cannot use `#putc`
46
212
  ```ruby
213
+ # Yeah this might need a name change because of possible interfearence with the private method
214
+ expect {
215
+ op.putc("hello")
216
+ }.to raise_error(NoMethodError, "private method 'putc' called for an instance of OnlyPutcs")
47
217
 
48
218
  ```
49
219
 
220
+ ## Context: #colorize parsing text to colorize it
221
+
222
+ ### Context: using the `Color` module again
223
+
224
+ Then we can parse and colorize as follows
225
+ ```ruby
226
+ Color.colorize("<red>IMPORTANT").to_h ==> ok: true, result: "\e[31mIMPORTANT"
227
+ Color.colorize("<yellow,bold>WARNING").to_h ==> ok: true, result: "\e[33m\e[1mWARNING"
228
+ Color.colorize!("<aqua>IMPORTANT", reset: true) ==> "\e[38;2;0;255;255mIMPORTANT\e[0m"
229
+ ```
230
+ And errors in syntax are reported
231
+ ```ruby
232
+ Color.colorize("<redIMPORTANT").to_h ==> ok: false, error: "Incomplete Color Spec redIMPORTANT"
233
+ ```
234
+ And `$NO_COLOR` is again obeyed
235
+ ```ruby
236
+ original = ENV['NO_COLOR']
237
+ ENV['NO_COLOR'] = 'true'
238
+ # ENV['NO_COLOR'] is cached though
239
+ ExAequo::Color.instance_variable_set("@___no_color__", true)
240
+
241
+ Color.colorize("<red,bold>IMPORTANT").to_h ==> ok: true, result: "IMPORTANT"
242
+ Color.colorize!("<aqua>IMPORTANT", reset: true) ==> "IMPORTANT"
243
+
244
+ ensure
245
+ ENV['NO_COLOR'] = original
246
+ ExAequo::Color.instance_variable_set("@___no_color__", false)
247
+ ```
248
+ But even with `$NO_COLOR` errors are reported or raised
249
+ ```ruby
250
+ original = ENV['NO_COLOR']
251
+ ENV['NO_COLOR'] = 'true'
252
+ # ENV['NO_COLOR'] is cached though
253
+ ExAequo::Color.instance_variable_set("@___no_color__", true)
254
+
255
+ Color.colorize("<red,boldIMPORTANT").to_h ==> ok: false, error: "Incomplete Color Spec boldIMPORTANT"
256
+
257
+ expect {
258
+ Color.colorize!("<red")
259
+ }.to raise_error(
260
+ Color::SyntaxError, "Incomplete Color Spec red"
261
+ )
262
+
263
+ ensure
264
+ ENV['NO_COLOR'] = original
265
+ ExAequo::Color.instance_variable_set("@___no_color__", false)
266
+
267
+ ```
268
+
269
+ ## Context: Extending the `String` class
270
+
271
+ Given we require that feature
272
+ ```ruby
273
+ require 'ex_aequo/color/string'
274
+ ```
275
+
276
+ Then we can call `colored` on a `String` instance
277
+ ```ruby
278
+ "hello".colored(:orange) ==> "\e[38;2;255;128;0mhello\e[0m"
279
+ # N.B. We have reset defaulting to true here
280
+ "hello".colored(:orange, reset: false) ==> "\e[38;2;255;128;0mhello"
281
+ ```
282
+
283
+ ## Context: Printing with colors
284
+
285
+ Given we intercept output
286
+ ```ruby
287
+ before do
288
+ expect(device).to receive(:puts).with(text)
289
+ end
290
+ ```
291
+
292
+ ### Context: We can print to $stderr with `#pcolored` by default
293
+
294
+ Given the following setup
295
+ ```ruby
296
+ let(:device) { $stderr }
297
+ let(:text) { "\e[38;2;255;135;175mwhat a color?\e[0m" }
298
+ ```
299
+ Then we can also print to a device
300
+ ```ruby
301
+ Color.pcolored(:pale_violet_red1, "what a color?")
302
+ ```
303
+
304
+ ### Context: We can print to any object responding to `:puts` with `#pcolored`
305
+
306
+ Given the following setup
307
+ ```ruby
308
+ let(:device) { $stdout }
309
+ let(:text) { "\e[38;2;255;135;175mwhat a color?" }
310
+ ```
311
+ Then we can also print to a device
312
+ ```ruby
313
+ Color.pcolored(:pale_violet_red1, "what a color?", device:, reset: false)
314
+ ```
315
+
316
+ ## Context: Printing lines, defaults to `$stdout`
317
+
318
+ Then we can do the following
319
+ ```ruby
320
+ expect($stdout)
321
+ .to receive(:puts).with("\e[31ma").ordered
322
+ expect($stdout)
323
+ .to receive(:puts).with("\e[34mb").ordered
324
+
325
+ Color.colorize_lines("<red>a\n<blue>b")
326
+ ```
327
+
328
+ But we will be warned about errors
329
+ ```ruby
330
+ expect($stderr).to receive(:puts).with("ERROR in line 1 ** Incomplete Color Spec re **")
331
+
332
+ Color.colorize_lines("<re")
333
+ ```
334
+
335
+ ## Context: Printing files, defaults to `$stdout`
336
+
337
+ Given a file
338
+ ```ruby
339
+ lines = [
340
+ "<bold>Hello",
341
+ "and <magenta,dim>World"
342
+ ]
343
+
344
+ require 'fileutils'
345
+ FileUtils.mkdir_p 'tmp'
346
+ file = File.join('tmp', SecureRandom.alphanumeric)
347
+ File.write(file, lines.join("\n"))
348
+ ```
349
+
350
+ Then we can do the following
351
+ ```ruby
352
+ expect($stdout).to receive(:puts).with("\e[1mHello").ordered
353
+ expect($stdout).to receive(:puts).with("and \e[35m\e[2mWorld").ordered
354
+
355
+ Color.colorize_file(file)
356
+ ```
357
+
358
+ Or we can write to a different device
359
+ ```ruby
360
+ output = StringIO.new
361
+ Color.colorize_file(file, device: output, reset: true)
362
+ output.rewind
363
+ expect(output.read).to eq("\e[1mHello\e[0m\nand \e[35m\e[2mWorld\e[0m\n")
364
+ ```
365
+
366
+
50
367
  ## Author
51
368
 
52
369
  Copyright 2025 Robert Dober robert.dober@gmail.com
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ex_aequo/base/kernel'
4
+ require_relative '../color'
5
+ require_relative '../color/colorizer'
6
+ require_relative '../color/string'
7
+
8
+ Color = ExAequo::Color
9
+ Colorizer = Color::Colorizer
10
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -0,0 +1,239 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ExAequo
4
+ module Color
5
+
6
+ EIGHT_BIT_COLORS = {
7
+ bg_black: 40,
8
+ bg_red: 41,
9
+ bg_green: 42,
10
+ bg_yellow: 43,
11
+ bg_blue: 44,
12
+ bg_magenta: 45,
13
+ bg_cyan: 46,
14
+ bg_white: 47,
15
+ black: 30,
16
+ blue: 34,
17
+ bold: 1,
18
+ cyan: 36,
19
+ dim: 2,
20
+ green: 32,
21
+ italic: 3,
22
+ magenta: 35,
23
+ red: 31,
24
+ reset: 0,
25
+ uline: 4,
26
+ underline: 4,
27
+ white: 37,
28
+ yellow: 33
29
+ }
30
+
31
+ RGB_COLORS = {
32
+ aqua: [0, 255, 255],
33
+ aquamarine1: [95, 255, 215],
34
+ aquamarine3: [95, 215, 175],
35
+ azure1: [240, 255, 255],
36
+ blue1: [0, 0, 255],
37
+ blue3: [0, 0, 175],
38
+ blue_violet: [95, 0, 255],
39
+ cadet_blue: [95, 175, 135],
40
+ chartreuse1: [135, 255, 0],
41
+ chartreuse2: [95, 255, 0],
42
+ chartreuse3: [95, 175, 0],
43
+ chartreuse4: [95, 135, 0],
44
+ cornflower_blue: [95, 135, 255],
45
+ cornsilk1: [255, 255, 215],
46
+ cyan1: [0, 255, 255],
47
+ cyan2: [0, 255, 215],
48
+ cyan3: [0, 215, 175],
49
+ dark_blue: [0, 0, 135],
50
+ dark_cyan: [0, 175, 135],
51
+ dark_goldenrod: [175, 135, 0],
52
+ dark_green: [0, 95, 0],
53
+ dark_khaki: [175, 175, 95],
54
+ dark_magenta: [135, 0, 135],
55
+ dark_olive_green1: [215, 255, 95],
56
+ dark_olive_green2: [175, 255, 95],
57
+ dark_olive_green3: [135, 175, 95],
58
+ dark_orange3: [175, 95, 0],
59
+ dark_orange: [255, 135, 0],
60
+ dark_red: [95, 0, 0],
61
+ dark_sea_green1: [175, 255, 215],
62
+ dark_sea_green2: [175, 215, 175],
63
+ dark_sea_green3: [135, 215, 175],
64
+ dark_sea_green4: [95, 135, 95],
65
+ dark_sea_green: [135, 175, 135],
66
+ dark_slate_gray1: [135, 255, 255],
67
+ dark_slate_gray2: [95, 255, 255],
68
+ dark_slate_gray3: [135, 215, 215],
69
+ dark_turquoise: [0, 215, 215],
70
+ dark_violet: [135, 0, 215],
71
+ deep_pink1: [255, 0, 135],
72
+ deep_pink2: [255, 0, 95],
73
+ deep_pink3: [215, 0, 95],
74
+ deep_pink4: [95, 0, 95],
75
+ deep_sky_blue1: [0, 175, 255],
76
+ deep_sky_blue2: [0, 175, 215],
77
+ deep_sky_blue3: [0, 135, 175],
78
+ deep_sky_blue4: [0, 95, 95],
79
+ dodger_blue1: [0, 135, 255],
80
+ dodger_blue2: [0, 95, 255],
81
+ dodger_blue3: [0, 95, 215],
82
+ fuchsia: [255, 0, 255],
83
+ gold1: [255, 215, 0],
84
+ gold3: [175, 175, 0],
85
+ green1: [0, 255, 0],
86
+ green3: [0, 175, 0],
87
+ green4: [0, 135, 0],
88
+ green_yellow: [175, 255, 0],
89
+ grey0: [0, 0, 0],
90
+ grey100: [255, 255, 255],
91
+ grey11: [28, 28, 28],
92
+ grey15: [38, 38, 38],
93
+ grey19: [48, 48, 48],
94
+ grey23: [58, 58, 58],
95
+ grey27: [68, 68, 68],
96
+ grey30: [78, 78, 78],
97
+ grey35: [88, 88, 88],
98
+ grey37: [95, 95, 95],
99
+ grey39: [98, 98, 98],
100
+ grey3: [8, 8, 8],
101
+ grey42: [108, 108, 108],
102
+ grey46: [118, 118, 118],
103
+ grey50: [128, 128, 128],
104
+ grey53: [135, 135, 135],
105
+ grey54: [138, 138, 138],
106
+ grey58: [148, 148, 148],
107
+ grey62: [158, 158, 158],
108
+ grey63: [175, 135, 175],
109
+ grey66: [168, 168, 168],
110
+ grey69: [175, 175, 175],
111
+ grey70: [178, 178, 178],
112
+ grey74: [188, 188, 188],
113
+ grey78: [198, 198, 198],
114
+ grey7: [18, 18, 18],
115
+ grey82: [208, 208, 208],
116
+ grey84: [215, 215, 215],
117
+ grey85: [218, 218, 218],
118
+ grey89: [228, 228, 228],
119
+ grey93: [238, 238, 238],
120
+ grey: [128, 128, 128],
121
+ honeydew2: [215, 255, 215],
122
+ hot_pink2: [215, 95, 175],
123
+ hot_pink3: [175, 95, 135],
124
+ hot_pink: [255, 95, 175],
125
+ indian_red1: [255, 95, 95],
126
+ indian_red: [175, 95, 95],
127
+ khaki1: [255, 255, 135],
128
+ khaki3: [215, 215, 95],
129
+ light_coral: [255, 135, 135],
130
+ light_cyan1: [215, 255, 255],
131
+ light_cyan3: [175, 215, 215],
132
+ light_goldenrod1: [255, 255, 95],
133
+ light_goldenrod2: [215, 215, 135],
134
+ light_goldenrod3: [215, 175, 95],
135
+ light_green: [135, 255, 95],
136
+ light_pink1: [255, 175, 175],
137
+ light_pink3: [215, 135, 135],
138
+ light_pink4: [135, 95, 95],
139
+ light_salmon1: [255, 175, 135],
140
+ light_salmon3: [175, 135, 95],
141
+ light_sea_green: [0, 175, 175],
142
+ light_sky_blue1: [175, 215, 255],
143
+ light_sky_blue3: [135, 175, 175],
144
+ light_slate_blue: [135, 135, 255],
145
+ light_slate_grey: [135, 135, 175],
146
+ light_steel_blue1: [215, 215, 255],
147
+ light_steel_blue3: [175, 175, 215],
148
+ light_steel_blue: [175, 175, 255],
149
+ light_yellow3: [215, 215, 175],
150
+ lime: [0, 255, 0],
151
+ magenta1: [255, 0, 255],
152
+ magenta2: [215, 0, 255],
153
+ magenta3: [175, 0, 175],
154
+ maroon: [128, 0, 0],
155
+ medium_orchid1: [215, 95, 255],
156
+ medium_orchid3: [175, 95, 175],
157
+ medium_orchid: [175, 95, 215],
158
+ medium_purple1: [175, 135, 255],
159
+ medium_purple2: [175, 95, 255],
160
+ medium_purple3: [135, 95, 175],
161
+ medium_purple4: [95, 95, 135],
162
+ medium_purple: [135, 135, 215],
163
+ medium_spring_green: [0, 255, 175],
164
+ medium_turquoise: [95, 215, 215],
165
+ medium_violet_red: [175, 0, 135],
166
+ misty_rose1: [255, 215, 215],
167
+ misty_rose3: [215, 175, 175],
168
+ navajo_white1: [255, 215, 175],
169
+ navajo_white3: [175, 175, 135],
170
+ navy: [0, 0, 128],
171
+ navy_blue: [0, 0, 95],
172
+ olive: [128, 128, 0],
173
+ orange: [255, 128, 0],
174
+ orange1: [255, 175, 0],
175
+ orange3: [215, 135, 0],
176
+ orange4: [95, 95, 0],
177
+ orange_red1: [255, 95, 0],
178
+ orchid1: [255, 135, 255],
179
+ orchid2: [255, 135, 215],
180
+ orchid: [215, 95, 215],
181
+ pale_green1: [135, 255, 175],
182
+ pale_green3: [95, 215, 95],
183
+ pale_turquoise1: [175, 255, 255],
184
+ pale_turquoise4: [95, 135, 135],
185
+ pale_violet_red1: [255, 135, 175],
186
+ pink1: [255, 175, 215],
187
+ pink3: [215, 135, 175],
188
+ plum1: [255, 175, 255],
189
+ plum2: [215, 175, 255],
190
+ plum3: [215, 135, 215],
191
+ plum4: [135, 95, 135],
192
+ purple3: [95, 0, 215],
193
+ purple4: [95, 0, 135],
194
+ purple: [128, 0, 128],
195
+ red1: [255, 0, 0],
196
+ red3: [175, 0, 0],
197
+ rosy_brown: [175, 135, 135],
198
+ royal_blue1: [95, 95, 255],
199
+ salmon1: [255, 135, 95],
200
+ sandy_brown: [255, 175, 95],
201
+ sea_green1: [95, 255, 135],
202
+ sea_green2: [95, 255, 95],
203
+ sea_green3: [95, 215, 135],
204
+ silver: [192, 192, 192],
205
+ sky_blue1: [135, 215, 255],
206
+ sky_blue2: [135, 175, 255],
207
+ sky_blue3: [95, 175, 215],
208
+ slate_blue1: [135, 95, 255],
209
+ slate_blue3: [95, 95, 175],
210
+ spring_green1: [0, 255, 135],
211
+ spring_green2: [0, 215, 135],
212
+ spring_green3: [0, 175, 95],
213
+ spring_green4: [0, 135, 95],
214
+ steel_blue1: [95, 175, 255],
215
+ steel_blue3: [95, 135, 215],
216
+ steel_blue: [95, 135, 175],
217
+ tan: [215, 175, 135],
218
+ teal: [0, 128, 128],
219
+ thistle1: [255, 215, 255],
220
+ thistle3: [215, 175, 215],
221
+ turquoise2: [0, 215, 255],
222
+ turquoise4: [0, 135, 135],
223
+ violet: [215, 135, 255],
224
+ wheat1: [255, 255, 175],
225
+ wheat4: [135, 135, 95],
226
+ yellow1: [255, 255, 0],
227
+ yellow2: [215, 255, 0],
228
+ yellow3: [175, 215, 0],
229
+ yellow4: [135, 135, 0]
230
+ }
231
+
232
+ ANSI_COLOR_NAMES =
233
+ (0..255)
234
+ .map {["color#{it}".to_sym, [:color, it]]}
235
+ .to_h
236
+ .merge(EIGHT_BIT_COLORS, RGB_COLORS)
237
+ end
238
+ end
239
+ # SPDX-License-Identifier: AGPL-3.0-or-later
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ require_relative 'ansi_color_names'
5
+ module ExAequo
6
+ module Color
7
+ module ColorDefinitions extend self
8
+ CSI = "\e["
9
+
10
+ def get(color, no_color)
11
+ color = find_color(color)
12
+ if color
13
+ return '' if no_color
14
+ color
15
+ end
16
+ end
17
+
18
+ def sgc(value) ="#{CSI}#{value}m"
19
+
20
+ private
21
+ def find_color(color)
22
+ case ANSI_COLOR_NAMES.fetch(color.to_sym, nil)
23
+ in [_, _, _] => rgb
24
+ sgc("38;2;#{rgb.join(";")}")
25
+ in [:color, col]
26
+ sgc("38;5;#{col}")
27
+ in value unless value.nil?
28
+ sgc(value)
29
+ else
30
+ nil
31
+ # raise BadColorSpecification, "bad color specification: #{color}"
32
+ end
33
+ end
34
+ # From ex_aequo/base
35
+ # def find_color(color)
36
+ # case ANSI_COLORS.fetch(color.to_sym, nil)
37
+ # in [r, g, b]
38
+ # "\e[38;2;#{r};#{g};#{b}m"
39
+ # in [:color, col]
40
+ # "\e[35;5;#{col}m"
41
+ # in nil
42
+ # nil
43
+ # in value
44
+ # "\e[#{value}m"
45
+ # end
46
+ end
47
+ end
48
+ end
49
+ # SPDX-License-Identifier: AGPL-3.0-or-later