#!/usr/bin/env ruby -w

require 'test/unit'

# Splits the arrays contained in the strarr parameter into
# arrays containing the individual table cell contents.
def totable(strarr)
    strarr.map do |line|
      line.gsub('\\','').split('&').map {|s| s.strip}
    end
end

# Given a two multidimensional array of strings, this method
# returns an array with the maximum string sizes of the rows
# of the original array.
def rowwidths(tbl)
    tbl.map {|x| x.map {|y| y.size}}.map {|x| x.max}
end

# Given an Enumerable object containing LaTeX table source code
# lines, this method returns a pretty printed version of it (in
# one single string).
def prettyprint(strarr)
    tbl = totable(strarr)
    # transpose
    transposed = tbl.transpose
    colwidths = rowwidths(transposed)
    # on the transposed table: expand rows of strings
    # to full string size
    transposed = (0...transposed.size).map do |i|
      transposed[i].map {|x| sprintf("%#{colwidths[i]}s",x)}
    end
    # transpose back
    tbl = transposed.transpose
    tbl.map {|x| x.join(' & ') + " \\\n"}.join()
end


# Tests
class PrettyPrintTest < Test::Unit::TestCase
    def test_totable
        assert_equal([['a','b','c'],['d','e','f']], totable(['  a & b &  c   \\ ', 'd&e& f\\']))
    end
    
    def test_rowwidths
        assert_equal([4,3], rowwidths([['x', 'aaaa', 'zz'], ['', 'zxx', 'x']]))
    end
    
    def test_killertest
        before =<<XXX
    &1 & 2& 3  & 4&5 &  6 \\
 Square & 1  &  4& 9 & 16  & 25& 36         \\
Faculty  & 1 & 2 & 6  &  24 &  120  & 720  \\
    Exp & 2.72 &  7.39  &  20.09 & 54.6  & 148.41 & 403.43  \\
XXX
        before = before.split("\n")
        
        after =<<XXX
        &    1 &    2 &     3 &    4 &      5 &      6 \\
 Square &    1 &    4 &     9 &   16 &     25 &     36 \\
Faculty &    1 &    2 &     6 &   24 &    120 &    720 \\
    Exp & 2.72 & 7.39 & 20.09 & 54.6 & 148.41 & 403.43 \\
XXX
        assert_equal(after, prettyprint(before))
    end
end
