rbbt-util 5.44.1 → 6.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/bin/rbbt +67 -90
- data/bin/rbbt_exec.rb +2 -2
- data/etc/app.d/base.rb +2 -2
- data/etc/app.d/semaphores.rb +3 -3
- data/lib/rbbt/annotations/annotated_array.rb +207 -207
- data/lib/rbbt/annotations/refactor.rb +27 -0
- data/lib/rbbt/annotations/util.rb +282 -282
- data/lib/rbbt/annotations.rb +343 -320
- data/lib/rbbt/association/database.rb +200 -225
- data/lib/rbbt/association/index.rb +294 -291
- data/lib/rbbt/association/item.rb +227 -227
- data/lib/rbbt/association/open.rb +35 -34
- data/lib/rbbt/association/util.rb +0 -169
- data/lib/rbbt/association.rb +2 -4
- data/lib/rbbt/entity/identifiers.rb +119 -118
- data/lib/rbbt/entity/refactor.rb +12 -0
- data/lib/rbbt/entity.rb +319 -315
- data/lib/rbbt/hpc/batch.rb +72 -53
- data/lib/rbbt/hpc/lsf.rb +2 -2
- data/lib/rbbt/hpc/orchestrate/batches.rb +2 -2
- data/lib/rbbt/hpc/orchestrate/chains.rb +25 -5
- data/lib/rbbt/hpc/orchestrate/rules.rb +2 -2
- data/lib/rbbt/hpc/orchestrate.rb +19 -13
- data/lib/rbbt/hpc/slurm.rb +18 -18
- data/lib/rbbt/knowledge_base/entity.rb +13 -5
- data/lib/rbbt/knowledge_base/query.rb +2 -2
- data/lib/rbbt/knowledge_base/registry.rb +32 -31
- data/lib/rbbt/knowledge_base/traverse.rb +1 -1
- data/lib/rbbt/knowledge_base.rb +1 -1
- data/lib/rbbt/monitor.rb +36 -25
- data/lib/rbbt/persist/refactor.rb +166 -0
- data/lib/rbbt/persist/tsv/tokyocabinet.rb +105 -105
- data/lib/rbbt/persist/tsv.rb +187 -185
- data/lib/rbbt/persist.rb +556 -551
- data/lib/rbbt/refactor.rb +20 -0
- data/lib/rbbt/resource/path/refactor.rb +178 -0
- data/lib/rbbt/resource/path.rb +317 -497
- data/lib/rbbt/resource/util.rb +0 -48
- data/lib/rbbt/resource.rb +3 -390
- data/lib/rbbt/tsv/accessor.rb +2 -838
- data/lib/rbbt/tsv/attach.rb +303 -299
- data/lib/rbbt/tsv/change_id.rb +244 -245
- data/lib/rbbt/tsv/csv.rb +87 -85
- data/lib/rbbt/tsv/dumper.rb +2 -100
- data/lib/rbbt/tsv/excel.rb +26 -24
- data/lib/rbbt/tsv/field_index.rb +4 -1
- data/lib/rbbt/tsv/filter.rb +3 -2
- data/lib/rbbt/tsv/index.rb +2 -284
- data/lib/rbbt/tsv/manipulate.rb +750 -747
- data/lib/rbbt/tsv/marshal.rb +3 -3
- data/lib/rbbt/tsv/matrix.rb +2 -2
- data/lib/rbbt/tsv/parallel/through.rb +2 -1
- data/lib/rbbt/tsv/parallel/traverse.rb +783 -781
- data/lib/rbbt/tsv/parser.rb +678 -678
- data/lib/rbbt/tsv/refactor.rb +195 -0
- data/lib/rbbt/tsv/stream.rb +253 -251
- data/lib/rbbt/tsv/util.rb +420 -420
- data/lib/rbbt/tsv.rb +210 -208
- data/lib/rbbt/util/R/eval.rb +4 -4
- data/lib/rbbt/util/R/plot.rb +62 -166
- data/lib/rbbt/util/R.rb +21 -18
- data/lib/rbbt/util/cmd.rb +2 -318
- data/lib/rbbt/util/color.rb +269 -269
- data/lib/rbbt/util/colorize.rb +89 -89
- data/lib/rbbt/util/concurrency/processes/refactor.rb +22 -0
- data/lib/rbbt/util/concurrency/processes/worker.rb +2 -2
- data/lib/rbbt/util/concurrency/processes.rb +389 -386
- data/lib/rbbt/util/config.rb +169 -167
- data/lib/rbbt/util/filecache.rb +1 -1
- data/lib/rbbt/util/iruby.rb +20 -0
- data/lib/rbbt/util/log/progress/report.rb +241 -241
- data/lib/rbbt/util/log/progress/util.rb +99 -99
- data/lib/rbbt/util/log/progress.rb +102 -102
- data/lib/rbbt/util/log/refactor.rb +49 -0
- data/lib/rbbt/util/log.rb +486 -532
- data/lib/rbbt/util/migrate.rb +2 -2
- data/lib/rbbt/util/misc/concurrent_stream.rb +248 -246
- data/lib/rbbt/util/misc/development.rb +12 -11
- data/lib/rbbt/util/misc/exceptions.rb +117 -112
- data/lib/rbbt/util/misc/format.rb +2 -230
- data/lib/rbbt/util/misc/indiferent_hash.rb +2 -107
- data/lib/rbbt/util/misc/inspect.rb +2 -476
- data/lib/rbbt/util/misc/lock.rb +109 -106
- data/lib/rbbt/util/misc/omics.rb +9 -1
- data/lib/rbbt/util/misc/pipes.rb +765 -793
- data/lib/rbbt/util/misc/refactor.rb +20 -0
- data/lib/rbbt/util/misc/ssw.rb +27 -17
- data/lib/rbbt/util/misc/system.rb +92 -105
- data/lib/rbbt/util/misc.rb +39 -20
- data/lib/rbbt/util/named_array/refactor.rb +4 -0
- data/lib/rbbt/util/named_array.rb +3 -220
- data/lib/rbbt/util/open/refactor.rb +7 -0
- data/lib/rbbt/util/open.rb +3 -857
- data/lib/rbbt/util/procpath.rb +6 -6
- data/lib/rbbt/util/python/paths.rb +27 -0
- data/lib/rbbt/util/python/run.rb +115 -0
- data/lib/rbbt/util/python/script.rb +110 -0
- data/lib/rbbt/util/python/util.rb +3 -3
- data/lib/rbbt/util/python.rb +22 -81
- data/lib/rbbt/util/semaphore.rb +152 -148
- data/lib/rbbt/util/simpleopt.rb +9 -8
- data/lib/rbbt/util/ssh/refactor.rb +19 -0
- data/lib/rbbt/util/ssh.rb +122 -118
- data/lib/rbbt/util/tar.rb +117 -115
- data/lib/rbbt/util/tmpfile.rb +69 -67
- data/lib/rbbt/util/version.rb +2 -0
- data/lib/rbbt/workflow/refactor/entity.rb +11 -0
- data/lib/rbbt/workflow/refactor/export.rb +66 -0
- data/lib/rbbt/workflow/refactor/inputs.rb +24 -0
- data/lib/rbbt/workflow/refactor/recursive.rb +64 -0
- data/lib/rbbt/workflow/refactor/task_info.rb +66 -0
- data/lib/rbbt/workflow/refactor.rb +150 -0
- data/lib/rbbt/workflow/remote_workflow/driver/rest.rb +1 -2
- data/lib/rbbt/workflow/remote_workflow/driver/ssh.rb +55 -32
- data/lib/rbbt/workflow/remote_workflow/remote_step/rest.rb +3 -1
- data/lib/rbbt/workflow/remote_workflow/remote_step/ssh.rb +14 -5
- data/lib/rbbt/workflow/remote_workflow/remote_step.rb +19 -7
- data/lib/rbbt/workflow/remote_workflow.rb +6 -1
- data/lib/rbbt/workflow/step/run.rb +766 -766
- data/lib/rbbt/workflow/step/save_load_inputs.rb +254 -254
- data/lib/rbbt/workflow/step.rb +2 -362
- data/lib/rbbt/workflow/task.rb +118 -118
- data/lib/rbbt/workflow/usage.rb +289 -287
- data/lib/rbbt/workflow/util/archive.rb +6 -5
- data/lib/rbbt/workflow/util/data.rb +1 -1
- data/lib/rbbt/workflow/util/orchestrator.rb +249 -246
- data/lib/rbbt/workflow/util/trace.rb +79 -44
- data/lib/rbbt/workflow.rb +4 -882
- data/lib/rbbt-util.rb +21 -13
- data/lib/rbbt.rb +16 -3
- data/python/rbbt/__init__.py +96 -4
- data/python/rbbt/workflow/remote.py +104 -0
- data/python/rbbt/workflow.py +64 -0
- data/python/test.py +10 -0
- data/share/Rlib/plot.R +37 -37
- data/share/Rlib/svg.R +22 -5
- data/share/install/software/lib/install_helpers +1 -1
- data/share/rbbt_commands/hpc/list +2 -3
- data/share/rbbt_commands/hpc/orchestrate +4 -4
- data/share/rbbt_commands/hpc/tail +2 -0
- data/share/rbbt_commands/hpc/task +10 -7
- data/share/rbbt_commands/lsf/list +2 -3
- data/share/rbbt_commands/lsf/orchestrate +4 -4
- data/share/rbbt_commands/lsf/tail +2 -0
- data/share/rbbt_commands/lsf/task +10 -7
- data/share/rbbt_commands/migrate +1 -1
- data/share/rbbt_commands/pbs/list +2 -3
- data/share/rbbt_commands/pbs/orchestrate +4 -4
- data/share/rbbt_commands/pbs/tail +2 -0
- data/share/rbbt_commands/pbs/task +10 -7
- data/share/rbbt_commands/resource/produce +8 -1
- data/share/rbbt_commands/slurm/list +2 -3
- data/share/rbbt_commands/slurm/orchestrate +4 -4
- data/share/rbbt_commands/slurm/tail +2 -0
- data/share/rbbt_commands/slurm/task +10 -7
- data/share/rbbt_commands/system/clean +5 -5
- data/share/rbbt_commands/system/status +5 -5
- data/share/rbbt_commands/tsv/get +2 -3
- data/share/rbbt_commands/tsv/info +10 -13
- data/share/rbbt_commands/tsv/keys +18 -14
- data/share/rbbt_commands/tsv/slice +2 -2
- data/share/rbbt_commands/tsv/transpose +6 -2
- data/share/rbbt_commands/workflow/info +20 -24
- data/share/rbbt_commands/workflow/list +1 -1
- data/share/rbbt_commands/workflow/prov +20 -13
- data/share/rbbt_commands/workflow/retry +43 -0
- data/share/rbbt_commands/workflow/server +12 -2
- data/share/rbbt_commands/workflow/task +80 -73
- data/share/rbbt_commands/workflow/write_info +26 -9
- data/share/software/opt/ssw/ssw.c +861 -0
- data/share/software/opt/ssw/ssw.h +130 -0
- data/share/workflow_config.ru +3 -3
- metadata +45 -6
data/lib/rbbt/util/color.rb
CHANGED
@@ -1,269 +1,269 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
class Color
|
25
|
-
|
26
|
-
attr_reader :r, :g, :b, :a
|
27
|
-
|
28
|
-
# Table for conversion to hex
|
29
|
-
HEXVAL = (('0'..'9').to_a).concat(('A'..'F').to_a).freeze
|
30
|
-
# Default value for #darken, #lighten etc.
|
31
|
-
BRIGHTNESS_DEFAULT = 0.2
|
32
|
-
|
33
|
-
SOLARIZED = {
|
34
|
-
:base03 => '#002b36',
|
35
|
-
:base02 => '#073642',
|
36
|
-
:base01 => '#586e75',
|
37
|
-
:base00 => '#657b83',
|
38
|
-
:base0 => '#839496',
|
39
|
-
:base1 => '#93a1a1',
|
40
|
-
:base2 => '#eee8d5',
|
41
|
-
:base3 => '#fdf6e3',
|
42
|
-
:yellow => '#b58900',
|
43
|
-
:orange => '#cb4b16',
|
44
|
-
:red => '#dc322f',
|
45
|
-
:magenta => '#d33682',
|
46
|
-
:violet => '#6c71c4',
|
47
|
-
:blue => '#268bd2',
|
48
|
-
:cyan => '#2aa198',
|
49
|
-
:green => '#859900',
|
50
|
-
}
|
51
|
-
|
52
|
-
# Constructor. Inits to white (#FFFFFF) by default, or accepts any params
|
53
|
-
# supported by #parse.
|
54
|
-
def initialize(*args)
|
55
|
-
@r = 255
|
56
|
-
@g = 255
|
57
|
-
@b = 255
|
58
|
-
@a = 255
|
59
|
-
|
60
|
-
if args.size.between?(3,4)
|
61
|
-
self.r = args[0]
|
62
|
-
self.g = args[1]
|
63
|
-
self.b = args[2]
|
64
|
-
self.a = args[3] if args[3]
|
65
|
-
else
|
66
|
-
set(*args)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# All-purpose setter - pass in another Color, '#000000', rgb vals... whatever
|
71
|
-
def set(*args)
|
72
|
-
val = Color.parse(*args)
|
73
|
-
unless val.nil?
|
74
|
-
self.r = val.r
|
75
|
-
self.g = val.g
|
76
|
-
self.b = val.b
|
77
|
-
self.a = val.a
|
78
|
-
end
|
79
|
-
self
|
80
|
-
end
|
81
|
-
|
82
|
-
# Test for equality, accepts string vals as well, eg Color.new('aaa') == '#AAAAAA' => true
|
83
|
-
def ==(val)
|
84
|
-
val = Color.parse(val)
|
85
|
-
return false if val.nil?
|
86
|
-
return r == val.r && g == val.g && b == val.b && a == val.a
|
87
|
-
end
|
88
|
-
|
89
|
-
# Setters for individual channels - take 0-255 or '00'-'FF' values
|
90
|
-
def r=(val); @r = from_hex(val); end
|
91
|
-
def g=(val); @g = from_hex(val); end
|
92
|
-
def b=(val); @b = from_hex(val); end
|
93
|
-
def a=(val); @a = from_hex(val); end
|
94
|
-
|
95
|
-
# Attempt to read in a string and parse it into values
|
96
|
-
def self.parse(*args)
|
97
|
-
case args.size
|
98
|
-
|
99
|
-
when 0 then
|
100
|
-
return nil
|
101
|
-
|
102
|
-
when 1 then
|
103
|
-
val = args[0]
|
104
|
-
|
105
|
-
# Trivial parse... :-)
|
106
|
-
return val if val.is_a?(Color)
|
107
|
-
|
108
|
-
# Single value, assume grayscale
|
109
|
-
return Color.new(val, val, val) if val.is_a?(Numeric)
|
110
|
-
|
111
|
-
# Assume string
|
112
|
-
str = val.to_s.upcase
|
113
|
-
str = str[/[0-9A-F]{3,8}/] || ''
|
114
|
-
case str.size
|
115
|
-
when 3, 4 then
|
116
|
-
r, g, b, a = str.scan(/[0-9A-F]/)
|
117
|
-
when 6,8 then
|
118
|
-
r, g, b, a = str.scan(/[0-9A-F]{2}/)
|
119
|
-
else
|
120
|
-
return nil
|
121
|
-
end
|
122
|
-
|
123
|
-
return Color.new(r,g,b,a || 255)
|
124
|
-
|
125
|
-
when 3,4 then
|
126
|
-
return Color.new(*args)
|
127
|
-
|
128
|
-
end
|
129
|
-
nil
|
130
|
-
end
|
131
|
-
|
132
|
-
def inspect
|
133
|
-
to_s(true)
|
134
|
-
end
|
135
|
-
|
136
|
-
def to_s(add_hash = true)
|
137
|
-
trans? ? to_rgba(add_hash) : to_rgb(add_hash)
|
138
|
-
end
|
139
|
-
|
140
|
-
def to_rgb(add_hash = true)
|
141
|
-
(add_hash ? '#' : '') + to_hex(r) + to_hex(g) + to_hex(b)
|
142
|
-
end
|
143
|
-
|
144
|
-
def to_rgba(add_hash = true)
|
145
|
-
to_rgb(add_hash) + to_hex(a)
|
146
|
-
end
|
147
|
-
|
148
|
-
def opaque?
|
149
|
-
@a == 255
|
150
|
-
end
|
151
|
-
|
152
|
-
def trans?
|
153
|
-
@a != 255
|
154
|
-
end
|
155
|
-
|
156
|
-
def grayscale?
|
157
|
-
@r == @g && @g == @b
|
158
|
-
end
|
159
|
-
|
160
|
-
# Lighten color towards white. 0.0 is a no-op, 1.0 will return #FFFFFF
|
161
|
-
def lighten(amt = BRIGHTNESS_DEFAULT)
|
162
|
-
return self if amt <= 0
|
163
|
-
return WHITE if amt >= 1.0
|
164
|
-
val = Color.new(self)
|
165
|
-
val.r += ((255-val.r) * amt).to_i
|
166
|
-
val.g += ((255-val.g) * amt).to_i
|
167
|
-
val.b += ((255-val.b) * amt).to_i
|
168
|
-
val
|
169
|
-
end
|
170
|
-
|
171
|
-
# In place version of #lighten
|
172
|
-
def lighten!(amt = BRIGHTNESS_DEFAULT)
|
173
|
-
set(lighten(amt))
|
174
|
-
self
|
175
|
-
end
|
176
|
-
|
177
|
-
# Darken a color towards full black. 0.0 is a no-op, 1.0 will return #000000
|
178
|
-
def darken(amt = BRIGHTNESS_DEFAULT)
|
179
|
-
return self if amt <= 0
|
180
|
-
return BLACK if amt >= 1.0
|
181
|
-
val = Color.new(self)
|
182
|
-
val.r -= (val.r * amt).to_i
|
183
|
-
val.g -= (val.g * amt).to_i
|
184
|
-
val.b -= (val.b * amt).to_i
|
185
|
-
val
|
186
|
-
end
|
187
|
-
|
188
|
-
# In place version of #darken
|
189
|
-
def darken!(amt = BRIGHTNESS_DEFAULT)
|
190
|
-
set(darken(amt))
|
191
|
-
self
|
192
|
-
end
|
193
|
-
|
194
|
-
# Convert to grayscale, using perception-based weighting
|
195
|
-
def grayscale
|
196
|
-
val = Color.new(self)
|
197
|
-
val.r = val.g = val.b = (0.2126 * val.r + 0.7152 * val.g + 0.0722 * val.b)
|
198
|
-
val
|
199
|
-
end
|
200
|
-
|
201
|
-
# In place version of #grayscale
|
202
|
-
def grayscale!
|
203
|
-
set(grayscale)
|
204
|
-
self
|
205
|
-
end
|
206
|
-
|
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
|
-
val = Color.new(self)
|
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
|
-
val
|
218
|
-
end
|
219
|
-
|
220
|
-
# In place version of #blend
|
221
|
-
def blend!(other, amt)
|
222
|
-
set(blend(other, amt))
|
223
|
-
self
|
224
|
-
end
|
225
|
-
|
226
|
-
# Class-level version for explicit blends of two values, useful with constants
|
227
|
-
def self.blend(col1, col2, amt)
|
228
|
-
col1 = Color.parse(col1)
|
229
|
-
col2 = Color.parse(col2)
|
230
|
-
col1.blend(col2, amt)
|
231
|
-
end
|
232
|
-
|
233
|
-
protected
|
234
|
-
|
235
|
-
# Convert int to string hex, eg 255 => 'FF'
|
236
|
-
def to_hex(val)
|
237
|
-
HEXVAL[val / 16] + HEXVAL[val % 16]
|
238
|
-
end
|
239
|
-
|
240
|
-
# Convert int or string to int, eg 80 => 80, 'FF' => 255, '7' => 119
|
241
|
-
def from_hex(val)
|
242
|
-
if val.is_a?(String)
|
243
|
-
# Double up if single char form
|
244
|
-
val = val + val if val.size == 1
|
245
|
-
# Convert to integer
|
246
|
-
val = val.hex
|
247
|
-
end
|
248
|
-
# Clamp
|
249
|
-
val = 0 if val < 0
|
250
|
-
val = 255 if val > 255
|
251
|
-
val
|
252
|
-
end
|
253
|
-
|
254
|
-
public
|
255
|
-
|
256
|
-
# Some constants for general use
|
257
|
-
WHITE = Color.new(255,255,255).freeze
|
258
|
-
BLACK = Color.new(0,0,0).freeze
|
259
|
-
|
260
|
-
end
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
def rgb(*args)
|
266
|
-
Color.parse(*args)
|
267
|
-
end
|
268
|
-
|
269
|
-
|
1
|
+
## Copyright (c) 2007 McClain Looney
|
2
|
+
##
|
3
|
+
## Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
## of this software and associated documentation files (the "Software"), to deal
|
5
|
+
## in the Software without restriction, including without limitation the rights
|
6
|
+
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
## copies of the Software, and to permit persons to whom the Software is
|
8
|
+
## furnished to do so, subject to the following conditions:
|
9
|
+
##
|
10
|
+
## The above copyright notice and this permission notice shall be included in
|
11
|
+
## all copies or substantial portions of the Software.
|
12
|
+
##
|
13
|
+
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
## THE SOFTWARE.
|
20
|
+
#
|
21
|
+
#
|
22
|
+
## Implements a color (r,g,b + a) with conversion to/from web format (eg #aabbcc), and
|
23
|
+
## with a number of utilities to lighten, darken and blend values.
|
24
|
+
#class Color
|
25
|
+
#
|
26
|
+
# attr_reader :r, :g, :b, :a
|
27
|
+
#
|
28
|
+
# # Table for conversion to hex
|
29
|
+
# HEXVAL = (('0'..'9').to_a).concat(('A'..'F').to_a).freeze
|
30
|
+
# # Default value for #darken, #lighten etc.
|
31
|
+
# BRIGHTNESS_DEFAULT = 0.2
|
32
|
+
#
|
33
|
+
# SOLARIZED = {
|
34
|
+
# :base03 => '#002b36',
|
35
|
+
# :base02 => '#073642',
|
36
|
+
# :base01 => '#586e75',
|
37
|
+
# :base00 => '#657b83',
|
38
|
+
# :base0 => '#839496',
|
39
|
+
# :base1 => '#93a1a1',
|
40
|
+
# :base2 => '#eee8d5',
|
41
|
+
# :base3 => '#fdf6e3',
|
42
|
+
# :yellow => '#b58900',
|
43
|
+
# :orange => '#cb4b16',
|
44
|
+
# :red => '#dc322f',
|
45
|
+
# :magenta => '#d33682',
|
46
|
+
# :violet => '#6c71c4',
|
47
|
+
# :blue => '#268bd2',
|
48
|
+
# :cyan => '#2aa198',
|
49
|
+
# :green => '#859900',
|
50
|
+
# }
|
51
|
+
#
|
52
|
+
# # Constructor. Inits to white (#FFFFFF) by default, or accepts any params
|
53
|
+
# # supported by #parse.
|
54
|
+
# def initialize(*args)
|
55
|
+
# @r = 255
|
56
|
+
# @g = 255
|
57
|
+
# @b = 255
|
58
|
+
# @a = 255
|
59
|
+
#
|
60
|
+
# if args.size.between?(3,4)
|
61
|
+
# self.r = args[0]
|
62
|
+
# self.g = args[1]
|
63
|
+
# self.b = args[2]
|
64
|
+
# self.a = args[3] if args[3]
|
65
|
+
# else
|
66
|
+
# set(*args)
|
67
|
+
# end
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# # All-purpose setter - pass in another Color, '#000000', rgb vals... whatever
|
71
|
+
# def set(*args)
|
72
|
+
# val = Color.parse(*args)
|
73
|
+
# unless val.nil?
|
74
|
+
# self.r = val.r
|
75
|
+
# self.g = val.g
|
76
|
+
# self.b = val.b
|
77
|
+
# self.a = val.a
|
78
|
+
# end
|
79
|
+
# self
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# # Test for equality, accepts string vals as well, eg Color.new('aaa') == '#AAAAAA' => true
|
83
|
+
# def ==(val)
|
84
|
+
# val = Color.parse(val)
|
85
|
+
# return false if val.nil?
|
86
|
+
# return r == val.r && g == val.g && b == val.b && a == val.a
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# # Setters for individual channels - take 0-255 or '00'-'FF' values
|
90
|
+
# def r=(val); @r = from_hex(val); end
|
91
|
+
# def g=(val); @g = from_hex(val); end
|
92
|
+
# def b=(val); @b = from_hex(val); end
|
93
|
+
# def a=(val); @a = from_hex(val); end
|
94
|
+
#
|
95
|
+
# # Attempt to read in a string and parse it into values
|
96
|
+
# def self.parse(*args)
|
97
|
+
# case args.size
|
98
|
+
#
|
99
|
+
# when 0 then
|
100
|
+
# return nil
|
101
|
+
#
|
102
|
+
# when 1 then
|
103
|
+
# val = args[0]
|
104
|
+
#
|
105
|
+
# # Trivial parse... :-)
|
106
|
+
# return val if val.is_a?(Color)
|
107
|
+
#
|
108
|
+
# # Single value, assume grayscale
|
109
|
+
# return Color.new(val, val, val) if val.is_a?(Numeric)
|
110
|
+
#
|
111
|
+
# # Assume string
|
112
|
+
# str = val.to_s.upcase
|
113
|
+
# str = str[/[0-9A-F]{3,8}/] || ''
|
114
|
+
# case str.size
|
115
|
+
# when 3, 4 then
|
116
|
+
# r, g, b, a = str.scan(/[0-9A-F]/)
|
117
|
+
# when 6,8 then
|
118
|
+
# r, g, b, a = str.scan(/[0-9A-F]{2}/)
|
119
|
+
# else
|
120
|
+
# return nil
|
121
|
+
# end
|
122
|
+
#
|
123
|
+
# return Color.new(r,g,b,a || 255)
|
124
|
+
#
|
125
|
+
# when 3,4 then
|
126
|
+
# return Color.new(*args)
|
127
|
+
#
|
128
|
+
# end
|
129
|
+
# nil
|
130
|
+
# end
|
131
|
+
#
|
132
|
+
# def inspect
|
133
|
+
# to_s(true)
|
134
|
+
# end
|
135
|
+
#
|
136
|
+
# def to_s(add_hash = true)
|
137
|
+
# trans? ? to_rgba(add_hash) : to_rgb(add_hash)
|
138
|
+
# end
|
139
|
+
#
|
140
|
+
# def to_rgb(add_hash = true)
|
141
|
+
# (add_hash ? '#' : '') + to_hex(r) + to_hex(g) + to_hex(b)
|
142
|
+
# end
|
143
|
+
#
|
144
|
+
# def to_rgba(add_hash = true)
|
145
|
+
# to_rgb(add_hash) + to_hex(a)
|
146
|
+
# end
|
147
|
+
#
|
148
|
+
# def opaque?
|
149
|
+
# @a == 255
|
150
|
+
# end
|
151
|
+
#
|
152
|
+
# def trans?
|
153
|
+
# @a != 255
|
154
|
+
# end
|
155
|
+
#
|
156
|
+
# def grayscale?
|
157
|
+
# @r == @g && @g == @b
|
158
|
+
# end
|
159
|
+
#
|
160
|
+
# # Lighten color towards white. 0.0 is a no-op, 1.0 will return #FFFFFF
|
161
|
+
# def lighten(amt = BRIGHTNESS_DEFAULT)
|
162
|
+
# return self if amt <= 0
|
163
|
+
# return WHITE if amt >= 1.0
|
164
|
+
# val = Color.new(self)
|
165
|
+
# val.r += ((255-val.r) * amt).to_i
|
166
|
+
# val.g += ((255-val.g) * amt).to_i
|
167
|
+
# val.b += ((255-val.b) * amt).to_i
|
168
|
+
# val
|
169
|
+
# end
|
170
|
+
#
|
171
|
+
# # In place version of #lighten
|
172
|
+
# def lighten!(amt = BRIGHTNESS_DEFAULT)
|
173
|
+
# set(lighten(amt))
|
174
|
+
# self
|
175
|
+
# end
|
176
|
+
#
|
177
|
+
# # Darken a color towards full black. 0.0 is a no-op, 1.0 will return #000000
|
178
|
+
# def darken(amt = BRIGHTNESS_DEFAULT)
|
179
|
+
# return self if amt <= 0
|
180
|
+
# return BLACK if amt >= 1.0
|
181
|
+
# val = Color.new(self)
|
182
|
+
# val.r -= (val.r * amt).to_i
|
183
|
+
# val.g -= (val.g * amt).to_i
|
184
|
+
# val.b -= (val.b * amt).to_i
|
185
|
+
# val
|
186
|
+
# end
|
187
|
+
#
|
188
|
+
# # In place version of #darken
|
189
|
+
# def darken!(amt = BRIGHTNESS_DEFAULT)
|
190
|
+
# set(darken(amt))
|
191
|
+
# self
|
192
|
+
# end
|
193
|
+
#
|
194
|
+
# # Convert to grayscale, using perception-based weighting
|
195
|
+
# def grayscale
|
196
|
+
# val = Color.new(self)
|
197
|
+
# val.r = val.g = val.b = (0.2126 * val.r + 0.7152 * val.g + 0.0722 * val.b)
|
198
|
+
# val
|
199
|
+
# end
|
200
|
+
#
|
201
|
+
# # In place version of #grayscale
|
202
|
+
# def grayscale!
|
203
|
+
# set(grayscale)
|
204
|
+
# self
|
205
|
+
# end
|
206
|
+
#
|
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
|
+
# val = Color.new(self)
|
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
|
+
# val
|
218
|
+
# end
|
219
|
+
#
|
220
|
+
# # In place version of #blend
|
221
|
+
# def blend!(other, amt)
|
222
|
+
# set(blend(other, amt))
|
223
|
+
# self
|
224
|
+
# end
|
225
|
+
#
|
226
|
+
# # Class-level version for explicit blends of two values, useful with constants
|
227
|
+
# def self.blend(col1, col2, amt)
|
228
|
+
# col1 = Color.parse(col1)
|
229
|
+
# col2 = Color.parse(col2)
|
230
|
+
# col1.blend(col2, amt)
|
231
|
+
# end
|
232
|
+
#
|
233
|
+
# protected
|
234
|
+
#
|
235
|
+
# # Convert int to string hex, eg 255 => 'FF'
|
236
|
+
# def to_hex(val)
|
237
|
+
# HEXVAL[val / 16] + HEXVAL[val % 16]
|
238
|
+
# end
|
239
|
+
#
|
240
|
+
# # Convert int or string to int, eg 80 => 80, 'FF' => 255, '7' => 119
|
241
|
+
# def from_hex(val)
|
242
|
+
# if val.is_a?(String)
|
243
|
+
# # Double up if single char form
|
244
|
+
# val = val + val if val.size == 1
|
245
|
+
# # Convert to integer
|
246
|
+
# val = val.hex
|
247
|
+
# end
|
248
|
+
# # Clamp
|
249
|
+
# val = 0 if val < 0
|
250
|
+
# val = 255 if val > 255
|
251
|
+
# val
|
252
|
+
# end
|
253
|
+
#
|
254
|
+
# public
|
255
|
+
#
|
256
|
+
# # Some constants for general use
|
257
|
+
# WHITE = Color.new(255,255,255).freeze
|
258
|
+
# BLACK = Color.new(0,0,0).freeze
|
259
|
+
#
|
260
|
+
#end
|
261
|
+
#
|
262
|
+
## "Global" method for creating Color objects, eg:
|
263
|
+
## new_color = rgb(params[:new_color])
|
264
|
+
## style="border: 1px solid <%= rgb(10,50,80).lighten %>"
|
265
|
+
#def rgb(*args)
|
266
|
+
# Color.parse(*args)
|
267
|
+
#end
|
268
|
+
#
|
269
|
+
#
|