Module: IRuby::HTML

Extended by:
HTML
Included in:
HTML
Defined in:
lib/iruby/formatter.rb

Instance Method Summary collapse

Instance Method Details

#table(obj, maxrows: 15, maxcols: 15, **options) ⇒ Object

Raises:

  • (ArgumentError)

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/iruby/formatter.rb', line 27

def table(obj, maxrows: 15, maxcols: 15, **options)
  raise ArgumentError, 'Invalid :maxrows' if maxrows && maxrows < 3
  raise ArgumentError, 'Invalid :maxcols' if maxcols && maxcols < 3

  return obj unless obj.respond_to?(:each)

  rows = []

  if obj.respond_to?(:keys)
    # Hash of Arrays
    header = obj.keys
    keys = (0...obj.keys.size).to_a
    cols = obj.values.map {|x| [x].flatten(1) }
    num_rows = cols.map(&:size).max
    rows = []
    (0...num_rows).each do |i|
      rows << []
      (0...cols.size).each do |j|
        rows[i][j] = cols[j][i]
      end
    end
  else
    keys = nil
    array_size = 0

    obj.each do |row|
      if row.respond_to?(:keys)
        # Array of Hashes
        keys ||= Set.new
        keys.merge(row.keys)
      elsif row.respond_to?(:map)
        # Array of Arrays
        array_size = row.size if array_size < row.size
      end
      rows << row
    end

    if keys
      header = keys.to_a
      keys.merge(0...array_size)
    else
      keys = 0...array_size
    end
    keys = keys.to_a
  end

  header ||= keys if options[:header]

  rows1, rows2 = rows, nil
  keys1, keys2 = keys, nil
  header1, header2 = header, nil

  if maxcols && keys.size > maxcols
    keys1 = keys[0...maxcols / 2]
    keys2 = keys[-maxcols / 2...-1]
    if header
      header1 = header[0...maxcols / 2]
      header2 = header[-maxcols / 2...-1]
    end
  end

  if maxrows && rows.size > maxrows
    rows1 = rows[0...maxrows / 2]
    rows2 = rows[-maxrows / 2...-1]
  end

  table = '<table>'

  if header1 && options[:header] != false
    table << '<tr>' << header1.map {|k| "<th>#{cell k}</th>" }.join
    table << "<th>&#8230;</th>" << header2.map {|k| "<th>#{cell k}</th>" }.join if keys2
    table << '</tr>'
  end

  row_block(table, rows1, keys1, keys2)

  if rows2
    table << "<tr><td#{keys1.size > 1 ? " colspan='#{keys1.size}'" : ''}>&#8942;</td>"
    table << "<td>&#8945;</td><td#{keys2.size > 1 ? " colspan='#{keys2.size}'" : ''}>&#8942;</td>" if keys2
    table << '</tr>'

    row_block(table, rows2, keys1, keys2)
  end

  table << '</table>'
end