chromate 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ed103af7c44122bf148349eb167f49fb28f0e0ef
4
+ data.tar.gz: 6f4eced71e79c497aca419d5a3586456e16c8fb1
5
+ SHA512:
6
+ metadata.gz: 27925f1b9e358d43d8d7868a28cb0514c5e4b0c658f85359b1460ce702eafe7ac2e6a7c776d92667d4d723bf9d8b70d043e270600035c8e6e14d5d3fa0c28073
7
+ data.tar.gz: 4871e670910a5b0ec06fa2b2459428eea5f98e9737806eb79927887f7f3670b7593ae9f6532fa1a1f1639333773dddaf671461157717cff90bcfd65c460b3e11
@@ -0,0 +1,12 @@
1
+ require 'chromate/version'
2
+ require 'chromate/cache'
3
+ require 'chromate/rgb'
4
+ require 'chromate/hex'
5
+ require 'chromate/lab'
6
+ require 'chromate/effect'
7
+ require 'chromate/color'
8
+ require 'chromate/effect_set'
9
+ require 'chromate/effects'
10
+ require 'chromate/formattable'
11
+
12
+ require 'chromate/core_ext/string'
@@ -0,0 +1,6 @@
1
+ module Chromate
2
+
3
+ # A cache mapping RGB arrays to their Color representations
4
+ CACHE = {}
5
+
6
+ end
@@ -0,0 +1,368 @@
1
+ module Chromate
2
+
3
+ #
4
+ # The `Color` class is used to represent a terminal color in the range 0..255.
5
+ # Colors are powerful tools, and have a multitude of convenience methods to
6
+ # make working with them easier.
7
+ #
8
+ # Color Models
9
+ # ============
10
+ # All colors have a so-called 'color model' (accessible via the `color_model`
11
+ # attribute). The color model of a color determines how it will be escaped.
12
+ # The following color models are possible:
13
+ #
14
+ # - Colors in the range 0..7 have a color model of 8. These colors are
15
+ # always escaped as single-integer values in the ranges 30..37 and
16
+ # 40..47 for foregrounds and backgrounds, respectively.
17
+ # - Colors in the range 8..15 have a color model of 16. These colors
18
+ # can be escaped in two ways, with single-integer values in the
19
+ # ranges 90..97 and 100..107, for foreground and background,
20
+ # respectively, or with additional bold sequences. Which route is
21
+ # taken depends on the compliancy setting; single-integer values are
22
+ # non-compliant, while bold sequences are. The compliancy setting
23
+ # may be specified in three ways, each overriding the last: via the
24
+ # class attribute on `Color`, via the instance attribute by the same
25
+ # name, and in the method call as a second (optional parameter).
26
+ # The default at all levels is non-compliancy.
27
+ # - Colors in the range 16..255 have a color model of 256. These
28
+ # colors are always escaped as xterm-256 escape sequences of the
29
+ # form 38;5;x for foreground and 48;5;x for background, where x is
30
+ # the actual color value.
31
+ #
32
+ # Converting from Other Formats
33
+ # =============================
34
+ # The `Color` class features a powerful approximation mechanism, allowing the
35
+ # creation of colors from arbitrary RGB values, which may be specified either
36
+ # in RGB using {::from_rgb} or in hex using {::from_hex}. When either of these
37
+ # methods are used, the closest matching terminal color code will be found
38
+ # automatically, using the CIE 1976 delta-E algorithm. This operation is quite
39
+ # a bit slower compared to using exact color values, but it must be done only
40
+ # once, as all values are cached after first use and kept until the end of
41
+ # program execution.
42
+ #
43
+ # Making New Colors
44
+ # =================
45
+ # If you __really__ want to make a new color, you may do so by calling the
46
+ # provided constructor. However, this is wasteful -- there is, after all, a
47
+ # finite set of possible colors. Moreover, all of these colors already exist
48
+ # as members of the `COLORS` constant. That's all well and good if you have
49
+ # the raw color code, which can be used as an index for the `COLORS` array,
50
+ # but what if you don't? Well, then {::[]} is your new best friend! This
51
+ # method accepts the full range of color representations, including raw color
52
+ # codes, names, hex strings, and RGB values. The following example showcases
53
+ # all of the various types that {::[]} accepts:
54
+ #
55
+ # ```ruby
56
+ # # The following all return the 'black' color
57
+ # Color[0]
58
+ # Color['black']
59
+ # Color['#000000']
60
+ # Color[:black]
61
+ # Color[[0, 0, 0]]
62
+ # Color[0, 0, 0]
63
+ #
64
+ # # Malformed inputs
65
+ # Color[-1] # => ArgumentError: bad color code: -1
66
+ # Color[256] # => ArgumentError: bad color code: 256
67
+ # Color['foo'] # => nil
68
+ # Color['#'] # => ArgumentError: invalid hex string: #
69
+ # Color[:foo] # => nil
70
+ # ```
71
+ #
72
+ # Note that when getting a color from a name, `nil` will be returned if no
73
+ # color with that name exists, rather than throwing an error.
74
+ #
75
+ class Color < Effect
76
+
77
+ # @return [Integer] the color model of the color (either 8, 16, or 256)
78
+ attr_reader :color_model
79
+
80
+ # @return [Boolean] the default compliancy setting for {#to_fg} and {#to_bg}
81
+ attr_accessor :compliant
82
+
83
+ class << self
84
+ # @return [Boolean] the global default compliancy setting
85
+ attr_accessor :compliant
86
+
87
+ def compliant=(what)
88
+ @compliant = what
89
+ COLORS.each { |c| c.compliant = what }
90
+ end
91
+ end
92
+ @compliant = false
93
+
94
+ #
95
+ # Create a new Color object representing the specified color code. The color
96
+ # model will be inferred automatically based on the range of `value` (8 if
97
+ # it's less than 8, 16 if it's less than 16, and 256 otherwise).
98
+ # @param value [Numeric] the xterm color code of the new color
99
+ #
100
+ # @return [Color]
101
+ def initialize(value, compliant = Color.compliant)
102
+ if COLOR_NAMES.key?(value)
103
+ super(COLOR_NAMES[value])
104
+ else
105
+ super(value)
106
+ end
107
+
108
+ @compliant = compliant
109
+ @escape = :fg
110
+ @color_model = if @value < 8
111
+ 8
112
+ elsif @value < 16
113
+ 16
114
+ else
115
+ 256
116
+ end
117
+ end
118
+
119
+ #
120
+ # Get an existing Color object representing the specified color code, hex
121
+ # value, color name, or RGB array.
122
+ # @param value [String,Symbol,Array]
123
+ #
124
+ # @return [Color]
125
+ def self.[](value, g = nil, b = nil)
126
+ case value
127
+ when Fixnum
128
+ if value > 255 or value < 0
129
+ raise ArgumentError, "bad color code: #{value}"
130
+ else
131
+ COLORS[value]
132
+ end
133
+ when String
134
+ if value[0] == '#'
135
+ Color.from_hex(value)
136
+ elsif COLOR_NAMES.key?(value.intern)
137
+ COLORS[COLOR_NAMES[value.intern]]
138
+ else
139
+ nil
140
+ end
141
+ when Symbol
142
+ if COLOR_NAMES.key?(value)
143
+ COLORS[COLOR_NAMES[value]]
144
+ else
145
+ nil
146
+ end
147
+ when Array
148
+ Color.from_rgb(*value)
149
+ else
150
+ if g.nil? and b.nil?
151
+ raise TypeError, "don't know what to do with a #{value.class}"
152
+ else
153
+ Color.from_rgb(value, g, b)
154
+ end
155
+ end
156
+ end
157
+
158
+ #
159
+ # Get a Color object representing the specified hex string.
160
+ # @param hex [String] a string of the form #XXXXXX
161
+ #
162
+ # @return [Color]
163
+ def self.from_hex(hex)
164
+ if Hex::PATTERN =~ hex
165
+ Color.from_rgb(*hex.scan(Hex::BYTE).map { |b| b.to_i(16) })
166
+ else
167
+ raise ArgumentError, "invalid hex string: #{hex}"
168
+ end
169
+ end
170
+
171
+ #
172
+ # Get a Color object representing the specified color in RGB space.
173
+ # @note The `g` and `b` arguments default to the value passed in for `r`, so
174
+ # that if you have a monochromatic color (e.g., r, g, and b are the same),
175
+ # you may pass a single value.
176
+ # @param r [Integer] the red component
177
+ # @param g [Integer] the green component
178
+ # @param b [Integer] the blue component
179
+ #
180
+ # @example Getting a monochromatic color
181
+ # Color.from_rgb(0) # <=> Color.from_rgb(0, 0, 0)
182
+ #
183
+ # @return [Color]
184
+ def self.from_rgb(r, g = r, b = r)
185
+ ary = [r, g, b]
186
+ if RGB::COLORS.include?(ary)
187
+ COLORS[RGB::COLORS.index(ary)]
188
+ elsif CACHE.include?(ary)
189
+ CACHE[ary]
190
+ else
191
+ lab = RGB.to_lab(ary)
192
+ code = Lab::COLORS.index(Lab::COLORS.sort do |lab1, lab2|
193
+ Lab.difference(lab, lab1) <=> Lab.difference(lab, lab2)
194
+ end.first)
195
+ CACHE[ary] = COLORS[code]
196
+ COLORS[code]
197
+ end
198
+ end
199
+
200
+ #
201
+ # Is this color supported by the host environment?
202
+ #
203
+ # @return [Boolean]
204
+ def supported?
205
+ SUPPORTED_COLORS.include?(self)
206
+ end
207
+
208
+ #
209
+ # Is this color greyscale?
210
+ #
211
+ # @return [Boolean]
212
+ def greyscale?
213
+ GREYSCALE_COLORS.include?(self)
214
+ end
215
+
216
+ #
217
+ # Escape as a foreground SGR escape sequence.
218
+ # @param compliant [Boolean] whether to use standards-compliant bold
219
+ # sequences or the non-standard 90-97 range
220
+ #
221
+ # @return [String] an escape sequence setting the foreground to the color
222
+ def to_fg(compliant = @compliant)
223
+ case @color_model
224
+ when 8
225
+ "\e[#{30 + @value}m"
226
+ when 16
227
+ if compliant
228
+ "\e[#{30 + @value - 8};1m"
229
+ else
230
+ "\e[#{90 + @value - 8}m"
231
+ end
232
+ when 256
233
+ "\e[38;5;#{@value}m"
234
+ end
235
+ end
236
+
237
+ #
238
+ # Convert to a Color that escapes to a foreground by default.
239
+ #
240
+ # @return [Color]
241
+ def as_fg
242
+ @escape = :fg
243
+ self
244
+ end
245
+
246
+ #
247
+ # Does this color represent a foreground?
248
+ #
249
+ # @return [Boolean]
250
+ def fg?
251
+ @escape == :fg
252
+ end
253
+
254
+ #
255
+ # Escape as a background SGR escape sequence.
256
+ # @param compliant [Boolean] whether to use standards-compliant bold
257
+ # sequences or the non-standard 100-107 range
258
+ #
259
+ # @return [String] an escape sequence setting the foreground to the color
260
+ def to_bg(compliant = @compliant)
261
+ case @color_model
262
+ when 8
263
+ "\e[#{40 + @value}m"
264
+ when 16
265
+ if compliant
266
+ "\e[#{40 + @value - 8};1m"
267
+ else
268
+ "\e[#{100 + @value - 8}m"
269
+ end
270
+ when 256
271
+ "\e[48;5;#{@value}m"
272
+ end
273
+ end
274
+
275
+ #
276
+ # Convert to a Color that escapes to a background by default.
277
+ #
278
+ # @return [Color]
279
+ def as_bg
280
+ @escape = :bg
281
+ self
282
+ end
283
+
284
+ #
285
+ # Does this color represent a background?
286
+ #
287
+ # @return [Boolean]
288
+ def bg?
289
+ @escape == :bg
290
+ end
291
+
292
+ #
293
+ # Escape as an SGR escape sequence.
294
+ #
295
+ # @return [String] an escape sequence of the form "\e[1;2;3;...m"
296
+ def escape
297
+ case @escape
298
+ when :fg
299
+ to_fg
300
+ when :bg
301
+ to_bg
302
+ end
303
+ end
304
+
305
+ #
306
+ # Get the name of the color, if it exists.
307
+ #
308
+ # @return [Symbol]
309
+ def name
310
+ if COLOR_NAMES.value?(@value)
311
+ COLOR_NAMES.find { |k, v| v == @value }.first
312
+ end
313
+ end
314
+
315
+ def inspect
316
+ if name.nil?
317
+ "#<Color: (#{to_rgb.join(',')})>"
318
+ else
319
+ "#<Color: #{name}>"
320
+ end
321
+ end
322
+
323
+ #
324
+ # Get the RGB value represented by the color.
325
+ #
326
+ # @return [<Integer>] an array containing r, g, and b values, in that order
327
+ def to_rgb
328
+ RGB::COLORS[@value]
329
+ end
330
+
331
+ #
332
+ # Get the hex value represented by the color.
333
+ #
334
+ # @return [String] a string of the form #XXXXXX
335
+ def to_hex
336
+ '#' + Hex::COLORS[@value]
337
+ end
338
+
339
+ #
340
+ # Get the red component of the color.
341
+ #
342
+ # @return [Integer]
343
+ def red
344
+ RGB::COLORS[@value][0]
345
+ end
346
+ alias_method :r, :red
347
+
348
+ #
349
+ # Get the green component of the color.
350
+ #
351
+ # @return [Integer]
352
+ def green
353
+ RGB::COLORS[@value][1]
354
+ end
355
+ alias_method :g, :green
356
+
357
+ #
358
+ # Get the blue component of the color.
359
+ #
360
+ # @return [Integer]
361
+ def blue
362
+ RGB::COLORS[@value][2]
363
+ end
364
+ alias_method :b, :blue
365
+
366
+ end
367
+
368
+ end
@@ -0,0 +1,14 @@
1
+ class String
2
+
3
+ alias_method :old_plus, :+
4
+ private :old_plus
5
+
6
+ def +(other)
7
+ if other.is_a?(Chromate::Effect) or other.is_a?(Chromate::EffectSet)
8
+ self + other.escape
9
+ else
10
+ old_plus(other)
11
+ end
12
+ end
13
+
14
+ end
@@ -0,0 +1,98 @@
1
+ module Chromate
2
+
3
+ #
4
+ # The `Effect` class is used to represent a generic escape sequences,
5
+ # providing a standardized escape mechanism. You may convert an effect to
6
+ # either a string, in which case it will be escaped as an SGR escape sequence,
7
+ # or an integer, in which case it will yield its internal value. You may also
8
+ # explicitly escape an effect by calling {#escape} on it.
9
+ #
10
+ class Effect
11
+
12
+ #
13
+ # Create a new effect with the specified value.
14
+ # @param value [Fixnum]
15
+ #
16
+ # @return [Effect]
17
+ def initialize(value)
18
+ unless value.is_a?(Numeric)
19
+ raise TypeError, "cannot create #{self.class} from #{value.class}"
20
+ end
21
+
22
+ @value = value.to_i
23
+ end
24
+
25
+ #
26
+ # Get the effect with the specified name.
27
+ # @param value [String,Symbol] the name of an effect
28
+ #
29
+ # @return [Effect]
30
+ def self.[](value)
31
+ if value.is_a?(Symbol) or value.is_a?(String)
32
+ EFFECTS[value.intern]
33
+ else
34
+ raise TypeError, "don't know what to do with a #{value.class}"
35
+ end
36
+ end
37
+
38
+ #
39
+ # Escape as an SGR escape sequence.
40
+ #
41
+ # @return [String] an escape sequence of the form "\e[1;2;3;...m"
42
+ def escape
43
+ "\e[#{@value}m"
44
+ end
45
+
46
+ #
47
+ # Get the name of this effect, if it exists.
48
+ #
49
+ # @return [Symbol]
50
+ def name
51
+ if EFFECTS.value?(self)
52
+ EFFECTS.find { |k, v| v == self }.first
53
+ end
54
+ end
55
+
56
+ # @return [String]
57
+ def inspect
58
+ if name.nil?
59
+ "#<Effect: #{@value}>"
60
+ else
61
+ "#<Effect: #{name}>"
62
+ end
63
+ end
64
+
65
+ #
66
+ # Yield the internal value.
67
+ #
68
+ # @return [Integer]
69
+ def to_i
70
+ @value
71
+ end
72
+
73
+ # @return [String]
74
+ def to_s
75
+ escape
76
+ end
77
+
78
+ # @return [Boolean]
79
+ def ==(other)
80
+ to_i == other.to_i
81
+ end
82
+
83
+ def +(other)
84
+ case other
85
+ when EffectSet
86
+ other.add(self)
87
+ when Effect
88
+ EffectSet.new([self, other])
89
+ when String
90
+ escape + other
91
+ else
92
+ raise TypeError, "cannot add #{other.class} to #{self.class}"
93
+ end
94
+ end
95
+
96
+ end
97
+
98
+ end
@@ -0,0 +1,139 @@
1
+ require 'set'
2
+
3
+ module Chromate
4
+
5
+ #
6
+ # A wrapper over the `Set` class, useful for maintaining and emitting
7
+ # collections of unrelated effects. Only effects may be added to an `EffectSet`,
8
+ # but some other types may be coerced into an effect. The coercion rules are
9
+ # as follows:
10
+ #
11
+ # 1. If the value is an `Effect`, it will remain as-is.
12
+ # 2. If the value is an `Array`, it is unambiguously in reference to a color,
13
+ # specifically an RGB array, and will be parsed as such.
14
+ # 3. If the value is a `Symbol`, it is in reference to a name of some sort.
15
+ # Names of effects will be checked before names of colors. If no effect
16
+ # or color exists with this name, an `ArgumentError` will be thrown.
17
+ # 4. If the value is a `String`, it may either be a name of some sort or a
18
+ # hex color string. If the value begins with a '#', it will be parsed as
19
+ # a hex string. Otherwise, it will be parsed according to rule 3.
20
+ # 5. If the value is a `Numeric`, it may either be a raw effect or a color
21
+ # code. If the value is negative or greater than 255, an error will be
22
+ # thrown. Otherwise, if the value is not a valid effect code, the value
23
+ # is unambiguously a color code and will be parsed as such. Otherwise,
24
+ # there is insufficient information available to determine course of
25
+ # action. The target class must be explicitly specified, or it will
26
+ # default to `Effect`. (Target class must be a subclass of `Effect`, or
27
+ # `Effect` itself.) As a special case, 0 is considered an invalid effect
28
+ # code, as it would make little sense to include an 'off' sequence in an
29
+ # unordered collection of effects. As such, adding 0 to an EffectSet will
30
+ # add the color black, not the off sequence.
31
+ #
32
+ class EffectSet < Set
33
+
34
+ #
35
+ # Construct a new `EffectSet` from an existing enumerable object containing
36
+ # effects. If non-effects are encountered, they will be parsed as per the
37
+ # rules of `EffectSet`.
38
+ # @param enum [Enumerable] an enumerable object containing colors
39
+ #
40
+ # @return [EffectSet]
41
+ def initialize(enum = [])
42
+ super(enum) { |what| parse_member(what) }
43
+ end
44
+
45
+ #
46
+ # Construct a new `EffectSet` from an array of effects. If non-effects are
47
+ # encountered, they will be parsed as per the rules of `EffectSet`.
48
+ # @param codes [<Chromate::Effect,Integer,<Integer>,Symbol,String>]
49
+ #
50
+ # @return [EffectSet]
51
+ def self.[](*codes)
52
+ new(codes)
53
+ end
54
+
55
+ #
56
+ # Generate a single escape sequence that is an agglomeration of the
57
+ # escape sequences of the individual effects within the set.
58
+ #
59
+ # @return [String]
60
+ def escape
61
+ "\e[" + map do |effect|
62
+ /\e\[(.*)m/.match(effect.escape)[1]
63
+ end.join(';') + 'm'
64
+ end
65
+ alias_method :to_s, :escape
66
+
67
+ #
68
+ # Add an element to the set. If it is a non-effect, it will be parsed as
69
+ # per the rules of `EffectSet`. An optional second parameter indicates the
70
+ # class of `Effect` to use if passing in an ambiguous effect code.
71
+ # @param what [Chromate::Effect,Integer,<Integer>,Symbol,String]
72
+ # @param klass [Class]
73
+ #
74
+ # @return [EffectSet] the same effect set with `what` added in to it
75
+ def add(what, klass = Effect)
76
+ super(parse_member(what, klass))
77
+ end
78
+
79
+ def +(other)
80
+ case other
81
+ when EffectSet
82
+ other.add(self)
83
+ when Effect
84
+ add(other)
85
+ when String
86
+ escape + other
87
+ else
88
+ raise TypeError, "cannot add #{other.class} to #{self.class}"
89
+ end
90
+ end
91
+
92
+ # @return [String]
93
+ def inspect
94
+ sprintf('#<EffectSet: {%s}>', to_a.inspect[1..-2])
95
+ end
96
+
97
+ private
98
+
99
+ def parse_member(what, klass = Effect)
100
+ unless klass <= Effect
101
+ raise TypeError, "#{klass.name} is not a sublcass of Effect"
102
+ end
103
+
104
+ case what
105
+ when Effect
106
+ what
107
+ when Numeric
108
+ return COLORS[0] if what == 0
109
+ if what < 0 or what > 255
110
+ raise ArgumentError, "invalid effect or color code: #{what}"
111
+ elsif VALID_EFFECTS.include?(what)
112
+ klass.new(what.to_i)
113
+ else
114
+ Color.new(what.to_i)
115
+ end
116
+ when Array
117
+ Color.from_rgb(*what)
118
+ when Symbol
119
+ if EFFECTS.include?(what)
120
+ EFFECTS[what]
121
+ elsif COLOR_NAMES.include?(what)
122
+ COLORS[COLOR_NAMES[what]]
123
+ else
124
+ raise ArgumentError, "no such effect or color: #{what}"
125
+ end
126
+ when String
127
+ if what[0] == '#'
128
+ Color.from_hex(what)
129
+ else
130
+ parse_member(what.intern)
131
+ end
132
+ else
133
+ raise TypeError, "cannot create Chromate::Effect from #{what.class}"
134
+ end
135
+ end
136
+
137
+ end
138
+
139
+ end
@@ -0,0 +1,65 @@
1
+ module Chromate
2
+
3
+ # Commonly supported effect sequences
4
+ EFFECTS = {
5
+ :off => Effect.new(0),
6
+ :bold => Effect.new(1),
7
+ :underline => Effect.new(4),
8
+ :blink => Effect.new(5),
9
+ :negative => Effect.new(7)
10
+ }
11
+
12
+ # Valid effect sequences
13
+ VALID_EFFECTS = EFFECTS.map { |n, e| e.to_i }
14
+
15
+ OFF = EFFECTS[:off]
16
+ const_set(:Effects, Module.new do
17
+ Chromate::EFFECTS.each do |name, effect|
18
+ const_set(name.to_s.upcase, effect)
19
+ end
20
+ end)
21
+
22
+ # Names for common colors
23
+ COLOR_NAMES = {
24
+ :black => 0,
25
+ :dark_red => 1,
26
+ :dark_green => 2,
27
+ :dark_yellow => 3,
28
+ :dark_blue => 4,
29
+ :dark_magenta => 5,
30
+ :dark_cyan => 6,
31
+ :silver => 7,
32
+ :gray => 8,
33
+ :grey => 8,
34
+ :red => 9,
35
+ :green => 10,
36
+ :yellow => 11,
37
+ :blue => 12,
38
+ :magenta => 13,
39
+ :cyan => 14,
40
+ :white => 15
41
+ }
42
+
43
+ # All xterm-256 colors
44
+ COLORS = (0..255).map { |i| Color.new(i) }
45
+
46
+ # Greyscale colors
47
+ GREYSCALE_COLORS = COLORS[231..255] +
48
+ [COLORS[0], COLORS[7], COLORS[8], COLORS[15]]
49
+
50
+ # Colors supported by the host environment
51
+ SUPPORTED_COLORS = case RbConfig::CONFIG['host_os']
52
+ when /darwin|linux|arch|solaris|sunos|(free|net|open)bsd/i
53
+ COLORS[0..`tput colors`.to_i - 1]
54
+ when /mswin|windows/i
55
+ begin
56
+ require 'win32console'
57
+ COLORS[0..15]
58
+ rescue LoadError
59
+ []
60
+ end
61
+ else
62
+ []
63
+ end
64
+
65
+ end
@@ -0,0 +1,71 @@
1
+ module Chromate
2
+
3
+ #
4
+ # The `Formattable` module allows any class easy access to Chromate formatting,
5
+ # so long as it provides an `effects` method, which is expected to return an
6
+ # `EffectSet`.
7
+ #
8
+ module Formattable
9
+
10
+ #
11
+ # Introduce a format attribute. Each format attribute comes with two
12
+ # methods, which generally differ only by addition of a '?' character (
13
+ # although this behavior can be overriden). The first method sets the format
14
+ # attribute with the given name, and the second queries whether it is set.
15
+ # @param name [Symbol] the name of an attribute
16
+ # @param question_name [Symbol] the name of the method to query whether the
17
+ # attribute is set
18
+ #
19
+ # @api private
20
+ def self.format_attr(name, question_name = name.to_s + '?')
21
+ if EFFECTS.include?(name)
22
+ module_eval(<<-EOF
23
+ define_method :#{name} do
24
+ effects << Effect[:#{name}]
25
+ self
26
+ end
27
+
28
+ define_method :#{question_name} do
29
+ effects.include?(Effect[:#{name}])
30
+ end
31
+ EOF
32
+ )
33
+ else
34
+ raise ArgumentError, "no such effect: #{name}"
35
+ end
36
+ end
37
+ class << self; private :format_attr; end
38
+
39
+ format_attr :bold
40
+ format_attr :underline, :underlined?
41
+
42
+ #
43
+ # Set the foreground and return self.
44
+ # @param what [Object] an object describing the foreground color (see
45
+ # {Chromate::Color::[]})
46
+ #
47
+ # @return [Formattable] self
48
+ def fg(what)
49
+ effects << Color[what]
50
+ self
51
+ end
52
+
53
+ #
54
+ # Set the background and return self.
55
+ # @param what [Object] an object describing the background color (see
56
+ # {Chromate::Color::[]})
57
+ #
58
+ # @return [Formattable] self
59
+ def bg(what)
60
+ effects << Color[what].as_bg
61
+ self
62
+ end
63
+
64
+ # @return [String]
65
+ def to_s
66
+ effects + self + OFF
67
+ end
68
+
69
+ end
70
+
71
+ end
@@ -0,0 +1,44 @@
1
+ module Chromate
2
+
3
+ module Hex
4
+
5
+ # A single hex byte, i.e., two valid hexadecimal numbers
6
+ BYTE = /[0-9A-F]{2}/i
7
+
8
+ # A CSS-style hex string, of the form #XXXXXX (case-insensitive), where X is
9
+ # a hexadecimal number
10
+ PATTERN = /#(#{BYTE})(#{BYTE})(#{BYTE})/io
11
+
12
+ # Hex string representations of the 256 xterm colors
13
+ COLORS = %w(
14
+ 000000 800000 008000 808000 000080 800080 008080 c0c0c0 808080 ff0000
15
+ 00ff00 ffff00 0000ff ff00ff 00ffff ffffff 000000 00005f 000087 0000af
16
+ 0000d7 0000ff 005f00 005f5f 005f87 005faf 005fd7 005fff 008700 00875f
17
+ 008787 0087af 0087d7 0087ff 00af00 00af5f 00af87 00afaf 00afd7 00afff
18
+ 00d700 00d75f 00d787 00d7af 00d7d7 00d7ff 00ff00 00ff5f 00ff87 00ffaf
19
+ 00ffd7 00ffff 5f0000 5f005f 5f0087 5f00af 5f00d7 5f00ff 5f5f00 5f5f5f
20
+ 5f5f87 5f5faf 5f5fd7 5f5fff 5f8700 5f875f 5f8787 5f87af 5f87d7 5f87ff
21
+ 5faf00 5faf5f 5faf87 5fafaf 5fafd7 5fafff 5fd700 5fd75f 5fd787 5fd7af
22
+ 5fd7d7 5fd7ff 5fff00 5fff5f 5fff87 5fffaf 5fffd7 5fffff 870000 87005f
23
+ 870087 8700af 8700d7 8700ff 875f00 875f5f 875f87 875faf 875fd7 875fff
24
+ 878700 87875f 878787 8787af 8787d7 8787ff 87af00 87af5f 87af87 87afaf
25
+ 87afd7 87afff 87d700 87d75f 87d787 87d7af 87d7d7 87d7ff 87ff00 87ff5f
26
+ 87ff87 87ffaf 87ffd7 87ffff af0000 af005f af0087 af00af af00d7 af00ff
27
+ af5f00 af5f5f af5f87 af5faf af5fd7 af5fff af8700 af875f af8787 af87af
28
+ af87d7 af87ff afaf00 afaf5f afaf87 afafaf afafd7 afafff afd700 afd75f
29
+ afd787 afd7af afd7d7 afd7ff afff00 afff5f afff87 afffaf afffd7 afffff
30
+ d70000 d7005f d70087 d700af d700d7 d700ff d75f00 d75f5f d75f87 d75faf
31
+ d75fd7 d75fff d78700 d7875f d78787 d787af d787d7 d787ff dfaf00 dfaf5f
32
+ dfaf87 dfafaf dfafdf dfafff dfdf00 dfdf5f dfdf87 dfdfaf dfdfdf dfdfff
33
+ dfff00 dfff5f dfff87 dfffaf dfffdf dfffff ff0000 ff005f ff0087 ff00af
34
+ ff00df ff00ff ff5f00 ff5f5f ff5f87 ff5faf ff5fdf ff5fff ff8700 ff875f
35
+ ff8787 ff87af ff87df ff87ff ffaf00 ffaf5f ffaf87 ffafaf ffafdf ffafff
36
+ ffdf00 ffdf5f ffdf87 ffdfaf ffdfdf ffdfff ffff00 ffff5f ffff87 ffffaf
37
+ ffffdf ffffff 080808 121212 1c1c1c 262626 303030 3a3a3a 444444 4e4e4e
38
+ 585858 626262 6c6c6c 767676 808080 8a8a8a 949494 9e9e9e a8a8a8 b2b2b2
39
+ bcbcbc c6c6c6 d0d0d0 dadada e4e4e4 eeeeee
40
+ )
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,281 @@
1
+ module Chromate
2
+
3
+ module Lab
4
+
5
+ # L*a*b* array representations of the 256 xterm colors
6
+ COLORS = [
7
+ [ 0.0, 0.0, 0.0],
8
+ [ 0.46573992598472813, 2.088717407442653, 0.7359554408427227],
9
+ [ 1.5661371650822282, -3.1994053792742116, 2.286912750078296],
10
+ [ 2.03187709106696, -1.1106879718315725, 3.022868190921024],
11
+ [ 0.1580585921287927, 1.1106870278938807, -3.022867813345936],
12
+ [ 0.6237985181135244, 3.199404435336492, -2.286912372503208],
13
+ [ 1.7241957572110245, -2.088718351380331, -0.7359550632676404],
14
+ [ 5.368312865335966,-2.3139277438577466e-06, 9.255710975430986e-07],
15
+ [ 2.1899356831957526, -9.439377057773868e-07, 3.775750823109547e-07],
16
+ [ 2.1702682120302335, 9.733065044192912, 3.429426187489948],
17
+ [ 7.2979307021415885, -14.908680584676814, 10.656621363709961],
18
+ [ 9.386516414015183, -4.836292441189285, 13.945215654378117],
19
+ [ 0.7365259429070754, 5.1756111418960336, -14.030418942944955],
20
+ [ 2.906794154937309, 14.90867618608896, -10.577468187682026],
21
+ [ 8.034374445289192, -9.732715133472695, -3.170796457047925],
22
+ [ 10.0284167860891,-3.7397147878426296e-06, 1.495885920688167e-06],
23
+ [ 0.0, 0.0, 0.0],
24
+ [ 0.08347787161759257, 0.5866039161370046, -1.5965128364159253],
25
+ [ 0.17750795822573195, 1.2473588679607768, -3.3948366001899046],
26
+ [ 0.31486836800315743, 2.212598550480893, -6.021852037641395],
27
+ [ 0.49992911286044617, 3.5130312945475946, -9.561135550220607],
28
+ [ 0.7365259429070754, 5.1756111418960336, -14.030418942944955],
29
+ [ 0.8271476763233778, -1.689750287577299, 1.207821772802542],
30
+ [ 0.9106255479409704, -1.1031463714402805, -0.3886910636133778],
31
+ [ 1.0046556345491098, -0.4423914196165224, -2.187014827387351],
32
+ [ 1.1420160443265353, 0.522848262903608, -4.814030264838859],
33
+ [ 1.327076789183824, 1.8232810069702954, -8.353313777418059],
34
+ [ 1.5636736192304532, 3.485860854318748, -12.806567152228022],
35
+ [ 1.758852883167851, -3.5930973999098725, 2.568321072833574],
36
+ [ 1.8423307547854435, -3.006493483772868, 0.9718082364176539],
37
+ [ 1.9363608413935829, -2.3457385319490958, -0.8265155273563196],
38
+ [ 2.0737212511710084, -1.3804988494289656, -3.453530964807822],
39
+ [ 2.258781996028297, -0.0800661053622781, -6.992814477387027],
40
+ [ 2.4953788260749263, 1.5825137419861746, -11.425760671238855],
41
+ [ 3.1199003268149355, -6.373532351418895, 4.5557566702606795],
42
+ [ 3.2033781984325316, -5.786928435281904, 2.959243833844755],
43
+ [ 3.2974082850406674, -5.126173483458133, 1.1609200700707756],
44
+ [ 3.4347686948180964, -4.160933800938002, -1.4660953673807153],
45
+ [ 3.619829439675385, -2.8605010568713145, -5.005378879959915],
46
+ [ 3.856426269722011, -1.197921209522848, -9.404496602590317],
47
+ [ 4.953590646431547, -10.119512463062835, 7.233357243902772],
48
+ [ 5.037068518049139, -9.532908546925817, 5.636844407486841],
49
+ [ 5.131098604657275, -8.872153595102045, 3.8385206437128616],
50
+ [ 5.268459014434704, -7.9069139125819285, 1.2115052062613652],
51
+ [ 5.453519759291993, -6.606481168515227, -2.3277783063178403],
52
+ [ 5.690116589338622, -4.943901321166788, -6.6737925931023625],
53
+ [ 7.2979307021415885, -14.908680584676814, 10.656621363709961],
54
+ [ 7.381408573759181, -14.322076668539797, 9.06010852729403],
55
+ [ 7.47543866036732, -13.661321716716039, 7.261784763520057],
56
+ [ 7.612799070144746, -12.696082034195907, 4.634769326068556],
57
+ [ 7.797859815002038, -11.395649290129233, 1.0954858134893664],
58
+ [ 8.034374445289192, -9.732715133472695, -3.170796457047925],
59
+ [ 0.24597826176295712, 1.1031458729042072, 0.38869126302781276],
60
+ [ 0.3294561333805497, 1.6897497890412116, -1.2078215733881126],
61
+ [ 0.4234862199886855, 2.3505047408649977, -3.0061453371620916],
62
+ [ 0.5608466297661145, 3.315744423385114, -5.633160774613588],
63
+ [ 0.7459073746234033, 4.616177167451829, -9.172444287192793],
64
+ [ 0.9825042046700325, 6.278757014800254, -13.639257157211764],
65
+ [ 1.0731259380863314, -0.5866044146730642, 1.5965130358303437],
66
+ [ 1.1566038097039275, -4.985360735343392e-07, 1.9941442941373566e-07],
67
+ [ 1.2506338963120633, 0.6607544532877124, -1.798323564359544],
68
+ [ 1.3879943060894924, 1.6259941358078152, -4.42533900181104],
69
+ [ 1.573055050946781, 2.9264268798745166, -7.964622514390252],
70
+ [ 1.8096518809934068, 4.589006727222969, -12.415097205484948],
71
+ [ 2.004831144930808, -2.4899515270056654, 2.9570123358613865],
72
+ [ 2.0883090165484006, -1.9033476108686609, 1.3604994994454611],
73
+ [ 2.1823391031565365, -1.2425926590448748, -0.4378242643285124],
74
+ [ 2.3196995129339655, -0.2773529765247723, -3.064839701780009],
75
+ [ 2.504760257791254, 1.023079767541929, -6.60412321435922],
76
+ [ 2.7413570878378835, 2.6856596148903678, -11.033952108865302],
77
+ [ 3.3658785885778926, -5.270386478514688, 4.944447933288481],
78
+ [ 3.449356460195485, -4.683782562377684, 3.3479350968725674],
79
+ [ 3.5433865468036245, -4.0230276105539255, 1.549611333098594],
80
+ [ 3.68074695658105, -3.057787928033795, -1.0774041043529137],
81
+ [ 3.8658077014383387, -1.7573551839670936, -4.616687616932113],
82
+ [ 4.102404531484968, -0.09477533661865489, -9.012208836891894],
83
+ [ 5.1995689081945, -9.0163665901586, 7.622048506930568],
84
+ [ 5.283046779812096, -8.429762674021624, 6.025535670514653],
85
+ [ 5.377076866420232, -7.769007722197838, 4.227211906740674],
86
+ [ 5.514437276197661, -6.803768039677721, 1.600196469289178],
87
+ [ 5.69949802105495, -5.50333529561102, -1.9390870432900331],
88
+ [ 5.936094851101579, -3.840755448262581, -6.280886529664969],
89
+ [ 7.543908963904542, -13.80553471177258, 11.045312626737768],
90
+ [ 7.627386835522138, -13.21893079563559, 9.44879979032185],
91
+ [ 7.721416922130274, -12.558175843811803, 7.65047602654787],
92
+ [ 7.858777331907703, -11.5929361612917, 5.0234605890963735],
93
+ [ 8.04372538421865, -10.29201767349075, 1.4839827790234683],
94
+ [ 8.27718726491764, -8.615925113436965, -2.7825997928274617],
95
+ [ 0.5230499792025647, 2.345737471858331, 0.8265159513926312],
96
+ [ 0.6065278508201573, 2.9323413879953493, -0.7699968850232997],
97
+ [ 0.7005579374282966, 3.5930963398190934, -2.568320648797273],
98
+ [ 0.8379183472057221, 4.558336022339238, -5.195336086248769],
99
+ [ 1.0229790920630109, 5.858768766405939, -8.734619598827981],
100
+ [ 1.25957592210964, 7.521348613754378, -13.198589208451061],
101
+ [ 1.3501976555259425, 0.6559871842810455, 2.0343377241951677],
102
+ [ 1.433675527143535, 1.24259110041805, 0.4378248877792479],
103
+ [ 1.527705613751671, 1.9033460522418222, -1.3604988759947312],
104
+ [ 1.6650660235291, 2.868585734761939, -3.9875143134462276],
105
+ [ 1.8501267683863887, 4.16901847882864, -7.526797826025433],
106
+ [ 2.086723598433018, 5.831598326177079, -11.974083544043578],
107
+ [ 2.2819028623704156, -1.247359928051528, 3.3948370242261996],
108
+ [ 2.365380733988008, -0.6607560119145373, 1.7983241878102851],
109
+ [ 2.4594108205961476,-1.0600907790481173e-06, 4.2403631161924693e-07],
110
+ [ 2.596771230373573, 0.9652386224293652, -2.627015013415196],
111
+ [ 2.781831975230862, 2.2656713664960666, -6.166298525994401],
112
+ [ 3.018428805277491, 3.928251213844505, -10.592558546339276],
113
+ [ 3.6429503060175, -4.027794879560551, 5.382272621653305],
114
+ [ 3.7264281776350963, -3.4411909634235878, 3.785759785237386],
115
+ [ 3.820458264243232, -2.780436011599802, 1.9874360214634068],
116
+ [ 3.9578186740206576, -1.815196329079685, -0.6395794159880952],
117
+ [ 4.142879418877946, -0.5147635850129562, -4.178862928567301],
118
+ [ 4.3794762489245755, 1.1478162623354826, -8.570277604210109],
119
+ [ 5.476640625634111, -7.7737749912044904, 8.059873195295392],
120
+ [ 5.560118497251704, -7.187171075067486, 6.463360358879472],
121
+ [ 5.654148583859843, -6.526416123243714, 4.665036595105493],
122
+ [ 5.791508993637269, -5.561176440723598, 2.038021157653996],
123
+ [ 5.9765697384945575, -4.260743696656896, -1.501262354925209],
124
+ [ 6.213166568541187, -2.5981638493084573, -5.838261492407609],
125
+ [ 7.820980681344153, -12.56294311281847, 11.483137315102587],
126
+ [ 7.904458552961749, -11.97633919668148, 9.886624478686667],
127
+ [ 7.998488639569885, -11.315584244857707, 8.088300714912688],
128
+ [ 8.135054279488433, -10.34691883018725, 5.45991498460105],
129
+ [ 8.316678738930346, -9.031674511054272, 1.9147068419953395],
130
+ [ 8.545001735678095, -7.333431589141681, -2.3550957847641163],
131
+ [ 0.9278000546103051, 4.160931920520639, 1.4660961195476718],
132
+ [ 1.0112779262279012, 4.7475358366576295, -0.13041671686824796],
133
+ [ 1.105308012836037, 5.408290788481401, -1.928740480642227],
134
+ [ 1.2426684226134626, 6.373530471001532, -4.555755918093729],
135
+ [ 1.4277291674707513, 7.673963215068246, -8.09503943067294],
136
+ [ 1.6643259975173805, 9.336543062416686, -12.554741017010935],
137
+ [ 1.754947730933683, 2.4711816329433534, 2.6739178923502136],
138
+ [ 1.8384256025512755, 3.057785549080344, 1.0774050559342885],
139
+ [ 1.932455689159415, 3.7185405009041164, -0.720918707839685],
140
+ [ 2.0698160989368404, 4.683780183424233, -3.347934145291187],
141
+ [ 2.254876843794129, 5.9842129274909475, -6.8872176578703925],
142
+ [ 2.4914736738407584, 7.646792774839387, -11.32973298057271],
143
+ [ 2.686652937778156, 0.567834520610766, 4.0344171923812455],
144
+ [ 2.770130809395752, 1.1544384367477427, 2.4379043559653257],
145
+ [ 2.864160896003888, 1.8151933885715288, 0.6395805921913467],
146
+ [ 3.0015213057813135, 2.7804330710916454, -1.9874348452601553],
147
+ [ 3.1865820506386022, 4.0808658151583606, -5.526718357839361],
148
+ [ 3.4231788806852315, 5.743445662506799, -9.94765588731043],
149
+ [ 4.047700381425244, -2.2126004308982843, 6.021852789808346],
150
+ [ 4.131178253042837, -1.6259965147612798, 4.4253399533924265],
151
+ [ 4.2252083396509725, -0.9652415629374939, 2.6270161896184527],
152
+ [ 4.362568749428402,-1.8804173912423394e-06, 7.521669509458206e-07],
153
+ [ 4.54762949428569, 1.300430863649324, -3.5392827604122545],
154
+ [ 4.784226324332316, 2.963010710997777, -7.9245934939712654],
155
+ [ 5.881390701041852, -5.958580542542183, 8.699453363450433],
156
+ [ 5.964868572659448, -5.37197662640522, 7.102940527034518],
157
+ [ 6.058898659267584, -4.71122167458142, 5.304616763260533],
158
+ [ 6.196259069045009, -3.745981992061304, 2.6776013258090368],
159
+ [ 6.381319813902298, -2.445549247994588, -0.861682186770174],
160
+ [ 6.617916643948927, -0.7829694006461496, -5.191568874186014],
161
+ [ 8.223607218362389, -10.738595481442792, 12.119056210172275],
162
+ [ 8.305275059300829, -10.14418970893012, 10.519422631206087],
163
+ [ 8.396613881889909, -9.47183448116215, 8.71645875705443],
164
+ [ 8.528826143428034, -8.484404504507104, 6.080567201948961],
165
+ [ 8.70472814153132, -7.1444944037420965, 2.525492746690433],
166
+ [ 8.926029928054998, -5.415987644656798, -1.7480821301431027],
167
+ [ 1.473105288901401, 6.606478182901276, 2.3277795005634205],
168
+ [ 1.5565831605189935, 7.193082099038267, 0.7312666641475007],
169
+ [ 1.6506132471271293, 7.853837050862053, -1.0670570996264783],
170
+ [ 1.7879736569045583, 8.81907673338217, -3.6940725370779806],
171
+ [ 1.973034401761847, 10.119509477448885, -7.233356049657186],
172
+ [ 2.2096312318084728, 11.782089324797337, -11.687093796927556],
173
+ [ 2.3002529652247787, 4.916727895323991, 3.5356012733659625],
174
+ [ 2.3837308368423713, 5.5033318114609955, 1.9390884369500427],
175
+ [ 2.477760923450507, 6.164086763284768, 0.14076467317606367],
176
+ [ 2.615121333227936, 7.12932644580487, -2.4862507642754386],
177
+ [ 2.800182078085225, 8.429759189871586, -6.025534276854638],
178
+ [ 3.0367789081318506, 10.092339037220038, -10.461413857059416],
179
+ [ 3.231958172069252, 3.013380782991404, 4.896100573397],
180
+ [ 3.3154360436868444, 3.5999846991284086, 3.299587736981074],
181
+ [ 3.4094661302949802, 4.260739650952194, 1.5012639732070898],
182
+ [ 3.5468265400724093, 5.2259793334722975, -1.1257514642443955],
183
+ [ 3.731887284929698, 6.526412077538998, -4.665034976823606],
184
+ [ 3.9684841149763272, 8.188991924887437, -9.07859827809046],
185
+ [ 4.719950073683535, 0.8022573384867254, 7.084131952532646],
186
+ [ 4.803427945301131, 1.3888612546237162, 5.487619116116738],
187
+ [ 4.897458031909267, 2.0496162064474883, 3.6892953523427527],
188
+ [ 5.034818441686692, 3.0148558889676185, 1.062279914891251],
189
+ [ 5.262960445386941, 4.6180231740532705, -3.3009319204752865],
190
+ [ 5.45647601659061, 5.977868480382758, -6.851902517813086],
191
+ [ 6.980514754786963, -3.815769078464981, 10.385065170167307],
192
+ [ 7.063992626404556, -3.2291651623279765, 8.788552333751381],
193
+ [ 7.158022713012695, -2.5684102105042044, 6.990228569977414],
194
+ [ 7.2953831227901205, -1.603170527984088, 4.363213132525912],
195
+ [ 7.5235251264903695, -3.242898435895647e-06, 1.2971593743582588e-06],
196
+ [ 7.717040697694038, 1.3595109328811417, -3.479420947230122],
197
+ [ 8.866298051616052, -7.5963288370378415, 13.130371822888593],
198
+ [ 8.943818556779096, -6.984046617217424, 11.523587664999313],
199
+ [ 9.0305651046354, -6.291897101808164, 9.712706075791145],
200
+ [ 9.156215163257453, -5.276181767756266, 7.0655003777269245],
201
+ [ 9.362175938461576, -3.6266215940371493, 2.664045044953273],
202
+ [ 9.534291317305062, -2.307210411480548, -0.7820413523084102],
203
+ [ 2.1702682120302335, 9.733065044192912, 3.429426187489948],
204
+ [ 2.253746083647826, 10.319668960329917, 1.832913351074017],
205
+ [ 2.3477761702559654, 10.980423912153675, 0.03458958730004902],
206
+ [ 2.485136580033391, 11.945663594673805, -2.5924258501514528],
207
+ [ 2.71327858373364, 13.54883087975943, -6.955637685517985],
208
+ [ 2.906794154937309, 14.90867618608896, -10.577468187682026],
209
+ [ 2.9974158883536113, 8.043314756615613, 4.637247960292489],
210
+ [ 3.080893759971204, 8.629918672752618, 3.0407351238765647],
211
+ [ 3.1749238465793397, 9.290673624576403, 1.2424113601025855],
212
+ [ 3.3122842563567687, 10.255913307096506, -1.384604077348911],
213
+ [ 3.540426260057014, 11.859080592182172, -5.747815912715448],
214
+ [ 3.7339418312606867, 13.21892589851166, -9.350937354703776],
215
+ [ 3.9291210951980844, 6.13996764428304, 5.997747260323516],
216
+ [ 4.0125989668156805, 6.726571560420017, 4.401234423907602],
217
+ [ 4.106629053423816, 7.387326512243803, 2.6029106601336283],
218
+ [ 4.243989463201242, 8.352566194763932, -0.0241047773178793],
219
+ [ 4.472131466901491, 9.955733479849584, -4.387316612684411],
220
+ [ 4.66564703810516, 11.315578786179072, -7.96718643389096],
221
+ [ 5.2901685388451725, 3.3595326927740032, 7.985182857750628],
222
+ [ 5.373646410462765, 3.9461366089109937, 6.388670021334702],
223
+ [ 5.467676497070901, 4.60689156073478, 4.590346257560723],
224
+ [ 5.605036906848326, 5.572131243254896, 1.963330820109227],
225
+ [ 5.833178910548575, 7.175298528340562, -2.3998810152573102],
226
+ [ 6.026694481752244, 8.534993990321052, -5.9417543099544385],
227
+ [ 7.550733219948597, -1.2584937241776895, 11.286116075385277],
228
+ [ 7.634211091566193, -0.6718898080407265, 9.689603238969363],
229
+ [ 7.728241178174329, -0.011134856216940547, 7.891279475195384],
230
+ [ 7.865601587951758, 0.9526131356607653, 5.264264037743882],
231
+ [ 8.093346866803692, 2.477891311819247, 0.9003681940181918],
232
+ [ 8.283854718648737, 3.6941518861046547, -2.5734295208431957],
233
+ [ 9.386516414015183, -4.836292441189285, 13.945215654378117],
234
+ [ 9.460906294700411, -4.2391184881929584, 12.333033868078802],
235
+ [ 9.544182347323037, -3.5829926712698383, 10.516168666398768],
236
+ [ 9.664865892482492, -2.6542303503559044, 7.860400014088703],
237
+ [ 9.862837195391332, -1.183527136262602, 3.4451697290818095],
238
+ [ 10.0284167860891,-3.7397147878426296e-06, 1.495885920688167e-06],
239
+ [ 0.021934076132581026, -9.454326210800446e-09, 3.781730484320178e-09],
240
+ [ 0.058780982569004436,-2.5336621689575622e-08, 1.0134648675830249e-08],
241
+ [ 0.11435633851765203,-4.9291529191641814e-08, 1.9716611676656726e-08],
242
+ [ 0.19243856430753326, -8.294763487182166e-08, 3.3179053948728665e-08],
243
+ [ 0.295077431223973, -1.271885236020509e-07, 5.087540944082036e-08],
244
+ [ 0.4240923330288915,-1.8279841529356133e-07, 7.311936611742453e-08],
245
+ [ 0.5811308595128502, -2.50487422470691e-07, 1.001949689882764e-07],
246
+ [ 0.7677063750858686,-3.3090787054934623e-07, 1.323631482197385e-07],
247
+ [ 0.9852237981900878,-4.2466538618946004e-07, 1.6986615447578401e-07],
248
+ [ 1.234998173671169, -5.323267521228914e-07, 2.1293070084915655e-07],
249
+ [ 1.518268563807407, -6.544260272578484e-07, 2.6177041090313935e-07],
250
+ [ 1.8362087507290958, -7.914691957378039e-07, 3.165876782951216e-07],
251
+ [ 2.1899356831957526, -9.439377057773868e-07, 3.775750823109547e-07],
252
+ [ 2.5805162775921744, -1.112291383997821e-06, 4.449165535991284e-07],
253
+ [ 3.0089729867597903,-1.2969709889398828e-06, 5.187883955759531e-07],
254
+ [ 3.476288425972694,-1.4984000151763155e-06, 5.993600171727564e-07],
255
+ [ 3.9834092637972525,-1.7169865668131834e-06, 6.867946267252734e-07],
256
+ [ 4.531249530409994, -1.953124606490775e-06, 7.812498425963099e-07],
257
+ [ 5.120693457658401, -2.20719523214008e-06, 8.828780984071471e-07],
258
+ [ 5.752597937960555,-2.4795678427169676e-06, 9.91827137086787e-07],
259
+ [ 6.427794669443173,-2.7706008737249377e-06, 1.1082403550410902e-06],
260
+ [ 7.147092040193037, -3.08064282417142e-06, 1.232257129668568e-06],
261
+ [ 7.911276793614039, -3.410032770045923e-06, 1.3640131080183693e-06],
262
+ [ 8.70043862073167,-3.5489133576316334e-06, 1.4195653430526534e-06],
263
+ ]
264
+
265
+ #
266
+ # Determine the difference (delta-E 1976) between two L*a*b* color values.
267
+ # @param lab1 [<Integer>] a L*a*b* array
268
+ # @param lab2 [<Integer>] another L*a*b* array
269
+ #
270
+ # @return [Integer]
271
+ def self.difference(lab1, lab2)
272
+ Math.sqrt(
273
+ (lab1[0] - lab2[0]) ** 2 +
274
+ (lab1[1] - lab2[1]) ** 2 +
275
+ (lab1[2] - lab2[2]) ** 2
276
+ )
277
+ end
278
+
279
+ end
280
+
281
+ end
@@ -0,0 +1,118 @@
1
+ require 'matrix'
2
+
3
+ module Chromate
4
+
5
+ module RGB
6
+
7
+ # RGB array representations of the 256 xterm colors
8
+ COLORS = [
9
+ [ 0, 0, 0], [128, 0, 0], [ 0, 128, 0], [128, 128, 0],
10
+ [ 0, 0, 128], [128, 0, 128], [ 0, 128, 128], [192, 192, 192],
11
+ [128, 128, 128], [255, 0, 0], [ 0, 255, 0], [255, 255, 0],
12
+ [ 0, 0, 255], [255, 0, 255], [ 0, 255, 255], [255, 255, 255],
13
+ [ 0, 0, 0], [ 0, 0, 95], [ 0, 0, 135], [ 0, 0, 175],
14
+ [ 0, 0, 215], [ 0, 0, 255], [ 0, 95, 0], [ 0, 95, 95],
15
+ [ 0, 95, 135], [ 0, 95, 175], [ 0, 95, 215], [ 0, 95, 255],
16
+ [ 0, 135, 0], [ 0, 135, 95], [ 0, 135, 135], [ 0, 135, 175],
17
+ [ 0, 135, 215], [ 0, 135, 255], [ 0, 175, 0], [ 0, 175, 95],
18
+ [ 0, 175, 135], [ 0, 175, 175], [ 0, 175, 215], [ 0, 175, 255],
19
+ [ 0, 215, 0], [ 0, 215, 95], [ 0, 215, 135], [ 0, 215, 175],
20
+ [ 0, 215, 215], [ 0, 215, 255], [ 0, 255, 0], [ 0, 255, 95],
21
+ [ 0, 255, 135], [ 0, 255, 175], [ 0, 255, 215], [ 0, 255, 255],
22
+ [ 95, 0, 0], [ 95, 0, 95], [ 95, 0, 135], [ 95, 0, 175],
23
+ [ 95, 0, 215], [ 95, 0, 255], [ 95, 95, 0], [ 95, 95, 95],
24
+ [ 95, 95, 135], [ 95, 95, 175], [ 95, 95, 215], [ 95, 95, 255],
25
+ [ 95, 135, 0], [ 95, 135, 95], [ 95, 135, 135], [ 95, 135, 175],
26
+ [ 95, 135, 215], [ 95, 135, 255], [ 95, 175, 0], [ 95, 175, 95],
27
+ [ 95, 175, 135], [ 95, 175, 175], [ 95, 175, 215], [ 95, 175, 255],
28
+ [ 95, 215, 0], [ 95, 215, 95], [ 95, 215, 135], [ 95, 215, 175],
29
+ [ 95, 215, 215], [ 95, 215, 255], [ 95, 255, 0], [ 95, 255, 95],
30
+ [ 95, 255, 135], [ 95, 255, 175], [ 95, 255, 215], [ 95, 255, 255],
31
+ [135, 0, 0], [135, 0, 95], [135, 0, 135], [135, 0, 175],
32
+ [135, 0, 215], [135, 0, 255], [135, 95, 0], [135, 95, 95],
33
+ [135, 95, 135], [135, 95, 175], [135, 95, 215], [135, 95, 255],
34
+ [135, 135, 0], [135, 135, 95], [135, 135, 135], [135, 135, 175],
35
+ [135, 135, 215], [135, 135, 255], [135, 175, 0], [135, 175, 95],
36
+ [135, 175, 135], [135, 175, 175], [135, 175, 215], [135, 175, 255],
37
+ [135, 215, 0], [135, 215, 95], [135, 215, 135], [135, 215, 175],
38
+ [135, 215, 215], [135, 215, 255], [135, 255, 0], [135, 255, 95],
39
+ [135, 255, 135], [135, 255, 175], [135, 255, 215], [135, 255, 255],
40
+ [175, 0, 0], [175, 0, 95], [175, 0, 135], [175, 0, 175],
41
+ [175, 0, 215], [175, 0, 255], [175, 95, 0], [175, 95, 95],
42
+ [175, 95, 135], [175, 95, 175], [175, 95, 215], [175, 95, 255],
43
+ [175, 135, 0], [175, 135, 95], [175, 135, 135], [175, 135, 175],
44
+ [175, 135, 215], [175, 135, 255], [175, 175, 0], [175, 175, 95],
45
+ [175, 175, 135], [175, 175, 175], [175, 175, 215], [175, 175, 255],
46
+ [175, 215, 0], [175, 215, 95], [175, 215, 135], [175, 215, 175],
47
+ [175, 215, 215], [175, 215, 255], [175, 255, 0], [175, 255, 95],
48
+ [175, 255, 135], [175, 255, 175], [175, 255, 215], [175, 255, 255],
49
+ [215, 0, 0], [215, 0, 95], [215, 0, 135], [215, 0, 175],
50
+ [215, 0, 215], [215, 0, 255], [215, 95, 0], [215, 95, 95],
51
+ [215, 95, 135], [215, 95, 175], [215, 95, 215], [215, 95, 255],
52
+ [215, 135, 0], [215, 135, 95], [215, 135, 135], [215, 135, 175],
53
+ [215, 135, 215], [215, 135, 255], [223, 175, 0], [223, 175, 95],
54
+ [223, 175, 135], [223, 175, 175], [223, 175, 223], [223, 175, 255],
55
+ [223, 223, 0], [223, 223, 95], [223, 223, 135], [223, 223, 175],
56
+ [223, 223, 223], [223, 223, 255], [223, 255, 0], [223, 255, 95],
57
+ [223, 255, 135], [223, 255, 175], [223, 255, 223], [223, 255, 255],
58
+ [255, 0, 0], [255, 0, 95], [255, 0, 135], [255, 0, 175],
59
+ [255, 0, 223], [255, 0, 255], [255, 95, 0], [255, 95, 95],
60
+ [255, 95, 135], [255, 95, 175], [255, 95, 223], [255, 95, 255],
61
+ [255, 135, 0], [255, 135, 95], [255, 135, 135], [255, 135, 175],
62
+ [255, 135, 223], [255, 135, 255], [255, 175, 0], [255, 175, 95],
63
+ [255, 175, 135], [255, 175, 175], [255, 175, 223], [255, 175, 255],
64
+ [255, 223, 0], [255, 223, 95], [255, 223, 135], [255, 223, 175],
65
+ [255, 223, 223], [255, 223, 255], [255, 255, 0], [255, 255, 95],
66
+ [255, 255, 135], [255, 255, 175], [255, 255, 223], [255, 255, 255],
67
+ [ 8, 8, 8], [ 18, 18, 18], [ 28, 28, 28], [ 38, 38, 38],
68
+ [ 48, 48, 48], [ 58, 58, 58], [ 68, 68, 68], [ 78, 78, 78],
69
+ [ 88, 88, 88], [ 98, 98, 98], [108, 108, 108], [118, 118, 118],
70
+ [128, 128, 128], [138, 138, 138], [148, 148, 148], [158, 158, 158],
71
+ [168, 168, 168], [178, 178, 178], [188, 188, 188], [198, 198, 198],
72
+ [208, 208, 208], [218, 218, 218], [228, 228, 228], [238, 238, 238]
73
+ ]
74
+
75
+ # D65 conversion matrix
76
+ CONVERSION_MATRIX = Matrix[
77
+ [0.4124564, 0.3575761, 0.1804375],
78
+ [0.2126729, 0.7151522, 0.0721750],
79
+ [0.0193339, 0.1191920, 0.9503041]
80
+ ]
81
+
82
+ # CIE D65 standard illuminant
83
+ RX = 95.047
84
+ RY = 100.0
85
+ RZ = 108.883
86
+
87
+ #
88
+ # Convert an RGB array into an array representing coordinates in L*a*b*
89
+ # color space.
90
+ # @param rgb [<Integer>] an RGB array
91
+ #
92
+ # @return [<Integer>] a L*a*b* array
93
+ def self.to_lab(rgb)
94
+ xyz_matrix = CONVERSION_MATRIX * Matrix[*rgb.map do |c|
95
+ c = c / 255.0
96
+ if c > 0.04045
97
+ [(c + 0.055 / 1.055) ** 2.4]
98
+ else
99
+ [c / 12.92]
100
+ end
101
+ end]
102
+ f_x, f_y, f_z = *[
103
+ xyz_matrix[0, 0] / RX,
104
+ xyz_matrix[1, 0] / RY,
105
+ xyz_matrix[2, 0] / RZ
106
+ ].map do |c|
107
+ if c > 0.008856
108
+ Math.cbrt(c)
109
+ else
110
+ (903.3 * c + 16) / 116
111
+ end
112
+ end
113
+ [116 * f_y - 16, 500 * (f_x - f_y), 200 * (f_y - f_z)]
114
+ end
115
+
116
+ end
117
+
118
+ end
@@ -0,0 +1,3 @@
1
+ module Chromate
2
+ VERSION = '1.0.0'
3
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chromate
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Octaplex
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-03 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: ''
14
+ email:
15
+ - damanm72@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/chromate.rb
21
+ - lib/chromate/cache.rb
22
+ - lib/chromate/color.rb
23
+ - lib/chromate/core_ext/string.rb
24
+ - lib/chromate/effect.rb
25
+ - lib/chromate/effect_set.rb
26
+ - lib/chromate/effects.rb
27
+ - lib/chromate/formattable.rb
28
+ - lib/chromate/hex.rb
29
+ - lib/chromate/lab.rb
30
+ - lib/chromate/rgb.rb
31
+ - lib/chromate/version.rb
32
+ homepage: ''
33
+ licenses:
34
+ - GPLv3
35
+ metadata: {}
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubyforge_project:
52
+ rubygems_version: 2.2.1
53
+ signing_key:
54
+ specification_version: 4
55
+ summary: A dead-simple terminal coloring utility.
56
+ test_files: []
57
+ has_rdoc: