Class: ANSI::Table

Inherits:
Object
  • Object
show all
Defined in:
lib/ansi/table.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(table, options = {}, &format) ⇒ Table

The Table class can be used to output nicely formatted tables with division lines and alignment.

table - array of array

options - align :left or :right options - space to add to each cell options - fit to screen width options -

The format block must return ANSI codes to apply to each cell.

Other Implementations:

TODO: Support for table headers and footers.


27
28
29
30
31
32
33
34
35
36
37
# File 'lib/ansi/table.rb', line 27

def initialize(table, options={}, &format)
  @table   = table
  @padding = options[:padding] || 0
  @align   = options[:align]
  @fit     = options[:fit]
  @border  = options[:border]
  #@ansi    = [options[:ansi]].flatten
  @format  = format

  @pad = " " * @padding
end

Instance Attribute Details

#alignObject

Returns the value of attribute align


49
50
51
# File 'lib/ansi/table.rb', line 49

def align
  @align
end

#borderObject

Returns the value of attribute border


55
56
57
# File 'lib/ansi/table.rb', line 55

def border
  @border
end

#fitObject

Fit to scree width.


43
44
45
# File 'lib/ansi/table.rb', line 43

def fit
  @fit
end

#formatObject

Returns the value of attribute format


52
53
54
# File 'lib/ansi/table.rb', line 52

def format
  @format
end

#paddingObject

Returns the value of attribute padding


46
47
48
# File 'lib/ansi/table.rb', line 46

def padding
  @padding
end

#tableObject

Returns the value of attribute table


40
41
42
# File 'lib/ansi/table.rb', line 40

def table
  @table
end

Instance Method Details

#ansi_formating(cell, col, row) ⇒ Object (private)


158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/ansi/table.rb', line 158

def ansi_formating(cell, col, row)
  if @format
    case @format.arity
    when 0
      f = @format[]
    when 1
      f = @format[cell]
    when 2 
      f = @format[row, col]
    else
      f = @format[cell, row, col]
    end
  else
    f = nil
  end
  [f].flatten.compact
end

#apply_format(str, cell, col, row) ⇒ Object (private)


149
150
151
152
153
154
155
# File 'lib/ansi/table.rb', line 149

def apply_format(str, cell, col, row)
  if @format
    str.ansi(*ansi_formating(cell, col, row))
  else
    str
  end 
end

#cell_template(max) ⇒ Object (private)


123
124
125
126
127
128
129
130
# File 'lib/ansi/table.rb', line 123

def cell_template(max)
  case align
  when :right, 'right'
    "#{@pad}%#{max}s"
  else
    "%-#{max}s#{@pad}"
  end
end

#column_sizeInteger (private)

Number of columns based on the first row of table.


118
119
120
# File 'lib/ansi/table.rb', line 118

def column_size
  table.first.size
end

#dividing_lineObject (private)

TODO: make more efficient


133
134
135
136
137
138
# File 'lib/ansi/table.rb', line 133

def dividing_line
  tmp = max_columns(fit).map{ |m| "%#{m}s" }.join(" | ")
  tmp = "| #{tmp} |"
  lin = (tmp % (['-'] * column_size)).gsub(/[^\|]/, '-').gsub('|', '+')
  lin
end

#fit_widthObject (private)

TODO: look at the lines and figure out how many columns will fit


91
92
93
94
# File 'lib/ansi/table.rb', line 91

def fit_width
  width = Terminal.terminal_width
  ((width.to_f / column_size) - (padding + 3)).to_i
end

#max_columns(fit = false) ⇒ Array (private)

Calculate the maximun column sizes.


99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/ansi/table.rb', line 99

def max_columns(fit=false)
  max = Array.new(column_size, 0)
  table.each do |row|
    row.each_with_index do |col, index|
      col = col.to_s
      col = col.unansi
      if fit
        max[index] = [max[index], col.size, fit_width].max
      else
        max[index] = [max[index], col.size].max
      end
    end
  end
  max
end

#to_sObject

(fit=false)


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/ansi/table.rb', line 58

def to_s #(fit=false)
  #row_count = table.size
  #col_count = table[0].size

  max = max_columns(fit)

  div = dividing_line
  top = div #.gsub('+', ".")
  bot = div #.gsub('+', "'")

  body = []
  table.each_with_index do |row, r|
     body_row = []
     row.each_with_index do |cell, c|
       t = cell_template(max[c])
       s = t % cell.to_s
       body_row << apply_format(s, cell, c, r)
     end
     body << "| " + body_row.join(' | ') + " |"
  end

  if border
    body = body.join("\n#{div}\n")
  else
    body = body.join("\n")
  end

  "#{top}\n#{body}\n#{bot}\n"
end