kungfuig 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d30ca22dee6e6cde7f9f34d17995ff7b27f6b37c
4
- data.tar.gz: a0b476f59450a277e1ad55f2927240a5689e978a
3
+ metadata.gz: 581fb0eb44fd71f631bfab19958c88944fc9029c
4
+ data.tar.gz: 7828afdfb7f56ec38e31786212610ba6d95dc596
5
5
  SHA512:
6
- metadata.gz: f3a3077967091d00545cce2ccdbff1a76360f51150939374c2e5b402191b0beee12133af44ee5f8debb00390878225b4ac031c7ba964cec776173ae978fb998f
7
- data.tar.gz: 058f353934143317f307ea99626480ff2f50558880ae25fb4eea2d69ccaaf77a1bf706b02af365cd5078dc714ded18ad0af7b31fd566b4551d806c990fca1a3e
6
+ metadata.gz: 594896fa2caf55cb544aee7e9ce91ed61f10157d130b2a12386dbbe91ebf12e0afe97ff79c4110a0aa82be9d2069a621249d6c647a9375ee18e9451ea6724627
7
+ data.tar.gz: f2c511de943a406a379dee7a8c755bdcb7749e6cc826bdd7379e40290147b383f0d39677c3ee4310d2e818566d861d7fb2578b4472d5972f34cdfc9c1aa89e77
@@ -2,6 +2,7 @@ require 'yaml'
2
2
  require 'hashie'
3
3
 
4
4
  require 'kungfuig/version'
5
+ require 'kungfuig/color'
5
6
  require 'kungfuig/aspector'
6
7
 
7
8
  module Kungfuig
@@ -14,7 +15,7 @@ module Kungfuig
14
15
  require 'logger'
15
16
  @✍ ||= Kernel.const_defined?('Rails') && Rails.logger || Logger.new($stdout)
16
17
  message = receiver.is_a?(String) ? "#{receiver} | #{method}" : "#{receiver.class}##{method}"
17
- "#{message} called with «#{args.inspect}» and returned «#{result || 'nothing (was it before aspect?)'}»".tap do |m|
18
+ "#{Color.to_xterm256(message, :info)} called with «#{Color.to_xterm256(args.inspect, :success)}» and returned «#{result || 'nothing (was it before aspect?)'}»".tap do |m|
18
19
  @✍.debug m
19
20
  end
20
21
  end
@@ -0,0 +1,286 @@
1
+ module Kungfuig
2
+ # rubocop:disable Metrics/ClassLength
3
+ # Dealing with colors
4
+ class Color
5
+ # Copyright (c) 2007 McClain Looney
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in
15
+ # all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ # THE SOFTWARE.
24
+
25
+ # Implements a color (r,g,b + a) with conversion to/from web format (eg #aabbcc), and
26
+ # with a number of utilities to lighten, darken and blend values.
27
+
28
+ attr_reader :r, :g, :b, :a
29
+
30
+ # Table for conversion to hex
31
+ HEXVAL = ('0'..'9').to_a.concat(('A'..'F').to_a).freeze
32
+ # Default value for #darken, #lighten etc.
33
+ BRIGHTNESS_DEFAULT = 0.2
34
+
35
+ # Constructor. Inits to white (#FFFFFF) by default, or accepts any params
36
+ # supported by #parse.
37
+ def initialize(*args)
38
+ @r = 255
39
+ @g = 255
40
+ @b = 255
41
+ @a = 255
42
+
43
+ if args.size.between?(3, 4)
44
+ self.r = args[0]
45
+ self.g = args[1]
46
+ self.b = args[2]
47
+ self.a = args[3] if args[3]
48
+ else
49
+ set(*args)
50
+ end
51
+ end
52
+
53
+ # All-purpose setter - pass in another Color, '#000000', rgb vals... whatever
54
+ def set(*args)
55
+ val = Color.parse(*args)
56
+ unless val.nil?
57
+ self.r = val.r
58
+ self.g = val.g
59
+ self.b = val.b
60
+ self.a = val.a
61
+ end
62
+ self
63
+ end
64
+
65
+ # Test for equality, accepts string vals as well, eg Color.new('aaa') == '#AAAAAA' => true
66
+ def ==(other)
67
+ val = Color.parse(other)
68
+ return false if val.nil?
69
+ r == val.r && g == val.g && b == val.b && a == val.a
70
+ end
71
+
72
+ # Setters for individual channels - take 0-255 or '00'-'FF' values
73
+ %i(r g b a).each do |m|
74
+ define_method "#{m}=" do |val|
75
+ instance_variable_set("@#{m}", from_hex(val))
76
+ end
77
+ end
78
+
79
+ # rubocop:disable Metrics/CyclomaticComplexity
80
+ # rubocop:disable Metrics/MethodLength
81
+ # Attempt to read in a string and parse it into values
82
+ def self.parse(*args)
83
+ case args.size
84
+ when 0 then return nil
85
+ when 1
86
+ case val = args.first
87
+ when Color then val
88
+ when Fixnum then Color.new(val, val, val) # Single value, assume grayscale
89
+ when String
90
+ str = val.to_s.upcase[/[0-9A-F]{3,8}/] || ''
91
+ Color.new(*case str.size
92
+ when 3, 4 then str.scan(/[0-9A-F]/)
93
+ when 6, 8 then str.scan(/[0-9A-F]{2}/)
94
+ else 'FF'
95
+ end.map { |c| Integer("0x#{c}") })
96
+ end
97
+ when 2 # assume gray + alpha
98
+ val, alpha = args
99
+ Color.new(val, val, val, alpha)
100
+ when 3, 4 then Color.new(*args)
101
+ end
102
+ end
103
+ # rubocop:enable Metrics/MethodLength
104
+ # rubocop:enable Metrics/CyclomaticComplexity
105
+
106
+ def inspect
107
+ id = format('%x', object_id << 1)
108
+ "#<#{self.class.name}:0x#{id.rjust(14, '0')} 💻=“\\e[#{to_esc(true)}#{to_esc(false)}\e[0mm” 🗔=“#{self}”>"
109
+ end
110
+
111
+ def to_s(add_hash = true)
112
+ trans? ? to_rgba(add_hash) : to_rgb(add_hash)
113
+ end
114
+
115
+ # rubocop:disable Metrics/CyclomaticComplexity
116
+ # rubocop:disable Metrics/PerceivedComplexity
117
+ # rubocop:disable Metrics/ParameterLists
118
+ # Color as used in 256-color terminal escape sequences
119
+ def to_esc(surround = true, bold: true, italic: false, underline: false, reverse: false, foreground: true)
120
+ result = if grayscale?
121
+ (r > 239) ? 15 : (r / 10).floor + 232
122
+ else
123
+ 16 + 36 * (r / 51).floor + 6 * (g / 51).floor + (b / 51).floor
124
+ end
125
+
126
+ esc = [
127
+ bold ? '01' : nil,
128
+ italic ? '03' : nil,
129
+ underline ? '04' : nil,
130
+ reverse ? '07' : nil,
131
+ foreground ? '38' : '48',
132
+ '05',
133
+ result
134
+ ].compact.join(';')
135
+
136
+ surround ? "\e[#{esc}m" : esc
137
+ end
138
+ # rubocop:enable Metrics/ParameterLists
139
+ # rubocop:enable Metrics/PerceivedComplexity
140
+ # rubocop:enable Metrics/CyclomaticComplexity
141
+
142
+ def to_rgb(add_hash = true)
143
+ (add_hash ? '#' : '') + to_hex(r) + to_hex(g) + to_hex(b)
144
+ end
145
+
146
+ def to_rgba(add_hash = true)
147
+ to_rgb(add_hash) + to_hex(a)
148
+ end
149
+
150
+ def opaque?
151
+ @a == 255
152
+ end
153
+
154
+ def trans?
155
+ !opaque?
156
+ end
157
+
158
+ def grayscale?
159
+ @r == @g && @g == @b
160
+ end
161
+
162
+ # Lighten color towards white. 0.0 is a no-op, 1.0 will return #FFFFFF
163
+ def lighten(amt = BRIGHTNESS_DEFAULT)
164
+ return self if amt <= 0
165
+ return WHITE if amt >= 1.0
166
+ Color.new(self).tap do |val|
167
+ val.r += ((255 - val.r) * amt).to_i
168
+ val.g += ((255 - val.g) * amt).to_i
169
+ val.b += ((255 - val.b) * amt).to_i
170
+ end
171
+ end
172
+
173
+ # In place version of #lighten
174
+ def lighten!(amt = BRIGHTNESS_DEFAULT)
175
+ set(lighten(amt))
176
+ end
177
+
178
+ # Darken a color towards full black. 0.0 is a no-op, 1.0 will return #000000
179
+ def darken(amt = BRIGHTNESS_DEFAULT)
180
+ return self if amt <= 0
181
+ return BLACK if amt >= 1.0
182
+ Color.new(self).tap do |val|
183
+ val.r -= (val.r * amt).to_i
184
+ val.g -= (val.g * amt).to_i
185
+ val.b -= (val.b * amt).to_i
186
+ end
187
+ end
188
+
189
+ # In place version of #darken
190
+ def darken!(amt = BRIGHTNESS_DEFAULT)
191
+ set(darken(amt))
192
+ end
193
+
194
+ # Convert to grayscale, using perception-based weighting
195
+ def grayscale
196
+ Color.new(self).tap do |val|
197
+ val.r = val.g = val.b = (0.2126 * val.r + 0.7152 * val.g + 0.0722 * val.b)
198
+ end
199
+ end
200
+
201
+ # In place version of #grayscale
202
+ def grayscale!
203
+ set(grayscale)
204
+ end
205
+
206
+ # rubocop:disable Metrics/AbcSize
207
+ # Blend to a color amt % towards another color value, eg
208
+ # red.blend(blue, 0.5) will be purple, white.blend(black, 0.5) will be gray, etc.
209
+ def blend(other, amt)
210
+ other = Color.parse(other)
211
+ return Color.new(self) if amt <= 0 || other.nil?
212
+ return Color.new(other) if amt >= 1.0
213
+ Color.new(self).tap do |val|
214
+ val.r += ((other.r - val.r) * amt).to_i
215
+ val.g += ((other.g - val.g) * amt).to_i
216
+ val.b += ((other.b - val.b) * amt).to_i
217
+ end
218
+ end
219
+ # rubocop:enable Metrics/AbcSize
220
+
221
+ # In place version of #blend
222
+ def blend!(other, amt)
223
+ set(blend(other, amt))
224
+ self
225
+ end
226
+
227
+ # Class-level version for explicit blends of two values, useful with constants
228
+ def self.blend(col1, col2, amt)
229
+ col1, col2 = [col1, col2].map { |c| Color.parse c }
230
+ col1.blend(col2, amt)
231
+ end
232
+
233
+ # rubocop:disable Metrics/ParameterLists
234
+ def self.to_xterm256(text, color, bold: true, italic: false, underline: false, reverse: false, foreground: true)
235
+ color = Color.preset(color) unless color.is_a?(Color)
236
+ [
237
+ color.to_esc(true, bold: bold, italic: italic, underline: underline, reverse: reverse, foreground: foreground),
238
+ text,
239
+ "\e[0m"
240
+ ].join
241
+ end
242
+ # rubocop:enable Metrics/ParameterLists
243
+
244
+ # rubocop:disable Metrics/CyclomaticComplexity
245
+ def self.preset type
246
+ Color.parse case type
247
+ when :label then '#999999'
248
+ when :success then '#468847'
249
+ when :warning then '#F89406'
250
+ when :important then '#B94A48'
251
+ when :fatal then '#B94A48'
252
+ when :error then '#FF0000'
253
+ when :info then '#3A87AD'
254
+ when :inverse then '#333333'
255
+ else type
256
+ end
257
+ end
258
+ # rubocop:enable Metrics/CyclomaticComplexity
259
+
260
+ protected
261
+
262
+ # Convert int to string hex, eg 255 => 'FF'
263
+ def to_hex(val)
264
+ HEXVAL[val / 16] + HEXVAL[val % 16]
265
+ end
266
+
267
+ # Convert int or string to int, eg 80 => 80, 'FF' => 255, '7' => 119
268
+ def from_hex(val)
269
+ if val.is_a?(String)
270
+ # Double up if single char form
271
+ val *= 2 if val.size == 1
272
+ # Convert to integer
273
+ val = val.hex
274
+ end
275
+ # Clamp
276
+ val = 0 if val < 0
277
+ val = 255 if val > 255
278
+ val
279
+ end
280
+
281
+ # Some constants for general use
282
+ WHITE = Color.new(255, 255, 255).freeze
283
+ BLACK = Color.new(0, 0, 0).freeze
284
+ end
285
+ # rubocop:enable Metrics/ClassLength
286
+ end
@@ -1,3 +1,3 @@
1
1
  module Kungfuig
2
- VERSION = "0.5.0"
2
+ VERSION = "0.5.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kungfuig
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kantox LTD
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-24 00:00:00.000000000 Z
11
+ date: 2016-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
@@ -160,6 +160,7 @@ files:
160
160
  - kungfuig.gemspec
161
161
  - lib/kungfuig.rb
162
162
  - lib/kungfuig/aspector.rb
163
+ - lib/kungfuig/color.rb
163
164
  - lib/kungfuig/jobber.rb
164
165
  - lib/kungfuig/version.rb
165
166
  homepage: http://kantox.com