Easy Text Tables!

Ovid on 2008-06-24T11:47:38

I really like the Text::Table module, but its use can be a bit cryptic at times. A basic table can look like this:

Time    Test
18m 12s t/acceptance.t
4m 17s  t/aggregate.t
2m 12s  t/unit/api/spider_and_validate.t
0m 53s  t/standards/use.t
0m 21s  t/system/both/import/log/search.t
0m 20s  t/system/both/import/log/pager.t
0m 18s  t/test_class_tests.t
0m 16s  t/unit/db/migrations.t
0m 14s  t/unit/piptest/pprove/testdb.t
0m 12s  t/system/both/import/log/log.t

That's nice and all, but I'd rather have this:

+---------+-----------------------------------+
| Time    | Test                              |
+---------+-----------------------------------+
| 18m 12s | t/acceptance.t                    |
| 4m 17s  | t/aggregate.t                     |
| 2m 12s  | t/unit/api/spider_and_validate.t  |
| 0m 53s  | t/standards/use.t                 |
| 0m 21s  | t/system/both/import/log/search.t |
| 0m 20s  | t/system/both/import/log/pager.t  |
| 0m 18s  | t/test_class_tests.t              |
| 0m 16s  | t/unit/db/migrations.t            |
| 0m 14s  | t/unit/piptest/pprove/testdb.t    |
| 0m 12s  | t/system/both/import/log/log.t    |
+---------+-----------------------------------+

Have fun reading the docs to figure that out :) Here's my generic function for printing tables like that. You get no control over formatting.

use Text::Table;

my @rows = code_to_get_rows();

print make_table(
    [qw/Time Test/],
    \@rows,
);

sub make_table {
    my ( $headers, $rows ) = @_;

    my @rule      = qw(- +);
    my @headers   = \'| ';
    push @headers => map { $_ => \' | ' } @$headers;
    pop  @headers;
    push @headers => \' |';

    unless ('ARRAY' eq ref $rows
        && 'ARRAY' eq ref $rows->[0]
        && @$headers == @{ $rows->[0] }) {
        croak(
            "make_table() rows must be an AoA with rows being same size as headers"
        );
    }
    my $table = Text::Table->new(@headers);
    $table->rule(@rule);
    $table->body_rule(@rule);
    $table->load(@$rows);

    return $table->rule(@rule),
           $table->title,
           $table->rule(@rule),
           map({ $table->body($_) } 0 .. @$rows),
           $table->rule(@rule);
}


As seen in Catalyst

jplindstrom on 2008-06-24T12:44:49

Text::SimpleTable?

Re:As seen in Catalyst

Ovid on 2008-06-24T12:52:06

Never saw that module before. I don't understand why it requires that I pass in the width when the calculation is trivial. Sometimes module interfaces mystify me.

Also nice...

kixx on 2008-06-24T14:29:38

Text::ASCIITable ?

Text::TabularDisplay

dlc on 2008-06-24T15:05:50

I wrote Text::TabularDisplay to do exactly that.

Re:Text::TabularDisplay

jplindstrom on 2008-06-24T15:10:10

Well, Text::SimpleTable is clearly more Table 2.0, what with the rounded corners and everything.

Re:Text::TabularDisplay

dlc on 2008-06-24T15:17:08

Well, Text::SimpleTable is clearly more Table 2.0, what with the rounded corners and everything.
And it's from 2005, too -- well ahead of its time. It looks pretty similar to Text::TabularDisplay, otherwise. I was specifically going for the mysql client look, as part of a similar command line client for $WORK, when I wrote it, so I don't think the rounded corners occurred to me at the time.

cryptic?

hdp on 2008-06-24T17:11:41

Have fun reading the docs to figure that out :)

I'm skeptical. I admit to having ever used Text::Table before, but not much, and it didn't take more than a glance at the docs to figure out how to do what you want:

my $t = Text::Table->new(\'| ', 'Time', \' | ', 'Text', \' |');
$t->load(... some data ...);
my $rule = $t->rule(qw(- +));
print $rule, $t->head, $rule, $t->body, $rule;

I'm not claiming to be overly fond of the interface -- any time I have to do \'foo' it trips my fingers up -- but I've read documentation that's far worse.

Wow!

mr_bean on 2008-06-25T10:33:27

All these table formatters. I never knew. I just use the 'format' built-in.

man perlform

Perhaps I should investigate them, because I don't know how to write argument lines to 'format' that match the number of values in an array. The number of values is variable. The argument lines are fixed.

Perhaps I should declare different formats for each of the possible number of values, because I have only a small number of different possible numbers of values.

Text::FormatTable

dschwei on 2008-06-25T14:03:54

My module Text::FormatTable (rather old and not really actively developed) can do word-wrapping and outputs tables like this:

     a| b     c
=================
this a| oh,   yep
test,| cool,
a nice| a
  test| test!
------+----------
   you| yes,  z
  mean| it
  it's| is.
really|
     a|
test?|
=================