termin-ansicolor 1.3.0.2

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.
@@ -0,0 +1,161 @@
1
+ module Termin
2
+ module ANSIColor
3
+ module RGBColorMetricsHelpers
4
+ module WeightedEuclideanDistance
5
+ def weighted_euclidean_distance_to(other, weights = [ 1.0 ] * values.size)
6
+ sum = 0.0
7
+ values.zip(other.values, weights) do |s, o, w|
8
+ sum += w * (s - o) ** 2
9
+ end
10
+ Math.sqrt(sum)
11
+ end
12
+ end
13
+
14
+ module NormalizeRGBTriple
15
+ private
16
+
17
+ def normalize(v)
18
+ v /= 255.0
19
+ if v <= 0.04045
20
+ v / 12
21
+ else
22
+ ( (v + 0.055) / 1.055) ** 2.4
23
+ end
24
+ end
25
+
26
+ def normalize_rgb_triple(rgb_triple)
27
+ [
28
+ rgb_triple.red,
29
+ rgb_triple.green,
30
+ rgb_triple.blue
31
+ ].map { |v| normalize(v) }
32
+ end
33
+ end
34
+ end
35
+
36
+ module RGBColorMetrics
37
+ def self.metric(name)
38
+ metric?(name) or raise ArgumentError, "unknown metric #{name.inspect}"
39
+ end
40
+
41
+ def self.metric?(name)
42
+ if const_defined?(name)
43
+ const_get name
44
+ end
45
+ end
46
+
47
+ def self.metrics
48
+ constants.map(&:to_sym)
49
+ end
50
+
51
+ # Implements color distance how the old greeks and most donkeys would…
52
+ module Euclidean
53
+ def self.distance(rgb1, rgb2)
54
+ rgb1.weighted_euclidean_distance_to rgb2
55
+ end
56
+ end
57
+
58
+ # Implements color distance the best way everybody knows…
59
+ module NTSC
60
+ def self.distance(rgb1, rgb2)
61
+ rgb1.weighted_euclidean_distance_to rgb2, [ 0.299, 0.587, 0.114 ]
62
+ end
63
+ end
64
+
65
+ # Implements color distance as given in:
66
+ # http://www.compuphase.com/cmetric.htm
67
+ module CompuPhase
68
+ def self.distance(rgb1, rgb2)
69
+ rmean = (rgb1.red + rgb2.red) / 2
70
+ rgb1.weighted_euclidean_distance_to rgb2,
71
+ [ 2 + (rmean >> 8), 4, 2 + ((255 - rmean) >> 8) ]
72
+ end
73
+ end
74
+
75
+ module YUV
76
+ class YUVTriple < Struct.new(:y, :u, :v)
77
+ include RGBColorMetricsHelpers::WeightedEuclideanDistance
78
+
79
+ def self.from_rgb_triple(rgb_triple)
80
+ r, g, b = rgb_triple.red, rgb_triple.green, rgb_triple.blue
81
+ y = (0.299 * r + 0.587 * g + 0.114 * b).round
82
+ u = ((b - y) * 0.492).round
83
+ v = ((r - y) * 0.877).round
84
+ new(y, u, v)
85
+ end
86
+ end
87
+
88
+ def self.distance(rgb1, rgb2)
89
+ yuv1 = YUVTriple.from_rgb_triple(rgb1)
90
+ yuv2 = YUVTriple.from_rgb_triple(rgb2)
91
+ yuv1.weighted_euclidean_distance_to yuv2
92
+ end
93
+ end
94
+
95
+ module CIEXYZ
96
+ class CIEXYZTriple < Struct.new(:x, :y, :z)
97
+ include RGBColorMetricsHelpers::WeightedEuclideanDistance
98
+ extend RGBColorMetricsHelpers::NormalizeRGBTriple
99
+
100
+ def self.from_rgb_triple(rgb_triple)
101
+ r, g, b = normalize_rgb_triple rgb_triple
102
+
103
+ x = 0.436052025 * r + 0.385081593 * g + 0.143087414 * b
104
+ y = 0.222491598 * r + 0.71688606 * g + 0.060621486 * b
105
+ z = 0.013929122 * r + 0.097097002 * g + 0.71418547 * b
106
+
107
+ x *= 255
108
+ y *= 255
109
+ z *= 255
110
+
111
+ new(x.round, y.round, z.round)
112
+ end
113
+ end
114
+
115
+ def self.distance(rgb1, rgb2)
116
+ xyz1 = CIEXYZTriple.from_rgb_triple(rgb1)
117
+ xyz2 = CIEXYZTriple.from_rgb_triple(rgb2)
118
+ xyz1.weighted_euclidean_distance_to xyz2
119
+ end
120
+ end
121
+
122
+ module CIELab
123
+ class CIELabTriple < Struct.new(:l, :a, :b)
124
+ include RGBColorMetricsHelpers::WeightedEuclideanDistance
125
+ extend RGBColorMetricsHelpers::NormalizeRGBTriple
126
+
127
+ def self.from_rgb_triple(rgb_triple)
128
+ r, g, b = normalize_rgb_triple rgb_triple
129
+
130
+ x = 0.436052025 * r + 0.385081593 * g + 0.143087414 * b
131
+ y = 0.222491598 * r + 0.71688606 * g + 0.060621486 * b
132
+ z = 0.013929122 * r + 0.097097002 * g + 0.71418547 * b
133
+
134
+ xr = x / 0.964221
135
+ yr = y
136
+ zr = z / 0.825211
137
+
138
+ eps = 216.0 / 24389
139
+ k = 24389.0 / 27
140
+
141
+ fx = xr > eps ? xr ** (1.0 / 3) : (k * xr + 16) / 116
142
+ fy = yr > eps ? yr ** (1.0 / 3) : (k * yr + 16) / 116
143
+ fz = zr > eps ? zr ** (1.0 / 3) : (k * zr + 16) / 116
144
+
145
+ l = 2.55 * ((116 * fy) - 16)
146
+ a = 500 * (fx - fy)
147
+ b = 200 * (fy - fz)
148
+
149
+ new(l.round, a.round, b.round)
150
+ end
151
+ end
152
+
153
+ def self.distance(rgb1, rgb2)
154
+ lab1 = CIELabTriple.from_rgb_triple(rgb1)
155
+ lab2 = CIELabTriple.from_rgb_triple(rgb2)
156
+ lab1.weighted_euclidean_distance_to lab2
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,121 @@
1
+ require 'termin/ansicolor/rgb_color_metrics'
2
+
3
+ module Termin
4
+ module ANSIColor
5
+ class RGBTriple
6
+ include Termin::ANSIColor::RGBColorMetricsHelpers::WeightedEuclideanDistance
7
+
8
+ def self.convert_value(color)
9
+ color.nil? and raise ArgumentError, "missing color value"
10
+ color = Integer(color)
11
+ (0..0xff) === color or raise ArgumentError,
12
+ "color value #{color.inspect} not between 0 and 255"
13
+ color
14
+ end
15
+
16
+ private_class_method :convert_value
17
+
18
+ def self.from_html(html)
19
+ case html
20
+ when /\A#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})\z/i
21
+ new(*$~.captures.map { |c| convert_value(c.to_i(16)) })
22
+ when /\A#([0-9a-f])([0-9a-f])([0-9a-f])\z/i
23
+ new(*$~.captures.map { |c| convert_value(c.to_i(16) << 4) })
24
+ end
25
+ end
26
+
27
+ def self.from_hash(options)
28
+ new(
29
+ convert_value(options[:red]),
30
+ convert_value(options[:green]),
31
+ convert_value(options[:blue])
32
+ )
33
+ end
34
+
35
+ def self.from_array(array)
36
+ new(*array)
37
+ end
38
+
39
+ def self.[](thing)
40
+ case
41
+ when thing.respond_to?(:to_rgb_triple) then thing
42
+ when thing.respond_to?(:to_ary) then RGBTriple.from_array(thing.to_ary)
43
+ when thing.respond_to?(:to_str) then RGBTriple.from_html(thing.to_str.sub(/\Aon_/, '')) # XXX somewhat hacky
44
+ when thing.respond_to?(:to_hash) then RGBTriple.from_hash(thing.to_hash)
45
+ else raise ArgumentError, "cannot convert #{thing.inspect} into #{self}"
46
+ end
47
+ end
48
+
49
+ def initialize(red, green, blue)
50
+ @values = [ red, green, blue ]
51
+ end
52
+
53
+ def red
54
+ @values[0]
55
+ end
56
+
57
+ def green
58
+ @values[1]
59
+ end
60
+
61
+ def blue
62
+ @values[2]
63
+ end
64
+
65
+ def gray?
66
+ red != 0 && red != 0xff && red == green && green == blue && blue == red
67
+ end
68
+
69
+ def html
70
+ s = '#'
71
+ @values.each { |c| s << '%02x' % c }
72
+ s
73
+ end
74
+
75
+ def to_rgb_triple
76
+ self
77
+ end
78
+
79
+ attr_reader :values
80
+ protected :values
81
+
82
+ def to_a
83
+ @values.dup
84
+ end
85
+
86
+ def ==(other)
87
+ @values == other.values
88
+ end
89
+
90
+ def distance_to(other, options = {})
91
+ options[:metric] ||= RGBColorMetrics::CIELab
92
+ options[:metric].distance(self, other)
93
+ end
94
+
95
+ def initialize_copy(other)
96
+ r = super
97
+ other.instance_variable_set :@values, @values.dup
98
+ r
99
+ end
100
+
101
+ def gradient_to(other, options = {})
102
+ options[:steps] ||= 16
103
+ steps = options[:steps].to_i
104
+ steps < 2 and raise ArgumentError, 'at least 2 steps are required'
105
+ changes = other.values.zip(@values).map { |x, y| x - y }
106
+ current = self
107
+ gradient = [ current.dup ]
108
+ s = steps - 1
109
+ while s > 1
110
+ current = current.dup
111
+ gradient << current
112
+ 3.times do |i|
113
+ current.values[i] += changes[i] / (steps - 1)
114
+ end
115
+ s -= 1
116
+ end
117
+ gradient << other
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,8 @@
1
+ module Termin::ANSIColor
2
+ # Termin::ANSIColor version
3
+ VERSION = '1.3.0'
4
+ VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
+ VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
+ VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
7
+ VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
8
+ end
@@ -0,0 +1,41 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # stub: term-ansicolor 1.3.0 ruby lib
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "termin-ansicolor"
6
+ s.version = "1.3.0.2"
7
+
8
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
9
+ s.require_paths = ["lib"]
10
+ s.authors = ["Florian Frank"]
11
+ s.date = "2014-02-06"
12
+ s.description = "This library uses ANSI escape sequences to control the attributes of terminal output. Termin Ansicolor is the clone of term-ansicolor gem with fixed bug. This gem is needed until merging pull request on official repo."
13
+ s.email = "flori@ping.de"
14
+ s.executables = ["cdiff", "decolor", "colortab", "term_mandel", "term_display"]
15
+ s.extra_rdoc_files = ["README.rdoc", "lib/termin/ansicolor.rb", "lib/termin/ansicolor/attribute.rb", "lib/termin/ansicolor/ppm_reader.rb", "lib/termin/ansicolor/rgb_color_metrics.rb", "lib/termin/ansicolor/rgb_triple.rb", "lib/termin/ansicolor/version.rb"]
16
+ s.files = [".gitignore", ".travis.yml", "CHANGES", "COPYING", "Gemfile", "README.rdoc", "Rakefile", "VERSION", "bin/cdiff", "bin/colortab", "bin/decolor", "bin/term_display", "bin/term_mandel", "examples/ColorTest.gif", "examples/Mona_Lisa.jpg", "examples/Stilleben.jpg", "examples/example.rb", "examples/lambda-red-plain.ppm", "examples/lambda-red.png", "examples/lambda-red.ppm", "examples/pacman.jpg", "examples/smiley.png", "examples/wool.jpg", "lib/termin/ansicolor.rb", "lib/termin/ansicolor/.keep", "lib/termin/ansicolor/attribute.rb", "lib/termin/ansicolor/ppm_reader.rb", "lib/termin/ansicolor/rgb_color_metrics.rb", "lib/termin/ansicolor/rgb_triple.rb", "lib/termin/ansicolor/version.rb", "term-ansicolor.gemspec", "tests/ansicolor_test.rb", "tests/attribute_test.rb", "tests/ppm_reader_test.rb", "tests/rgb_color_metrics_test.rb", "tests/rgb_triple_test.rb", "tests/test_helper.rb"]
17
+ s.homepage = "http://flori.github.com/term-ansicolor"
18
+ s.licenses = ["GPL-2"]
19
+ s.rdoc_options = ["--title", "Term-ansicolor - Ruby library that colors strings using ANSI escape sequences", "--main", "README.rdoc"]
20
+ s.rubygems_version = "2.2.2"
21
+ s.summary = "Ruby library that colors strings using ANSI escape sequences"
22
+ s.test_files = ["tests/ansicolor_test.rb", "tests/attribute_test.rb", "tests/ppm_reader_test.rb", "tests/rgb_color_metrics_test.rb", "tests/rgb_triple_test.rb", "tests/test_helper.rb"]
23
+
24
+ if s.respond_to? :specification_version then
25
+ s.specification_version = 4
26
+
27
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
28
+ s.add_development_dependency(%q<gem_hadar>, ["~> 1.0.0"])
29
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
30
+ s.add_runtime_dependency(%q<tins>, ["~> 1.0"])
31
+ else
32
+ s.add_dependency(%q<gem_hadar>, ["~> 1.0.0"])
33
+ s.add_dependency(%q<simplecov>, [">= 0"])
34
+ s.add_dependency(%q<tins>, ["~> 1.0"])
35
+ end
36
+ else
37
+ s.add_dependency(%q<gem_hadar>, ["~> 1.0.0"])
38
+ s.add_dependency(%q<simplecov>, [">= 0"])
39
+ s.add_dependency(%q<tins>, ["~> 1.0"])
40
+ end
41
+ end
@@ -0,0 +1,133 @@
1
+ require 'test_helper'
2
+
3
+ class String
4
+ include Termin::ANSIColor
5
+ end
6
+
7
+ class Color
8
+ extend Termin::ANSIColor
9
+ end
10
+
11
+ class StringLike
12
+ def initialize(string)
13
+ @string = string
14
+ end
15
+
16
+ def to_str
17
+ @string
18
+ end
19
+ end
20
+
21
+ class ANSIColorTest < Test::Unit::TestCase
22
+ include Termin::ANSIColor
23
+
24
+ def setup
25
+ @string = "red"
26
+ @string_red = "\e[31mred\e[0m"
27
+ @string_red_on_green = "\e[42m\e[31mred\e[0m\e[0m"
28
+ @string_like = StringLike.new(@string)
29
+ @string_like_red = StringLike.new(@string_red)
30
+ end
31
+
32
+ attr_reader :string, :string_red, :string_red_on_green, :string_like, :string_like_red
33
+
34
+ def test_red
35
+ assert_equal string_red, string.red
36
+ assert_equal string_red, Color.red(string)
37
+ assert_equal string_red, Color.red { string }
38
+ assert_equal string_red, Termin::ANSIColor.red { string }
39
+ assert_equal string_red, red { string }
40
+ end
41
+
42
+ def test_red_on_green
43
+ assert_equal string_red_on_green, string.red.on_green
44
+ assert_equal string_red_on_green, Color.on_green(Color.red(string))
45
+ assert_equal string_red_on_green, Color.on_green { Color.red { string } }
46
+ assert_equal string_red_on_green,
47
+ Termin::ANSIColor.on_green { Termin::ANSIColor.red { string } }
48
+ assert_equal string_red_on_green, on_green { red { string } }
49
+ end
50
+
51
+ def test_color
52
+ assert_equal "\e[38;5;128mfoo\e[0m", Color.color(:color128, "foo")
53
+ assert_equal "\e[38;5;128mfoo\e[0m", "foo".color(:color128)
54
+ assert_equal "\e[38;5;128mfoo\e[0m", color(:color128, "foo")
55
+ assert_equal "\e[38;5;128mfoo\e[0m", Color.color(:color128) { "foo" }
56
+ assert_equal "\e[38;5;128mfoo\e[0m", "foo".color(:color128) { "foo" }
57
+ assert_equal "\e[38;5;128mfoo\e[0m", color(:color128) { "foo" }
58
+ assert_equal "\e[38;5;128mfoo\e[0m", color(:color128) + "foo" + color(:reset)
59
+ assert_equal "\e[38;5;128mfoo\e[0m", Color.color(128, "foo")
60
+ assert_equal "\e[38;5;128mfoo\e[0m", "foo".color(128)
61
+ assert_equal "\e[38;5;128mfoo\e[0m", color(128, "foo")
62
+ assert_equal "\e[38;5;128mfoo\e[0m", Color.color(128) { "foo" }
63
+ assert_equal "\e[38;5;128mfoo\e[0m", "foo".color(128) { "foo" }
64
+ assert_equal "\e[38;5;128mfoo\e[0m", color(128) { "foo" }
65
+ assert_equal "\e[38;5;128mfoo\e[0m", color(128) + "foo" + color(:reset)
66
+ end
67
+
68
+ def test_on_color
69
+ assert_equal "\e[48;5;128mfoo\e[0m", Color.on_color(:color128, "foo")
70
+ assert_equal "\e[48;5;128mfoo\e[0m", "foo".on_color(:color128)
71
+ assert_equal "\e[48;5;128mfoo\e[0m", on_color(:color128, "foo")
72
+ assert_equal "\e[48;5;128mfoo\e[0m", Color.on_color(:color128) { "foo" }
73
+ assert_equal "\e[48;5;128mfoo\e[0m", "foo".on_color(:color128) { "foo" }
74
+ assert_equal "\e[48;5;128mfoo\e[0m", on_color(:color128) { "foo" }
75
+ assert_equal "\e[48;5;128mfoo\e[0m", on_color(:color128) + "foo" + color(:reset)
76
+ assert_equal "\e[48;5;128mfoo\e[0m", Color.on_color(128, "foo")
77
+ assert_equal "\e[48;5;128mfoo\e[0m", "foo".on_color(128)
78
+ assert_equal "\e[48;5;128mfoo\e[0m", on_color(128, "foo")
79
+ assert_equal "\e[48;5;128mfoo\e[0m", Color.on_color(128) { "foo" }
80
+ assert_equal "\e[48;5;128mfoo\e[0m", "foo".on_color(128) { "foo" }
81
+ assert_equal "\e[48;5;128mfoo\e[0m", on_color(128) { "foo" }
82
+ assert_equal "\e[48;5;128mfoo\e[0m", on_color(128) + "foo" + color(:reset)
83
+ end
84
+
85
+ def test_uncolor
86
+ assert_equal string, string_red.uncolor
87
+ assert_equal string, Color.uncolor(string_red)
88
+ assert_equal string, Color.uncolor(string_like_red)
89
+ assert_equal string, Color.uncolor { string_red }
90
+ assert_equal string, Color.uncolor { string_like_red }
91
+ assert_equal string, Termin::ANSIColor.uncolor { string_red }
92
+ assert_equal string, Termin::ANSIColor.uncolor { string_like_red }
93
+ assert_equal string, uncolor { string }
94
+ assert_equal string, uncolor { string_like_red }
95
+ assert_equal "", uncolor(Object.new)
96
+ for index in 0..255
97
+ assert_equal "foo", Color.uncolor(Color.color("color#{index}", "foo"))
98
+ assert_equal "foo", Color.uncolor(Color.on_color("color#{index}", "foo"))
99
+ end
100
+ end
101
+
102
+ def test_attributes
103
+ foo = 'foo'
104
+ for a in Termin::ANSIColor.attributes
105
+ # skip clear for Ruby 1.9 which implements String#clear to empty the string
106
+ if a != :clear || Termin::ANSIColor.support?(:clear)
107
+ assert_not_equal foo, foo_colored = foo.__send__(a)
108
+ assert_equal foo, foo_colored.uncolor
109
+ end
110
+ assert_not_equal foo, foo_colored = Color.__send__(a, foo)
111
+ assert_equal foo, Color.uncolor(foo_colored)
112
+ assert_not_equal foo, foo_colored = Color.__send__(a) { foo }
113
+ assert_equal foo, Color.uncolor { foo_colored }
114
+ assert_not_equal foo, foo_colored = Termin::ANSIColor.__send__(a) { foo }
115
+ assert_equal foo, Termin::ANSIColor.uncolor { foo_colored }
116
+ assert_not_equal foo, foo_colored = __send__(a) { foo }
117
+ assert_equal foo, uncolor { foo_colored }
118
+ end
119
+ assert_equal Termin::ANSIColor.attributes, 'foo'.attributes
120
+ end
121
+
122
+ def test_coloring_string_like
123
+ assert_equal "\e[31mred\e[0m", red(string_like)
124
+ end
125
+
126
+ def test_frozen
127
+ string = 'foo'
128
+ red = string.red
129
+ string.extend(Termin::ANSIColor).freeze
130
+ assert string.frozen?
131
+ assert_equal red, string.red
132
+ end
133
+ end