yummi 0.5.2 → 0.6.0

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.
@@ -22,39 +22,27 @@
22
22
 
23
23
  Yummi::Color::load_color_map(
24
24
  :default => {
25
- :key_code => 0,
25
+ :key_code => '0;3',
26
26
  :schema => Yummi::Color::Schema::NORMAL_COLORS
27
27
  },
28
- :intense => {
29
- :key_code => 1,
30
- :schema => Yummi::Color::Schema::ALTERNATE_COLORS
31
- },
32
- :strong => {
33
- :key_code => 1,
34
- :schema => Yummi::Color::Schema::ALTERNATE_COLORS
35
- },
36
- :underscore => {
37
- :key_code => 4,
28
+ :reverse => {
29
+ :key_code => '0;4',
38
30
  :schema => Yummi::Color::Schema::NORMAL_COLORS
39
31
  },
40
- :underscored => {
41
- :key_code => 4,
42
- :schema => Yummi::Color::Schema::NORMAL_COLORS
43
- },
44
- :blink => {
45
- :key_code => 5,
46
- :schema => Yummi::Color::Schema::NORMAL_COLORS
32
+ [:intense, :strong, :bold] => {
33
+ :key_code => '1;3',
34
+ :schema => Yummi::Color::Schema::ALTERNATE_COLORS
47
35
  },
48
- :blinking => {
49
- :key_code => 5,
36
+ [:underline, :underscore, :underscored] => {
37
+ :key_code => '4;3',
50
38
  :schema => Yummi::Color::Schema::NORMAL_COLORS
51
39
  },
52
- :highlight => {
53
- :key_code => 7,
40
+ [:blink, :blinking] => {
41
+ :key_code => '5;3',
54
42
  :schema => Yummi::Color::Schema::NORMAL_COLORS
55
43
  },
56
- :highlighted => {
57
- :key_code => 7,
44
+ [:highlight, :highlighted] => {
45
+ :key_code => '7;3',
58
46
  :schema => Yummi::Color::Schema::NORMAL_COLORS
59
47
  }
60
48
  )
@@ -36,12 +36,11 @@ module Yummi
36
36
  #
37
37
  # === Args
38
38
  #
39
- # An array of arguments that will be passed to :call: method to get the color. By
40
- # convention, the first argument must be the object to colorize (to_s is called on it
41
- # for getting the text to colorize).
39
+ # A context or a value.
42
40
  #
43
- def colorize (*args)
44
- Yummi.colorize args.first.to_s, color_for(args)
41
+ def colorize (arg)
42
+ arg = Yummi::Context::new(arg) unless arg.is_a? Context
43
+ Yummi.colorize arg.value.to_s, color_for(arg)
45
44
  end
46
45
 
47
46
  #
@@ -49,11 +48,11 @@ module Yummi
49
48
  #
50
49
  # === Args
51
50
  #
52
- # An array of arguments that will be passed to :call: method to get the color. By
53
- # convention, the first argument must be the object to colorize (to_s is called on it
54
- # for getting the text to colorize).#
55
- def color_for (*args)
56
- call(*args)
51
+ # A context or a value.
52
+ #
53
+ def color_for (arg)
54
+ arg = Yummi::Context::new(arg) unless arg.is_a? Context
55
+ call(arg)
57
56
  end
58
57
 
59
58
  end
@@ -80,16 +79,6 @@ module Yummi
80
79
  join.extend Colorizer
81
80
  end
82
81
 
83
- # Returns a new instance of #DataEvalColorizer
84
- def self.by_data_eval &block
85
- DataEvalColorizer::new(&block)
86
- end
87
-
88
- # Returns a new instance of #EvalColorizer
89
- def self.by_eval &block
90
- EvalColorizer::new(&block)
91
- end
92
-
93
82
  # Returns a new instance of #StripeColorizer
94
83
  def self.stripe *colors
95
84
  StripeColorizer::new(*colors)
@@ -104,13 +93,14 @@ module Yummi
104
93
  # A colorizer that uses the given color.
105
94
  #
106
95
  def self.with color
107
- Yummi::to_colorize do |value|
96
+ Yummi::to_colorize do |ctx|
108
97
  color
109
98
  end
110
99
  end
111
100
 
112
101
  def self.when params
113
- Yummi::to_colorize do |value|
102
+ Yummi::to_colorize do |ctx|
103
+ value = ctx.value
114
104
  color = params[value]
115
105
  return color if color
116
106
  if value.respond_to? :to_sym
@@ -133,7 +123,8 @@ module Yummi
133
123
  # - if_false: color used if the value is false (defaults to yellow)
134
124
  #
135
125
  def self.boolean params = {}
136
- Yummi::to_colorize do |value|
126
+ Yummi::to_colorize do |ctx|
127
+ value = ctx.value
137
128
  if value.to_s.downcase == "true"
138
129
  (params[:if_true] or :green)
139
130
  else
@@ -149,10 +140,21 @@ module Yummi
149
140
  # - MINIMUN_VALUE: COLOR_TO_USE
150
141
  #
151
142
  def self.threshold params
152
- colorizer = lambda do |value|
153
- params.sort.reverse_each do |limit, color|
154
- return color if value > limit
143
+ params = params.dup
144
+ mode = (params.delete(:mode) or :min)
145
+ colorizer = lambda do |ctx|
146
+ value = ctx.value
147
+ case mode.to_sym
148
+ when :min
149
+ params.sort.reverse_each do |limit, color|
150
+ return color if value >= limit
151
+ end
152
+ when :max
153
+ params.sort.each do |limit, color|
154
+ return color if value <= limit
155
+ end
155
156
  end
157
+ nil
156
158
  end
157
159
  Yummi::to_colorize(&colorizer)
158
160
  end
@@ -162,7 +164,8 @@ module Yummi
162
164
  end
163
165
 
164
166
  def self.numeric params
165
- Yummi::to_format do |value|
167
+ Yummi::to_format do |ctx|
168
+ value = ctx.value
166
169
  if params[:negative] and value < 0
167
170
  params[:negative]
168
171
  elsif params[:positive] and value > 0
@@ -177,29 +180,34 @@ module Yummi
177
180
  include Yummi::Colorizer
178
181
 
179
182
  def initialize(params)
180
- @max = params[:max]
183
+ @max = params[:max].to_sym
181
184
  @free = params[:free]
182
185
  @using = params[:using]
183
- @color = params[:color] || {
186
+ color = {
184
187
  :bad => :red,
185
188
  :warn => :yellow,
186
189
  :good => :green
187
- }
188
- @threshold = params[:threshold] || {
190
+ }.merge!(params[:colors] || {})
191
+ threshold = {
189
192
  :warn => 0.30,
190
- :bad => 0.15
191
- }
193
+ :bad => 0.15,
194
+ :good => 1
195
+ }.merge!(params[:threshold] || {})
196
+
197
+ threshold_params = { :mode => :max }
198
+ color.each do |type, name|
199
+ threshold_params[threshold[type]] = name
200
+ end
201
+ @threshold = Yummi::Colorizers.threshold threshold_params
192
202
  end
193
203
 
194
204
  def call(data)
195
- max = data[@max.to_sym].to_f
205
+ max = data[@max].to_f
196
206
  free = @using ? max - data[@using.to_sym].to_f : data[@free.to_sym].to_f
197
207
 
198
208
  percentage = free / max
199
209
 
200
- return @color[:bad] if percentage <= @threshold[:bad]
201
- return @color[:warn] if percentage <= @threshold[:warn]
202
- @color[:good]
210
+ @threshold.color_for(percentage)
203
211
  end
204
212
 
205
213
  end
@@ -254,8 +262,8 @@ module Yummi
254
262
  @last_color = nil
255
263
  end
256
264
 
257
- def call *args
258
- line = args.first.to_s
265
+ def call ctx
266
+ line = ctx.value.to_s
259
267
  @patterns.each do |regex, color|
260
268
  if regex.match(line)
261
269
  @last_color = color
@@ -284,81 +292,6 @@ module Yummi
284
292
 
285
293
  end
286
294
 
287
- #
288
- # A colorizer that evaluates a main block and returns a color based on other blocks.
289
- #
290
- # The main block must be compatible with the colorizing type (receiving a column
291
- # value in case of a table column colorizer or the row index and row value in case
292
- # of a table row colorizer).
293
- #
294
- # === Example
295
- #
296
- # # assuming that the table has :max and :current aliases
297
- # colorizer = DataEvalColorizer::new { |index, data| data[:current] / data[:max] }
298
- # # the result of the expression above will be passed to this block
299
- # colorizer.use(:red) { |value| value >= 0.9 }
300
- #
301
- # table.using_row.colorize :current, :using => colorizer
302
- #
303
- class EvalColorizer
304
- include Yummi::Colorizer
305
-
306
- def initialize (&block)
307
- @block = block
308
- @colors = []
309
- @eval_blocks = []
310
- end
311
-
312
- #
313
- # Uses the given color if the given block returns something when evaluated with the
314
- # result of main block.
315
- #
316
- # An objtect that responds to :call may also be used.
317
- #
318
- def use (color, component = nil, &eval_block)
319
- @colors << color
320
- @eval_blocks << (component or eval_block)
321
- end
322
-
323
- # Resolves the value using the main block and given arguments
324
- def resolve_value (*args)
325
- @block.call(*args)
326
- end
327
-
328
- def call (*args)
329
- value = resolve_value(*args)
330
- @eval_blocks.each_index do |i|
331
- return @colors[i] if @eval_blocks[i].call(value)
332
- end
333
- nil
334
- end
335
-
336
- end
337
-
338
- #
339
- # A colorizer that evaluates a main block and returns a color based on other blocks.
340
- #
341
- # The main block can receive any parameters and the names must be aliases the current
342
- # evaluated data.
343
- #
344
- # === Example
345
- #
346
- # # assuming that the table has :max and :current aliases
347
- # colorizer = DataEvalColorizer::new { |max, current| current / max }
348
- # # the result of the expression above will be passed to this block
349
- # colorizer.use(:red) { |value| value >= 0.9 }
350
- #
351
- # table.using_row.colorize :current, :using => colorizer
352
- #
353
- class DataEvalColorizer < EvalColorizer
354
- include Yummi::BlockHandler, Yummi::Colorizer
355
-
356
- def resolve_value (*args)
357
- block_call args.first, &@block # by convention, the first arg is data
358
- end
359
-
360
- end
361
-
362
295
  end
363
296
 
364
297
  end
@@ -26,7 +26,8 @@ module Yummi
26
26
  module FormatterBlock
27
27
 
28
28
  # Calls the :call: method
29
- def format (value)
29
+ def format (arg)
30
+ arg = Yummi::Context::new(arg) unless arg.is_a? Context
30
31
  call value
31
32
  end
32
33
 
@@ -49,7 +50,8 @@ module Yummi
49
50
  # :if_false => String to use when value is false
50
51
  #
51
52
  def self.boolean params = {}
52
- Yummi::to_format do |value|
53
+ Yummi::to_format do |ctx|
54
+ value = ctx.value
53
55
  if value.to_s.downcase == "true"
54
56
  (params[:if_true] or "Yes")
55
57
  else
@@ -60,14 +62,16 @@ module Yummi
60
62
 
61
63
  # A formatter to round float values
62
64
  def self.round precision
63
- Yummi::to_format do |value|
65
+ Yummi::to_format do |ctx|
66
+ value = ctx.value
64
67
  "%.#{precision}f" % value
65
68
  end
66
69
  end
67
70
 
68
71
  # A formatter that uses the given format
69
72
  def self.with format
70
- Yummi::to_format do |value|
73
+ Yummi::to_format do |ctx|
74
+ value = ctx.value
71
75
  format % value
72
76
  end
73
77
  end
@@ -82,7 +86,8 @@ module Yummi
82
86
  # :positive => format to use when value is positive
83
87
  #
84
88
  def self.numeric params
85
- Yummi::to_format do |value|
89
+ Yummi::to_format do |ctx|
90
+ value = ctx.value
86
91
  if params[:negative] and value < 0
87
92
  params[:negative] % value.abs
88
93
  elsif params[:positive] and value > 0
@@ -100,7 +105,8 @@ module Yummi
100
105
  # The precision to use (defaults to 3)
101
106
  #
102
107
  def self.percentage precision = 3
103
- Yummi::to_format do |value|
108
+ Yummi::to_format do |ctx|
109
+ value = ctx.value
104
110
  "%.#{precision}f%%" % (value * 100)
105
111
  end
106
112
  end
@@ -130,7 +136,8 @@ module Yummi
130
136
  # See #BYTE_MODES
131
137
  #
132
138
  def self.byte params = {}
133
- Yummi::to_format do |value|
139
+ Yummi::to_format do |ctx|
140
+ value = ctx.value
134
141
  value = value.to_i if value.is_a? String
135
142
  mode = (params[:mode] or :iec)
136
143
  range = BYTE_MODES[mode][:range]
data/lib/yummi/logger.rb CHANGED
@@ -60,7 +60,7 @@ module Yummi
60
60
  @colors = {
61
61
  :debug => nil,
62
62
  :info => :green,
63
- :warn => :brown,
63
+ :warn => :yellow,
64
64
  :error => :red,
65
65
  :fatal => :intense_red,
66
66
  :any => :intense_gray
@@ -8,5 +8,5 @@ patterns:
8
8
  Warning : yellow
9
9
  Error : red
10
10
  Critical : intense_red
11
- Alert : highlight_red
12
- Emergency : blink_red
11
+ Alert : intense_underline_red
12
+ Emergency : highlight_red
data/lib/yummi/table.rb CHANGED
@@ -23,8 +23,6 @@
23
23
  module Yummi
24
24
  # A Table that supports colorizing title, header, values and also formatting the values.
25
25
  class Table
26
- # The table data. It holds a two dimensional array.
27
- attr_accessor :data
28
26
  # The table title
29
27
  attr_accessor :title
30
28
  # The table description
@@ -75,8 +73,7 @@ module Yummi
75
73
 
76
74
  @align = [:left]
77
75
  @components = {}
78
- #@contexts = []
79
- @context_rows = []
76
+ @contexts = [:default]
80
77
  _define_ :default
81
78
  @current_context = :default
82
79
  end
@@ -91,18 +88,50 @@ module Yummi
91
88
  @no_colors = true
92
89
  end
93
90
 
94
- def context params = {}
95
- params ||= {}
96
- index = @context_rows.size #@contexts.size
97
- _define_ index
98
- #@contexts.insert(index, context)
99
- @context_rows.insert(index, (params[:rows] or 1))
100
-
101
- @current_context = index
102
- yield if block_given?
103
- @current_context = :default
91
+ #
92
+ # Groups definitions for a specified group of rows at the bottom of the table.
93
+ # Every customization can be used (formatter/colorizer for null values, for rows
94
+ # and columns). Customizations must be done in the given block.
95
+ #
96
+ # Subsequent calls to this method creates different groups.
97
+ #
98
+ # === Args
99
+ # +:rows+:: The number of rows to group using the customizations in the block
100
+ #
101
+ # === Examples
102
+ #
103
+ # table.bottom :rows => 3 do
104
+ # table.colorize :subtotal, :with => :green
105
+ # table.format :approved, :using => Yummi::Formatters::boolean
106
+ # end
107
+ # table.bottom { table.colorize :total, :with => :white }
108
+ #
109
+ def bottom params = {}, &block
110
+ index = @contexts.size
111
+ _context_ index, params, &block
104
112
  end
105
113
 
114
+ #
115
+ # Groups definitions for a specified group of rows at the top of the table.
116
+ # Every customization can be used (formatter/colorizer for null values, for rows
117
+ # and columns). Customizations must be done in the given block.
118
+ #
119
+ # Subsequent calls to this method creates different groups.
120
+ #
121
+ # === Args
122
+ # +:rows+:: The number of rows to group using the customizations in the block
123
+ #
124
+ # === Examples
125
+ #
126
+ # table.top :rows => 3 do
127
+ # table.colorize :subtotal, :with => :green
128
+ # table.format :approved, :using => Yummi::Formatters::boolean
129
+ # end
130
+ # table.top { table.colorize :total, :with => :white }
131
+ #
132
+ def top params = {}, &block
133
+ _context_ 0, params, &block
134
+ end
106
135
 
107
136
  # Sets the table print layout.
108
137
  def layout=(layout)
@@ -127,7 +156,7 @@ module Yummi
127
156
  index = parse_index(index)
128
157
  columns = []
129
158
  @data.each do |row|
130
- columns << row[index]
159
+ columns << row_to_array(row)[index].value
131
160
  end
132
161
  columns
133
162
  end
@@ -193,39 +222,20 @@ module Yummi
193
222
  component[:row_colorizer] = obj
194
223
  end
195
224
 
196
- #
197
- # Indicates that the column colorizer (#colorize) should receive the entire row as the
198
- # argument instead of just the column value for all definitions inside of the given
199
- # block.
200
- #
201
- # === Example
202
- #
203
- # table.using_row do
204
- # table.colorize(:value) { |row| :red if row[:value] < row[:average] }
205
- # end
206
- #
207
- def using_row
208
- @using_row = true
209
- yield if block_given?
210
- @using_row = false
225
+ # Sets the table data
226
+ def data= (data)
227
+ @data = data
211
228
  end
212
229
 
213
230
  #
214
231
  # Adds the given data as a row. If the argument is a hash, its keys will be used
215
232
  # to match header alias for building the row data.
216
233
  #
217
- def << (row)
218
- if row.is_a? Hash
219
- array = []
220
- aliases.each do |header_alias|
221
- array << row[header_alias]
222
- end
223
- row = array
224
- end
234
+ def add (row)
225
235
  @data << row
226
236
  end
227
237
 
228
- alias_method :add, :<<
238
+ alias_method :<<, :add
229
239
 
230
240
  #
231
241
  # Sets a component to colorize a column.
@@ -254,7 +264,7 @@ module Yummi
254
264
  index = parse_index(index)
255
265
  if index
256
266
  obj = extract_component(params, &block)
257
- component[:colorizers][index] = {:use_row => @using_row, :component => obj}
267
+ component[:colorizers][index] = obj
258
268
  else
259
269
  colorize_null params, &block
260
270
  end
@@ -375,6 +385,18 @@ module Yummi
375
385
  }
376
386
  end
377
387
 
388
+ def _context_ index, params, &block
389
+ params ||= {}
390
+ rows = (params[:rows] or 1)
391
+ ctx = @contexts.size
392
+ _define_ ctx
393
+ @contexts.insert(index, {:id => ctx, :rows => rows})
394
+
395
+ @current_context = ctx
396
+ block.call if block
397
+ @current_context = :default
398
+ end
399
+
378
400
  #
379
401
  # Gets the content string for the given color map and content
380
402
  #
@@ -388,7 +410,7 @@ module Yummi
388
410
  width = max_width data, j
389
411
  alignment = (@align[j] or @default_align)
390
412
  value = Aligner.align alignment, column[:value].to_s, width
391
- value = Color.colorize value, column[:color] unless @no_colors
413
+ value = Yummi.colorize value, column[:color] unless @no_colors
392
414
  string << value
393
415
  string << (' ' * @colspan)
394
416
  end
@@ -415,6 +437,30 @@ module Yummi
415
437
  output
416
438
  end
417
439
 
440
+ # maps the context for each row
441
+ def build_row_contexts
442
+ rows = @data.size
443
+ row_contexts = [:default] * rows
444
+ offset = 0
445
+ @contexts.each do |ctx|
446
+ if ctx == :default
447
+ break
448
+ end
449
+ size = ctx[:rows]
450
+ row_contexts[offset...(size + offset)] = [ctx[:id]] * size
451
+ offset += size
452
+ end
453
+ @contexts.reverse_each do |ctx|
454
+ if ctx == :default
455
+ break
456
+ end
457
+ size = ctx[:rows]
458
+ row_contexts[(rows - size)...rows] = [ctx[:id]] * size
459
+ rows -= size
460
+ end
461
+ row_contexts
462
+ end
463
+
418
464
  #
419
465
  # Builds the data output for this table.
420
466
  #
@@ -422,21 +468,12 @@ module Yummi
422
468
  #
423
469
  def build_data_output
424
470
  output = []
425
- rows = @data.size
426
- # maps the context for each row
427
- row_contexts = [:default] * rows
428
- i = 1
429
- @context_rows.reverse_each do |size|
430
- row_contexts[(rows - size)...rows] = [@context_rows.size - i] * size
431
- rows -= size
432
- i += 1
433
- end
471
+ row_contexts = build_row_contexts
434
472
  @data.each_index do |row_index|
435
473
  # sets the current context
436
474
  @current_context = row_contexts[row_index]
437
- row = @data[row_index]
475
+ row = row_to_array(@data[row_index], row_index)
438
476
  _row_data = []
439
- row = row.to_a if row.is_a? Range
440
477
  row.each_index do |col_index|
441
478
  next if not @header.empty? and @header[0].size < col_index + 1
442
479
  color = nil
@@ -446,21 +483,19 @@ module Yummi
446
483
  if component[:null_colorizer] and column.nil?
447
484
  color = component[:null_colorizer].call(column)
448
485
  elsif colorizer
449
- arg = colorizer[:use_row] ? IndexedData::new(@aliases, row) : column
450
- color = colorizer[:component].call(arg)
486
+ color = colorizer.call(column)
451
487
  else
452
488
  color = @colors[:value]
453
489
  end
454
490
  formatter = component[:formatters][col_index]
455
491
  formatter = component[:null_formatter] if column.nil? and @null_formatter
456
- value = (formatter ? formatter.call(column) : column)
492
+ value = (formatter ? formatter.call(column) : column.value)
457
493
 
458
494
  _row_data << {:value => value, :color => color}
459
495
  end
460
496
  row_colorizer = component[:row_colorizer]
461
497
  if row_colorizer
462
- row_data = IndexedData::new @aliases, row
463
- row_color = row_colorizer.call row_data, row_index
498
+ row_color = row_colorizer.call row.first
464
499
  _row_data.collect! { |data| data[:color] = row_color; data } if row_color
465
500
  end
466
501
 
@@ -480,6 +515,46 @@ module Yummi
480
515
  output
481
516
  end
482
517
 
518
+ def row_to_array (row, row_index = nil)
519
+ array = []
520
+ row = row.to_a if row.is_a? Range
521
+ if row.is_a? Hash
522
+ @aliases.each_index do |column_index|
523
+ obj = TableContext::new(
524
+ :obj => row,
525
+ :row_index => row_index,
526
+ :column_index => column_index,
527
+ :value => row[@aliases[column_index]]
528
+ )
529
+ array << obj
530
+ end
531
+ elsif row.is_a? Array
532
+ row.each_index do |column_index|
533
+ obj = TableContext::new(
534
+ :obj => IndexedData::new(@aliases, row),
535
+ :row_index => row_index,
536
+ :column_index => column_index,
537
+ :value => row[column_index]
538
+ )
539
+ array << obj
540
+ end
541
+ else
542
+ @aliases.each_index do |column_index|
543
+ obj = TableContext::new(
544
+ :obj => row,
545
+ :row_index => row_index,
546
+ :column_index => column_index,
547
+ :value => row.send(@aliases[column_index])
548
+ )
549
+ def obj.[] (index)
550
+ obj.send(index)
551
+ end
552
+ array << obj
553
+ end
554
+ end
555
+ array
556
+ end
557
+
483
558
  def component
484
559
  @components[@current_context]
485
560
  end
@@ -534,4 +609,17 @@ module Yummi
534
609
 
535
610
  end
536
611
 
612
+ class TableContext < Yummi::Context
613
+
614
+ attr_reader :row_index, :column_index
615
+
616
+ def initialize params
617
+ @row_index = params[:row_index]
618
+ @column_index = params[:column_index]
619
+ @value = params[:value]
620
+ @obj = params[:obj]
621
+ end
622
+
623
+ end
624
+
537
625
  end