yummi 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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