simplecolor 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,111 @@
1
+ module SimpleColor
2
+ class RGB
3
+ GREY256=232
4
+ TRUE_COLOR=0xFFFFFF
5
+
6
+ ANSI_COLORS_16 = {
7
+ :black => 0,
8
+ :red => 1,
9
+ :green => 2,
10
+ :yellow => 3,
11
+ :blue => 4,
12
+ :magenta => 5,
13
+ :cyan => 6,
14
+ :white => 7,
15
+ :intense_black => 8,
16
+ :intense_red => 9,
17
+ :intense_green => 10,
18
+ :intense_yellow => 11,
19
+ :intense_blue => 12,
20
+ :intense_magenta => 13,
21
+ :intense_cyan => 14,
22
+ :intense_white => 15,
23
+ }
24
+ (0..15).each { |i| ANSI_COLORS_16[:"color#{i}"]=i}
25
+
26
+ # A list of color names for standard ansi colors, needed for 16/8 color fallback mode
27
+ # See https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
28
+ # These are the xterm color palette
29
+ RGB_COLORS_ANSI = {
30
+ :black => [ 0, 0, 0],
31
+ :red => [205, 0, 0],
32
+ :green => [ 0, 205, 0],
33
+ :yellow => [205, 205, 0],
34
+ :blue => [ 0, 0, 238],
35
+ :magenta => [205, 0, 205],
36
+ :cyan => [ 0, 205, 205],
37
+ :white => [229, 229, 229],
38
+ :gray => [229, 229, 229],
39
+ }.each { |_k, v| v.freeze }.freeze
40
+
41
+ RGB_COLORS_ANSI_BRIGHT = {
42
+ :intense_black => [127, 127, 127],
43
+ :intense_red => [255, 0, 0],
44
+ :intense_green => [ 0, 255, 0],
45
+ :intense_yellow => [255, 255, 0],
46
+ :intense_blue => [ 92, 92, 255],
47
+ :intense_magenta => [255, 0, 255],
48
+ :intense_cyan => [ 0, 255, 255],
49
+ :intense_white => [255, 255, 255],
50
+ :intense_gray => [255, 255, 255],
51
+ }.each { |_k, v| v.freeze }.freeze
52
+
53
+ RGB_COLORS_ANSI_16 = RGB_COLORS_ANSI.merge(RGB_COLORS_ANSI_BRIGHT)
54
+
55
+ COLOR_NAMES={
56
+ :random => proc { rgb_random },
57
+ }
58
+
59
+ module ColorNames
60
+ def color_names
61
+ @color_names ||= COLOR_NAMES.dup
62
+ end
63
+
64
+ def all_color_names
65
+ return @rgb_color_names if defined? @rgb_color_names
66
+ # A list of color names, based on X11's rgb.txt
67
+ rgb_colors = File.dirname(__FILE__) + "/../../data/rgb_colors.json.gz"
68
+ # Rewrite file:
69
+ # h={}; rgb.each do |k,v| h[SimpleColor::RGB.rgb_clean(k)]=v end
70
+ # Pathname.new("data/rgb_colors.json").write(h.to_json)
71
+ File.open(rgb_colors, "rb") do |file|
72
+ serialized_data = Zlib::GzipReader.new(file).read
73
+ # serialized_data.force_encoding Encoding::BINARY
74
+ @rgb_color_names = JSON.parse(serialized_data)
75
+ end
76
+ end
77
+
78
+ def color_names_priority
79
+ @rgb_color_names.keys
80
+ end
81
+
82
+ def rgb_clean(name) #clean up name
83
+ name.gsub(/\s+/,'').downcase.gsub('gray','grey')
84
+ end
85
+
86
+ def find_color(name)
87
+ custom=color_names
88
+ case name
89
+ when String
90
+ return custom[name] if custom.key?(name)
91
+ name=rgb_clean(name)
92
+ return custom[name] if custom.key?(name)
93
+ colors=all_color_names
94
+ base, rest=name.split(':', 2)
95
+ if rest.nil?
96
+ color_names_priority.each do |base|
97
+ c=colors[base]
98
+ return c[name] if c.key?(name)
99
+ end
100
+ else
101
+ c=colors[base]
102
+ return c[rest]
103
+ end
104
+ else
105
+ custom[name]
106
+ end
107
+ end
108
+ end
109
+ extend ColorNames
110
+ end
111
+ end
@@ -1,4 +1,4 @@
1
1
  module SimpleColor
2
2
  # simplecolor version
3
- VERSION = "0.2.0"
3
+ VERSION = "0.3.0"
4
4
  end
data/simplecolor.gemspec CHANGED
@@ -35,6 +35,7 @@ Gem::Specification.new do |gem|
35
35
  end
36
36
  end
37
37
  gem.files = glob[gemspec['files']] if gemspec['files']
38
+ gem.files = gem.files + gemspec['extra_files'] if gemspec['extra_files']
38
39
 
39
40
  gem.executables = gemspec.fetch('executables') do
40
41
  glob['bin/*'].map { |path| File.basename(path) }
@@ -68,4 +69,5 @@ Gem::Specification.new do |gem|
68
69
  end
69
70
 
70
71
  gem.metadata['yard.run']='yri'
72
+ gem.metadata['project_name']='SimpleColor'
71
73
  end
data/test/test_rgb.rb ADDED
@@ -0,0 +1,103 @@
1
+ require 'helper'
2
+ require 'simplecolor'
3
+
4
+ describe SimpleColor::RGB do
5
+ it "Should output truecolor code" do
6
+ SimpleColor::RGB.new(10,20,30).ansi.must_equal "38;2;10;20;30"
7
+ end
8
+ it "Can degrade to 256 colors" do
9
+ SimpleColor::RGB.new(10,20,30).convert(256).ansi.must_equal "38;5;234"
10
+ end
11
+ it "Can degrade to 16 colors" do
12
+ SimpleColor::RGB.new(10,20,160).convert(16).ansi.must_equal "34"
13
+ end
14
+ it "Can degrade to 8 colors" do
15
+ SimpleColor::RGB.new(10,20,30).convert(8).ansi.must_equal "30"
16
+ end
17
+
18
+ describe "List name" do
19
+ it "Can specify color names" do
20
+ SimpleColor::RGB.parse("lavender").to_hex.must_equal "#9F90D0"
21
+ end
22
+ it "Can specify the dict to use for color names" do
23
+ SimpleColor::RGB.parse("x11:lavender").to_hex.must_equal "#E6E6FA"
24
+ end
25
+ it "Can use custom names" do
26
+ SimpleColor::RGB.parse("solarized_base03").to_hex.must_equal "#002B36"
27
+ end
28
+ it "Custom names have precedence" do
29
+ SimpleColor::RGB.parse("verydarkbluishgreen").to_hex.must_equal "#002A29"
30
+ SimpleColor::RGB.color_names["verydarkbluishgreen"]="#002B30"
31
+ SimpleColor::RGB.parse("verydarkbluishgreen").to_hex.must_equal "#002B30"
32
+ SimpleColor::RGB.parse("nbs:verydarkbluishgreen").to_hex.must_equal "#002A29"
33
+ end
34
+ end
35
+ end
36
+
37
+ describe SimpleColor do
38
+ after do #restore default options
39
+ SimpleColor.opts=nil
40
+ end
41
+
42
+ it "Can parse a true color name" do
43
+ SimpleColor.color("foo", "rgb:10-20-30").must_equal "\e[38;2;10;20;30mfoo\e[0m"
44
+ SimpleColor.color("foo", "10-20-30").must_equal "\e[38;2;10;20;30mfoo\e[0m"
45
+ SimpleColor.color("foo", "10:20:30").must_equal "\e[38;2;10;20;30mfoo\e[0m"
46
+ SimpleColor.color("foo", [10, 20, 30]).must_equal "\e[38;2;10;20;30mfoo\e[0m"
47
+ end
48
+
49
+ it "Can specify 256 colors" do
50
+ SimpleColor.color("foo", "rgb256:1-2-3").must_equal "\e[38;5;67mfoo\e[0m"
51
+ SimpleColor.color("foo", "256:1-2-3").must_equal "\e[38;5;67mfoo\e[0m"
52
+ SimpleColor.color("foo", "256:grey1").must_equal "\e[38;5;233mfoo\e[0m"
53
+ SimpleColor.color("foo", "256:10").must_equal "\e[38;5;10mfoo\e[0m"
54
+ end
55
+
56
+ it "Can specify hexa color name" do
57
+ SimpleColor.color("foo", "#10AABB").must_equal "\e[38;2;16;170;187mfoo\e[0m"
58
+ SimpleColor.color("foo", "#1AB").must_equal "\e[38;2;17;170;187mfoo\e[0m"
59
+ end
60
+
61
+ it "Can specify x11 color name" do
62
+ SimpleColor.color("foo", "Lemon Chiffon").must_equal "\e[38;2;255;250;205mfoo\e[0m"
63
+ SimpleColor.color("foo", "lemonchiffon").must_equal "\e[38;2;255;250;205mfoo\e[0m"
64
+ end
65
+
66
+ it "Can specify background color name" do
67
+ SimpleColor.color("foo", "on_lemonchiffon").must_equal "\e[48;2;255;250;205mfoo\e[0m"
68
+ SimpleColor.color("foo", "on_rgb:255+250+205").must_equal "\e[48;2;255;250;205mfoo\e[0m"
69
+ SimpleColor.color("foo", "on_#CCBBAA").must_equal "\e[48;2;204;187;170mfoo\e[0m"
70
+ SimpleColor.color("foo", "on_rgb256:1+2+3").must_equal "\e[48;5;67mfoo\e[0m"
71
+ SimpleColor.color("foo", "on_rgb256:1").must_equal "\e[48;5;1mfoo\e[0m"
72
+ SimpleColor.color("foo", "on_rgb256:gray1").must_equal "\e[48;5;233mfoo\e[0m"
73
+ SimpleColor.color("foo", [:on, 10, 20, 30]).must_equal "\e[48;2;10;20;30mfoo\e[0m"
74
+ end
75
+
76
+ describe "It can fallback to 256 colors" do
77
+ before do
78
+ SimpleColor.color_mode=256
79
+ end
80
+
81
+ it "Can specify x11 color name" do
82
+ SimpleColor.color("foo", "Lemon Chiffon").must_equal "\e[38;5;230mfoo\e[0m"
83
+ SimpleColor.color("foo", "on_Lemon Chiffon").must_equal "\e[48;5;230mfoo\e[0m"
84
+ end
85
+
86
+ it "Can be forced to be truecolor" do
87
+ SimpleColor.color("foo", "t:Lemon Chiffon").must_equal "\e[38;2;255;250;205mfoo\e[0m"
88
+ SimpleColor.color("foo", "truecolor:Lemon Chiffon").must_equal "\e[38;2;255;250;205mfoo\e[0m"
89
+ SimpleColor.color("foo", "true:on_Lemon Chiffon").must_equal "\e[48;2;255;250;205mfoo\e[0m"
90
+ end
91
+ end
92
+
93
+ describe "It can fallback to 8 colors" do
94
+ before do
95
+ SimpleColor.color_mode=8
96
+ end
97
+
98
+ it "Can specify x11 color name" do
99
+ SimpleColor.color("foo", "Lemon Chiffon").must_equal "\e[37mfoo\e[0m"
100
+ SimpleColor.color("foo", "on_Lemon Chiffon").must_equal "\e[47mfoo\e[0m"
101
+ end
102
+ end
103
+ end
@@ -2,18 +2,15 @@ require 'helper'
2
2
  require 'simplecolor'
3
3
 
4
4
  class TestSimpleColor < MiniTest::Test
5
-
6
5
  def test_version
7
6
  version = SimpleColor.const_get('VERSION')
8
-
9
7
  assert(!version.empty?, 'should have a VERSION constant')
10
8
  end
11
-
12
9
  end
13
10
 
14
11
  describe SimpleColor do
15
- before do
16
- SimpleColor.enabled=true
12
+ after do #restore default options
13
+ SimpleColor.opts=nil
17
14
  end
18
15
 
19
16
  it "Can be used directly" do
@@ -57,6 +54,50 @@ describe SimpleColor do
57
54
  SimpleColor.color?(SimpleColor.color("red",:red)).must_equal true
58
55
  end
59
56
 
57
+ it "Can only show color escape when passed nil" do
58
+ SimpleColor.color(nil, "x11:lavender").must_equal "\e[38;2;230;230;250m"
59
+ end
60
+
61
+ it "Accepts a block as color parameter" do
62
+ SimpleColor.color("foo", proc { "x11:lavender" }).must_equal "\e[38;2;230;230;250mfoo\e[0m"
63
+ end
64
+
65
+ it "Proc as color parameter can return multiple values" do
66
+ SimpleColor.color("foo", proc { ["x11:lavender", :bold] }).must_equal "\e[38;2;230;230;250;1mfoo\e[0m"
67
+ end
68
+
69
+ it "Has default options" do
70
+ SimpleColor.opts.must_equal(SimpleColor::Opts.default_opts)
71
+ end
72
+
73
+ describe "Abbreviations" do
74
+ before do
75
+ SimpleColor.abbreviations={red: SimpleColor.color(:green), color1: SimpleColor.color(nil, "x11:lavender")}
76
+ end
77
+
78
+ it "Can use the color1 abbreviations" do
79
+ SimpleColor.color("foo", :color1).must_equal "\e[38;2;230;230;250mfoo\e[0m"
80
+ end
81
+ it "Abbrevations have precedence" do
82
+ SimpleColor.color("foo", :red).must_equal SimpleColor.color("foo", :green)
83
+ end
84
+ end
85
+
86
+ describe "Random" do
87
+ it "Has a :random color" do
88
+ SimpleColor.color("foo", :random).must_match(/\e\[38;2;\d+;\d+;\d+mfoo\e\[0m/)
89
+ end
90
+ it "Has a :on_random color" do
91
+ SimpleColor.color("foo", :on_random).must_match(/\e\[48;2;\d+;\d+;\d+mfoo\e\[0m/)
92
+ end
93
+ end
94
+
95
+ describe "Abbreviations" do
96
+ it "Can specify abbreviations" do
97
+ SimpleColor.abbreviations[:important]=[:red, :bold]
98
+ SimpleColor.color("foo", :important).must_equal("\e[31;1mfoo\e[0m")
99
+ end
100
+ end
60
101
 
61
102
  describe "Shell mode" do
62
103
  before do
@@ -66,6 +107,23 @@ describe SimpleColor do
66
107
  it "Wraps color into shell escapes" do
67
108
  SimpleColor.color("red",:red).must_equal "%{\e[31m%}red%{\e[0m%}"
68
109
  end
110
+
111
+ it "Can uncolor correctly" do
112
+ SimpleColor.uncolor(SimpleColor.color("red",:red)).must_equal "red"
113
+ end
114
+
115
+ it "Only uncolor shell wrapped colors" do
116
+ red="\e[31mred\e[0m"
117
+ SimpleColor.uncolor(red).must_equal red
118
+ end
119
+
120
+ it "Can detect colors correctly" do
121
+ SimpleColor.color?(SimpleColor.color("red",:red)).must_equal true
122
+ end
123
+
124
+ it "Only detect shell wrapped colors" do
125
+ SimpleColor.color?("\e[31mred\e[0m").must_equal false
126
+ end
69
127
  end
70
128
 
71
129
  describe "It can be mixed in strings" do
@@ -104,10 +162,8 @@ describe SimpleColor do
104
162
  s.uncolor!
105
163
  s.must_equal "red"
106
164
  end
107
-
108
165
  end
109
166
 
110
-
111
167
  describe "It can be disabled" do
112
168
  before do
113
169
  SimpleColor.enabled=false
@@ -122,6 +178,13 @@ describe SimpleColor do
122
178
  word="\e[31mred\e[0m"
123
179
  SimpleColor.uncolor(word).must_equal "red"
124
180
  end
181
+
182
+ it "Can be disabled punctually" do
183
+ SimpleColor.enabled=true
184
+ word="red"
185
+ SimpleColor.color(word,:red, mode: false).must_equal word
186
+ SimpleColor.color(word,:red).must_equal "\e[31mred\e[0m"
187
+ end
125
188
  end
126
189
 
127
190
  describe "It has colors helpers utilities" do
@@ -145,10 +208,132 @@ describe SimpleColor do
145
208
  SimpleColor.attributes_from_colors("\e[m"+b+e).must_equal([:reset,:red,:bright,:reset])
146
209
  end
147
210
 
211
+ it "Can detect 256 and truecolor attributes" do
212
+ test=SimpleColor[nil, "rgb256:3", "on_rgb:1:2:3", :green, :bold, :conceal, :color15]
213
+ expected=[SimpleColor::RGB.new(3, mode: 256),
214
+ SimpleColor::RGB.new([1,2,3], background: true),
215
+ :green, :bright, :conceal, :intense_white]
216
+ SimpleColor.attributes_from_colors(test).must_equal(expected)
217
+ end
218
+
148
219
  it "Can split a string into color entities" do
149
220
  SimpleColor.color_entities(SimpleColor.color("red",:red,:bold)+SimpleColor.color("blue",:blue)).must_equal(["\e[31;1m", "r", "e", "d", "\e[0m\e[34m", "b", "l", "u", "e", "\e[0m"])
150
221
  SimpleColor.color_entities("blue "+SimpleColor.color("red",:red,:bold)+" green").must_equal(["b", "l", "u", "e", " ", "\e[31;1m", "r", "e", "d", "\e[0m", " ", "g", "r", "e", "e", "n"])
151
222
  end
223
+
224
+ it "Can split a string into color strings" do
225
+ SimpleColor.color_strings(SimpleColor.color("red",:red,:bold)+SimpleColor.color("blue",:blue)).must_equal(["\e[31;1m", "red", "\e[0m\e[34m", "blue", "\e[0m"])
226
+ SimpleColor.color_strings("blue "+SimpleColor.color("red",:red,:bold)+" green").must_equal(["blue ", "\e[31;1m", "red", "\e[0m", " green"])
227
+ end
228
+ end
229
+
230
+ describe "It can use a different color module" do
231
+ module SimpleColor2
232
+ extend SimpleColor
233
+ end
234
+
235
+ it "Can color too" do
236
+ SimpleColor2.color("red", :red).must_equal "\e[31mred\e[0m"
237
+ end
238
+
239
+ it "Still works if SimpleColor is disabled" do
240
+ SimpleColor.enabled=false
241
+ SimpleColor2.color("red", :red).must_equal "\e[31mred\e[0m"
242
+ SimpleColor.color("red", :red).must_equal "red"
243
+ end
244
+
245
+ it "Can be disabled without disabling SimpleColor" do
246
+ SimpleColor2.enabled=false
247
+ SimpleColor.color("red", :red).must_equal "\e[31mred\e[0m"
248
+ SimpleColor2.color("red", :red).must_equal "red"
249
+ SimpleColor2.enabled=true
250
+ end
251
+
252
+ it "Can be mixed in a class" do
253
+ string_class=Class.new(String)
254
+ SimpleColor2.mix_in(string_class)
255
+ string_class.new("red").color(:red).must_equal "\e[31mred\e[0m"
256
+ SimpleColor.enabled=false
257
+ string_class.new("red").color(:red).must_equal "\e[31mred\e[0m"
258
+ SimpleColor2.enabled=false
259
+ string_class.new("red").color(:red).must_equal "red"
260
+ SimpleColor2.enabled=true
261
+ end
262
+
263
+ it "Setting a different color module copy the defaults opts and not the current opts" do
264
+
265
+ default_opts=SimpleColor.opts
266
+ SimpleColor.opts={mode: false, colormode: 16}
267
+ module SimpleColor3
268
+ extend SimpleColor
269
+ end
270
+ SimpleColor.opts=default_opts
271
+ SimpleColor3.opts.must_equal default_opts
272
+ end
152
273
  end
153
274
 
275
+ describe "It raises invalid parameters" do
276
+ it "Raises when we pass invalid parameter" do
277
+ proc { SimpleColor.color("foo", mode: :garbage)}.must_raise SimpleColor::WrongParameter
278
+ end
279
+
280
+ it "Raises when we pass invalid rgb parameter" do
281
+ proc { SimpleColor.color("foo", "x11:lavender", color_mode:10)}.must_raise SimpleColor::WrongRGBParameter
282
+ end
283
+
284
+ it "Raises when we pass an invalid color" do
285
+ proc { SimpleColor.color("foo", SimpleColor)}.must_raise SimpleColor::WrongColor
286
+ proc { SimpleColor.color("foo", "nonexistingcolorname")}.must_raise SimpleColor::WrongRGBColor
287
+ end
288
+ end
289
+
290
+ describe "Chain colors" do
291
+ it "Can chain global colors" do
292
+ r=SimpleColor["red", :red]
293
+ SimpleColor.color(r, :blue).must_equal "\e[31m\e[34mred\e[0m"
294
+ end
295
+
296
+ it "Can keep global colors" do
297
+ r=SimpleColor["red", :red]
298
+ SimpleColor.color(r, :blue, global_color: :keep).must_equal SimpleColor["red", :red]
299
+ end
300
+
301
+ it "Can give precedence to existing global colors" do
302
+ r=SimpleColor["red", :red]
303
+ SimpleColor.color(r, :blue, global_color: :before).must_equal "\e[34m\e[31mred\e[0m"
304
+ end
305
+
306
+ it "Will give precedence to local colors" do
307
+ r="foo "+SimpleColor["red", :red]+" bar"
308
+ SimpleColor.color(r, :blue).must_equal "\e[34mfoo \e[31mred\e[0m\e[34m bar\e[0m"
309
+ r="foo "+SimpleColor["red", :red]
310
+ SimpleColor.color(r, :blue).must_equal "\e[34mfoo \e[31mred\e[0m"
311
+ r=+SimpleColor["red", :red]+" bar"
312
+ SimpleColor.color(r, :blue).must_equal "\e[34m\e[31mred\e[0m\e[34m bar\e[0m"
313
+ end
314
+
315
+ it "Can get precedence over local colors" do
316
+ r="foo "+SimpleColor["red", :red]+" bar"
317
+ SimpleColor.color(r, :blue, local_color: :after).must_equal "\e[34mfoo \e[31m\e[34mred\e[0m\e[34m bar\e[0m"
318
+ r="foo "+SimpleColor["red", :red]
319
+ SimpleColor.color(r, :blue, local_color: :after).must_equal "\e[34mfoo \e[31m\e[34mred\e[0m"
320
+ r=+SimpleColor["red", :red]+" bar"
321
+ SimpleColor.color(r, :blue, local_color: :after).must_equal "\e[31m\e[34mred\e[0m\e[34m bar\e[0m"
322
+ end
323
+
324
+ it "Can keep local colors" do
325
+ r="foo "+SimpleColor["red", :red]+" bar"
326
+ SimpleColor.color(r, :blue, local_color: :keep).must_equal "\e[34mfoo \e[0m\e[31mred\e[0m\e[34m bar\e[0m"
327
+ r="foo "+SimpleColor["red", :red]
328
+ SimpleColor.color(r, :blue, local_color: :keep).must_equal "\e[34mfoo \e[0m\e[31mred\e[0m"
329
+ r=+SimpleColor["red", :red]+" bar"
330
+ SimpleColor.color(r, :blue, local_color: :keep).must_equal "\e[31mred\e[0m\e[34m bar\e[0m"
331
+ end
332
+
333
+ it "Can store precedence settings" do
334
+ SimpleColor.opts[:global_color]=:keep
335
+ r=SimpleColor["red", :red]
336
+ SimpleColor.color(r, :blue).must_equal(SimpleColor["red", :red])
337
+ end
338
+ end
154
339
  end