package Acme::CPANModules::TextTable;

our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
our $DATE = '2021-02-15'; # DATE
our $DIST = 'Acme-CPANModules-TextTable'; # DIST
our $VERSION = '0.008'; # VERSION

use 5.010001;
use strict;
use warnings;

sub _make_table {
    my ($cols, $rows, $celltext) = @_;
    my $res = [];
    push @$res, [];
    for (0..$cols-1) { $res->[0][$_] = "col" . ($_+1) }
    for my $row (1..$rows) {
        push @$res, [ map { $celltext // "row$row.$_" } 1..$cols ];
    }
    $res;
}

our $LIST = {
    summary => 'Modules that generate text tables',
    entry_features => {
        wide_char => {summary => 'Whether the use of wide characters (e.g. Kanji) in cells does not cause the table to be misaligned'},
        color_data =>  {summary => 'Whether module supports ANSI colors (i.e. text with ANSI color codes can still be aligned properly)'},
        multiline_data => {summary => 'Whether module supports aligning data cells that contain newlines'},

        box_char => {summary => 'Whether module can utilize box-drawing characters'},
        custom_border => {summary => 'Whether module allows customizing border in some way'},

        align_column => {summary => "Whether module supports aligning text in a column (left/right/middle)"},
        align_cell => {summary => "Whether module supports aligning text in individual cells (left/right/middle)"},

        rowspan => {summary => "Whether module supports row spans"},
        colspan => {summary => "Whether module supports column spans"},

        custom_color => {summary => 'Whether the module produces colored table and supports customizing color in some way'},
        color_theme => {summary => 'Whether the module supports color theme/scheme'},
    },
    entries => [
        {
            module => 'Text::ANSITable',
            bench_code => sub {
                my ($table) = @_;
                my $t = Text::ANSITable->new(
                    use_utf8 => 0,
                    use_box_chars => 0,
                    use_color =>  0,
                    columns => $table->[0],
                    border_style => 'ASCII::SingleLine',
                );
                $t->add_row($table->[$_]) for 1..@$table-1;
                $t->draw;
            },
            features => {
                align_cell => 1,
                align_column => 1,
                box_char => 1,
                color_data =>  1,
                color_theme => 1,
                colspan => 0,
                custom_border => 1,
                custom_color => 1,
                multiline_data => 1,
                rowspan => 0,
                wide_char_data => 1,
            },
        },
        {
            module => 'Text::ASCIITable',
            bench_code => sub {
                my ($table) = @_;
                my $t = Text::ASCIITable->new();
                $t->setCols(@{ $table->[0] });
                $t->addRow(@{ $table->[$_] }) for 1..@$table-1;
                "$t";
            },
            features => {
                wide_char_data => 0,
                color_data =>  0,
                box_char => 0,
                multiline_data => 1,
            },
        },
        {
            module => 'Text::FormatTable',
            bench_code => sub {
                my ($table) = @_;
                my $t = Text::FormatTable->new(join('|', ('l') x @{ $table->[0] }));
                $t->head(@{ $table->[0] });
                $t->row(@{ $table->[$_] }) for 1..@$table-1;
                $t->render;
            },
            features => {
                wide_char_data => 0,
                color_data =>  0,
                box_char => 0,
                multiline_data => 1,
            },
        },
        {
            module => 'Text::MarkdownTable',
            bench_code => sub {
                my ($table) = @_;
                my $out = "";
                my $t = Text::MarkdownTable->new(file => \$out);
                my $fields = $table->[0];
                foreach (1..@$table-1) {
                    my $row = $table->[$_];
                    $t->add( {
                        map { $fields->[$_] => $row->[$_] } 0..@$fields-1
                    });
                }
                $t->done;
                $out;
            },
            features => {
                wide_char_data => 0,
                color_data =>  0,
                box_char => 0,
                multiline_data => {value=>0, summary=>'Newlines stripped'},
            },
        },
        {
            module => 'Text::Table',
            bench_code => sub {
                my ($table) = @_;
                my $t = Text::Table->new(@{ $table->[0] });
                $t->load(@{ $table }[1..@$table-1]);
                $t;
            },
            features => {
                wide_char_data => 0,
                color_data =>  0,
                box_char => {value=>undef, summary=>'Does not draw borders'},
                multiline_data => 1,
            },
        },
        {
            module => 'Text::Table::Tiny',
            bench_code => sub {
                my ($table) = @_;
                Text::Table::Tiny::table(rows=>$table, header_row=>1);
            },
            features => {
                wide_char_data => 1,
                color_data =>  1,
                box_char => 1,
                multiline_data => 0,
            },
        },
        {
            module => 'Text::Table::TinyBorderStyle',
            bench_code => sub {
                my ($table) = @_;
                Text::Table::TinyBorderStyle::table(rows=>$table, header_row=>1);
            },
            features => {
                wide_char_data => 0,
                color_data =>  0,
                box_char => 1,
                multiline_data => 0,
            },
        },
        {
            module => 'Text::Table::Span',
            bench_code => sub {
                my ($table) = @_;
                Text::Table::Span::table(rows=>$table, header_row=>1);
            },
            features => {
                align_cell => 0, # todo
                align_column => 0, # todo
                box_char => 1,
                color_data =>  0,
                color_theme => 1,
                colspan => 1,
                custom_border => 1,
                custom_color => 1,
                multiline_data => 1,
                rowspan => 1,
                wide_char_data => 0,
            },
        },
        {
            module => 'Text::Table::Sprintf',
            bench_code => sub {
                my ($table) = @_;
                Text::Table::Sprintf::table(rows=>$table, header_row=>1);
            },
            features => {
                wide_char_data => 0,
                color_data =>  0,
                box_char => 0,
                multiline_data => 0,
            },
        },
        {
            module => 'Text::Table::TinyColor',
            bench_code => sub {
                my ($table) = @_;
                Text::Table::TinyColor::table(rows=>$table, header_row=>1);
            },
            features => {
                wide_char_data => 0,
                color_data =>  1,
                box_char => 0,
                multiline_data => 0,
            },
        },
        {
            module => 'Text::Table::TinyColorWide',
            bench_code => sub {
                my ($table) = @_;
                Text::Table::TinyColorWide::table(rows=>$table, header_row=>1);
            },
            features => {
                wide_char_data => 1,
                color_data =>  1,
                box_char => 0,
                multiline_data => 0,
            },
        },
        {
            module => 'Text::Table::TinyWide',
            bench_code => sub {
                my ($table) = @_;
                Text::Table::TinyWide::table(rows=>$table, header_row=>1);
            },
            features => {
                wide_char_data => 1,
                color_data =>  0,
                box_char => 0,
            },
        },
        {
            module => 'Text::Table::Org',
            bench_code => sub {
                my ($table) = @_;
                Text::Table::Org::table(rows=>$table, header_row=>1);
            },
            features => {
                wide_char_data => 0,
                color_data =>  0,
                box_char => 0,
                multiline_data => 0,
            },
        },
        {
            module => 'Text::Table::CSV',
            bench_code => sub {
                my ($table) = @_;
                Text::Table::CSV::table(rows=>$table, header_row=>1);
            },
            features => {
                wide_char_data => 1,
                color_data =>  0,
                box_char => {value=>undef, summary=>"Irrelevant"},
                multiline_data => {value=>1, summary=>"But make sure your CSV parser can handle multiline cell"},
            },
        },
        {
            module => 'Text::Table::HTML',
            bench_code => sub {
                my ($table) = @_;
                Text::Table::HTML::table(rows=>$table, header_row=>1);
            },
            features => {
                wide_char_data => 1,
                color_data =>  {value=>0, summary=>'Not converted to HTML color elements'},
                box_char => 0,
                multiline_data => 1,
            },
        },
        {
            module => 'Text::Table::HTML::DataTables',
            bench_code => sub {
                my ($table) = @_;
                Text::Table::HTML::DataTables::table(rows=>$table, header_row=>1);
            },
            features => {
                wide_char_data => 1,
                color_data =>  {value=>0, summary=>'Not converted to HTML color elements'},
                box_char => 0,
                multiline_data => 1,
            },
        },
        {
            module => 'Text::TabularDisplay',
            bench_code => sub {
                my ($table) = @_;
                my $t = Text::TabularDisplay->new(@{ $table->[0] });
                $t->add(@{ $table->[$_] }) for 1..@$table-1;
                $t->render; # doesn't add newline
            },
            features => {
                wide_char_data => 1,
                color_data =>  0,
                box_char => {value=>undef, summary=>"Irrelevant"},
                multiline_data => 1,
            },
        },
    ],

    bench_datasets => [
        {name=>'multiline data (2x1)', argv => [ [["col1", "col2"], ["foobar\nbaz\nqux\nquux","corge"]] ], include_by_default=>0 },
        {name=>'tiny (1x1)'          , argv => [_make_table( 1, 1)],},
        {name=>'small (3x5)'         , argv => [_make_table( 3, 5)],},
        {name=>'wide (30x5)'         , argv => [_make_table(30, 5)],},
        {name=>'long (3x300)'        , argv => [_make_table( 3, 300)],},
        {name=>'large (30x300)'      , argv => [_make_table(30, 300)],},
    ],

};

1;
# ABSTRACT: Modules that generate text tables

__END__

=pod

=encoding UTF-8

=head1 NAME

Acme::CPANModules::TextTable - Modules that generate text tables

=head1 VERSION

This document describes version 0.008 of Acme::CPANModules::TextTable (from Perl distribution Acme-CPANModules-TextTable), released on 2021-02-15.

=head1 SYNOPSIS

To run benchmark with default option:

 % bencher --cpanmodules-module TextTable

To run module startup overhead benchmark:

 % bencher --module-startup --cpanmodules-module TextTable

For more options (dump scenario, list/include/exclude/add participants, list/include/exclude/add datasets, etc), see L<bencher> or run C<bencher --help>.

=head1 BENCHMARKED MODULES

Version numbers shown below are the versions used when running the sample benchmark.

L<Text::ANSITable> 0.601

L<Text::ASCIITable> 0.22

L<Text::FormatTable> 1.03

L<Text::MarkdownTable> 0.3.1

L<Text::Table> 1.133

L<Text::Table::Tiny> 1.00

L<Text::Table::TinyBorderStyle> 0.004

L<Text::Table::Span> 0.002

L<Text::Table::Sprintf> 0.001

L<Text::Table::TinyColor> 0.002

L<Text::Table::TinyColorWide> 0.001

L<Text::Table::TinyWide> 0.001

L<Text::Table::Org> 0.02

L<Text::Table::CSV> 0.023

L<Text::Table::HTML> 0.003

L<Text::Table::HTML::DataTables> 0.007

L<Text::TabularDisplay> 1.38

=head1 BENCHMARK PARTICIPANTS

=over

=item * Text::ANSITable (perl_code)

L<Text::ANSITable>



=item * Text::ASCIITable (perl_code)

L<Text::ASCIITable>



=item * Text::FormatTable (perl_code)

L<Text::FormatTable>



=item * Text::MarkdownTable (perl_code)

L<Text::MarkdownTable>



=item * Text::Table (perl_code)

L<Text::Table>



=item * Text::Table::Tiny (perl_code)

L<Text::Table::Tiny>



=item * Text::Table::TinyBorderStyle (perl_code)

L<Text::Table::TinyBorderStyle>



=item * Text::Table::Span (perl_code)

L<Text::Table::Span>



=item * Text::Table::Sprintf (perl_code)

L<Text::Table::Sprintf>



=item * Text::Table::TinyColor (perl_code)

L<Text::Table::TinyColor>



=item * Text::Table::TinyColorWide (perl_code)

L<Text::Table::TinyColorWide>



=item * Text::Table::TinyWide (perl_code)

L<Text::Table::TinyWide>



=item * Text::Table::Org (perl_code)

L<Text::Table::Org>



=item * Text::Table::CSV (perl_code)

L<Text::Table::CSV>



=item * Text::Table::HTML (perl_code)

L<Text::Table::HTML>



=item * Text::Table::HTML::DataTables (perl_code)

L<Text::Table::HTML::DataTables>



=item * Text::TabularDisplay (perl_code)

L<Text::TabularDisplay>



=back

=head1 BENCHMARK DATASETS

=over

=item * tiny (1x1)

=item * small (3x5)

=item * wide (30x5)

=item * long (3x300)

=item * large (30x300)

=item * multiline data (2x1) (not included by default)

=back

=head1 SAMPLE BENCHMARK RESULTS

Run on: perl: I<< v5.30.0 >>, CPU: I<< Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz (2 cores) >>, OS: I<< GNU/Linux Ubuntu version 19.10 >>, OS kernel: I<< Linux version 5.3.0-64-generic >>.

Benchmark with default options (C<< bencher --cpanmodules-module TextTable >>):

 #table1#
 {dataset=>"large (30x300)"}
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+-----------+---------+
 | participant                   | rate (/s) | time (ms) | pct_faster_vs_slowest | pct_slower_vs_fastest |  errors   | samples |
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+-----------+---------+
 | Text::ANSITable               |      2.56 |    390    |                 0.00% |             16612.00% |   0.00018 |      20 |
 | Text::Table::Span             |      6.5  |    150    |               152.82% |              6510.32% |   0.0008  |      20 |
 | Text::ASCIITable              |     12.3  |     81.2  |               380.58% |              3377.44% | 7.2e-05   |      20 |
 | Text::Table::TinyColorWide    |     17.4  |     57.5  |               579.05% |              2361.07% | 4.1e-05   |      20 |
 | Text::FormatTable             |     18.8  |     53.2  |               633.73% |              2177.69% | 4.2e-05   |      20 |
 | Text::Table::TinyWide         |     24.8  |     40.3  |               869.37% |              1624.00% | 1.5e-05   |      20 |
 | Text::TabularDisplay          |     47.9  |     20.9  |              1770.65% |               793.38% | 1.6e-05   |      20 |
 | Text::Table::TinyColor        |     64    |     16    |              2417.69% |               563.78% |   2e-05   |      22 |
 | Text::Table::Tiny             |     70.1  |     14.3  |              2637.54% |               510.47% | 7.4e-06   |      20 |
 | Text::MarkdownTable           |     96.1  |     10.4  |              3651.10% |               345.52% | 7.8e-06   |      20 |
 | Text::Table                   |    120    |      8.4  |              4548.20% |               259.54% | 1.8e-05   |      20 |
 | Text::Table::HTML::DataTables |    120    |      8.1  |              4708.86% |               247.53% | 1.2e-05   |      21 |
 | Text::Table::HTML             |    130    |      8    |              4809.66% |               240.39% | 1.6e-05   |      20 |
 | Text::Table::CSV              |    240    |      4.2  |              9263.92% |                78.47% | 4.7e-06   |      20 |
 | Text::Table::Org              |    249    |      4.02 |              9622.42% |                71.89% | 2.5e-06   |      20 |
 | Text::Table::TinyBorderStyle  |    270    |      3.7  |             10503.64% |                57.61% | 7.4e-06   |      20 |
 | Text::Table::Sprintf          |    430    |      2.3  |             16612.00% |                 0.00% | 5.2e-06   |      20 |
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+-----------+---------+

 #table2#
 {dataset=>"long (3x300)"}
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+
 | participant                   | rate (/s) | time (ms) | pct_faster_vs_slowest | pct_slower_vs_fastest |  errors | samples |
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+
 | Text::ANSITable               |        23 |    43     |                 0.00% |             13871.55% | 6.5e-05 |      20 |
 | Text::Table::Span             |        64 |    16     |               172.35% |              5030.01% | 2.2e-05 |      20 |
 | Text::ASCIITable              |       130 |     7.6   |               460.40% |              2393.13% | 1.5e-05 |      20 |
 | Text::FormatTable             |       167 |     5.97  |               614.89% |              1854.35% |   5e-06 |      20 |
 | Text::Table::TinyColorWide    |       172 |     5.81  |               635.00% |              1800.89% | 2.7e-06 |      20 |
 | Text::Table::TinyWide         |       246 |     4.07  |               950.19% |              1230.39% | 1.1e-06 |      20 |
 | Text::TabularDisplay          |       361 |     2.77  |              1441.69% |               806.25% | 2.7e-06 |      20 |
 | Text::MarkdownTable           |       448 |     2.23  |              1815.36% |               629.45% | 1.9e-06 |      20 |
 | Text::Table                   |       531 |     1.88  |              2166.16% |               516.53% | 8.5e-07 |      20 |
 | Text::Table::Tiny             |       596 |     1.68  |              2444.56% |               449.07% | 6.9e-07 |      20 |
 | Text::Table::TinyColor        |       610 |     1.64  |              2505.80% |               436.17% | 6.9e-07 |      20 |
 | Text::Table::HTML::DataTables |       990 |     1     |              4119.45% |               231.12% | 1.1e-06 |      20 |
 | Text::Table::HTML             |      1100 |     0.93  |              4497.39% |               203.90% | 1.9e-06 |      21 |
 | Text::Table::CSV              |      1790 |     0.557 |              7565.54% |                82.26% | 3.6e-07 |      21 |
 | Text::Table::Org              |      1800 |     0.54  |              7780.08% |                77.30% | 6.4e-07 |      20 |
 | Text::Table::TinyBorderStyle  |      1900 |     0.54  |              7814.40% |                76.53% | 9.1e-07 |      20 |
 | Text::Table::Sprintf          |      3270 |     0.306 |             13871.55% |                 0.00% | 2.1e-07 |      20 |
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+

 #table3#
 {dataset=>"small (3x5)"}
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+
 | participant                   | rate (/s) | time (μs) | pct_faster_vs_slowest | pct_slower_vs_fastest |  errors | samples |
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+
 | Text::ANSITable               |     897   | 1120      |                 0.00% |             11090.81% | 9.4e-07 |      21 |
 | Text::Table::Span             |    2400   |  410      |               169.42% |              4053.66% | 6.9e-07 |      20 |
 | Text::ASCIITable              |    4900   |  200      |               451.19% |              1930.31% | 4.2e-07 |      21 |
 | Text::FormatTable             |    7000   |  140      |               681.01% |              1332.86% | 2.1e-07 |      21 |
 | Text::Table::TinyColorWide    |    7700   |  130      |               756.60% |              1206.42% | 1.8e-07 |      27 |
 | Text::Table                   |    7700   |  130      |               762.41% |              1197.61% | 1.9e-07 |      26 |
 | Text::Table::TinyWide         |   11116.5 |   89.9563 |              1139.91% |               802.55% | 2.3e-11 |      22 |
 | Text::Table::TinyBorderStyle  |   12000   |   83      |              1246.53% |               731.09% | 9.9e-08 |      23 |
 | Text::MarkdownTable           |   13000   |   79      |              1318.49% |               688.93% | 1.1e-07 |      20 |
 | Text::Table::HTML::DataTables |   15300   |   65.2    |              1610.01% |               554.43% | 2.7e-08 |      20 |
 | Text::TabularDisplay          |   15000   |   65      |              1621.97% |               549.88% | 1.1e-07 |      20 |
 | Text::Table::Tiny             |   21000   |   47      |              2254.37% |               375.32% | 5.3e-08 |      20 |
 | Text::Table::TinyColor        |   24045.1 |   41.5886 |              2581.93% |               317.27% |   0     |      21 |
 | Text::Table::HTML             |   47000   |   21.3    |              5142.38% |               113.47% | 6.5e-09 |      21 |
 | Text::Table::Org              |   56000   |   18      |              6130.61% |                79.61% | 2.7e-08 |      20 |
 | Text::Table::CSV              |   79900   |   12.5    |              8807.54% |                25.63% | 3.3e-09 |      20 |
 | Text::Table::Sprintf          |  100000   |   10      |             11090.81% |                 0.00% | 1.3e-08 |      20 |
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+

 #table4#
 {dataset=>"tiny (1x1)"}
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+
 | participant                   | rate (/s) | time (μs) | pct_faster_vs_slowest | pct_slower_vs_fastest |  errors | samples |
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+
 | Text::ANSITable               |      3300 |  310      |                 0.00% |              8857.99% | 4.8e-07 |      20 |
 | Text::Table::Span             |      8500 |  120      |               159.85% |              3347.30% |   2e-07 |      22 |
 | Text::Table::TinyBorderStyle  |     16000 |   63      |               389.31% |              1730.76% | 7.5e-08 |      23 |
 | Text::ASCIITable              |     18000 |   57      |               438.60% |              1563.18% | 2.7e-07 |      29 |
 | Text::Table                   |     20700 |   48.3    |               535.65% |              1309.26% | 4.4e-08 |      29 |
 | Text::Table::HTML::DataTables |     21000 |   48      |               539.56% |              1300.66% | 1.1e-07 |      20 |
 | Text::MarkdownTable           |     26000 |   39      |               686.58% |              1038.85% | 5.3e-08 |      20 |
 | Text::FormatTable             |     35000 |   29      |               963.43% |               742.37% | 5.3e-08 |      20 |
 | Text::Table::TinyColorWide    |     44000 |   23      |              1247.93% |               564.57% | 3.3e-08 |      20 |
 | Text::Table::TinyWide         |     60000 |   17      |              1727.69% |               390.13% |   2e-08 |      20 |
 | Text::TabularDisplay          |     61000 |   16      |              1772.35% |               378.43% | 2.7e-08 |      30 |
 | Text::Table::Tiny             |     64000 |   16      |              1863.37% |               356.26% | 2.9e-08 |      27 |
 | Text::Table::TinyColor        |     93300 |   10.7    |              2764.25% |               212.75% | 9.8e-09 |      21 |
 | Text::Table::Org              |    148140 |    6.7504 |              4450.02% |                96.88% | 2.3e-11 |      20 |
 | Text::Table::HTML             |    180000 |    5.6    |              5419.10% |                62.31% | 6.7e-09 |      20 |
 | Text::Table::Sprintf          |    281000 |    3.56   |              8527.99% |                 3.82% | 1.4e-09 |      27 |
 | Text::Table::CSV              |    292000 |    3.43   |              8857.99% |                 0.00% | 1.5e-09 |      24 |
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+

 #table5#
 {dataset=>"wide (30x5)"}
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+
 | participant                   | rate (/s) | time (ms) | pct_faster_vs_slowest | pct_slower_vs_fastest |  errors | samples |
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+
 | Text::ANSITable               |       113 |    8.83   |                 0.00% |             13931.98% | 4.5e-06 |      20 |
 | Text::Table::Span             |       324 |    3.08   |               186.31% |              4800.93% | 2.7e-06 |      20 |
 | Text::ASCIITable              |       540 |    1.85   |               376.41% |              2845.37% | 1.5e-06 |      20 |
 | Text::FormatTable             |       741 |    1.35   |               554.47% |              2044.01% | 8.5e-07 |      20 |
 | Text::Table::TinyColorWide    |       860 |    1.2    |               661.62% |              1742.38% | 1.4e-06 |      20 |
 | Text::Table                   |      1200 |    0.82   |               971.39% |              1209.70% | 8.5e-07 |      20 |
 | Text::Table::TinyWide         |      1200 |    0.81   |               994.51% |              1182.04% | 8.1e-07 |      22 |
 | Text::TabularDisplay          |      2300 |    0.43   |              1960.06% |               581.14% | 6.9e-07 |      20 |
 | Text::Table::Tiny             |      3040 |    0.329  |              2583.63% |               422.87% | 2.1e-07 |      20 |
 | Text::Table::TinyColor        |      3060 |    0.327  |              2599.08% |               419.88% | 2.1e-07 |      20 |
 | Text::Table::TinyBorderStyle  |      3450 |    0.29   |              2942.68% |               361.17% | 2.1e-07 |      20 |
 | Text::MarkdownTable           |      3600 |    0.27   |              3115.42% |               336.40% | 4.3e-07 |      20 |
 | Text::Table::HTML::DataTables |      4900 |    0.2    |              4212.12% |               225.41% | 2.1e-07 |      20 |
 | Text::Table::HTML             |      6300 |    0.159  |              5467.24% |               152.05% | 4.7e-08 |      26 |
 | Text::Table::Org              |      9300 |    0.11   |              8087.60% |                71.38% | 2.1e-07 |      20 |
 | Text::Table::CSV              |     12000 |    0.082  |             10629.00% |                30.79% | 1.3e-07 |      20 |
 | Text::Table::Sprintf          |     15900 |    0.0629 |             13931.98% |                 0.00% | 2.6e-08 |      21 |
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+


Benchmark module startup overhead (C<< bencher --cpanmodules-module TextTable --module-startup >>):

 #table6#
 +-------------------------------+-----------+--------------------+-----------------------+-----------------------+---------+---------+
 | participant                   | time (ms) | mod_overhead_time  | pct_faster_vs_slowest | pct_slower_vs_fastest |  errors | samples |
 +-------------------------------+-----------+--------------------+-----------------------+-----------------------+---------+---------+
 | Text::ANSITable               |     44.8  | 37                 |                 0.00% |               473.02% | 4.2e-05 |      20 |
 | Text::MarkdownTable           |     41    | 33.2               |                 9.36% |               423.96% | 4.6e-05 |      20 |
 | Text::Table::TinyColorWide    |     31.9  | 24.1               |                40.38% |               308.21% |   3e-05 |      20 |
 | Text::Table::TinyWide         |     29    | 21.2               |                51.98% |               277.03% | 2.9e-05 |      20 |
 | Text::Table::Span             |     22.8  | 15                 |                96.10% |               192.21% | 1.4e-05 |      20 |
 | Text::Table                   |     21.6  | 13.8               |               107.45% |               176.22% | 1.5e-05 |      20 |
 | Text::ASCIITable              |     17.8  | 10                 |               152.04% |               127.35% | 1.6e-05 |      20 |
 | Text::Table::Tiny             |     14.9  |  7.1               |               201.36% |                90.15% | 1.4e-05 |      20 |
 | Text::FormatTable             |     14.2  |  6.4               |               214.73% |                82.07% | 9.2e-06 |      20 |
 | Text::Table::TinyColor        |     13.4  |  5.6               |               234.68% |                71.22% |   1e-05 |      20 |
 | Text::Table::TinyBorderStyle  |     11    |  3.2               |               297.28% |                44.24% | 1.8e-05 |      20 |
 | Text::TabularDisplay          |     11    |  3.2               |               321.42% |                35.98% |   2e-05 |      20 |
 | Text::Table::HTML::DataTables |     10    |  2.2               |               349.55% |                27.46% |   1e-05 |      20 |
 | Text::Table::HTML             |      9.85 |  2.05              |               354.65% |                26.04% | 7.4e-06 |      20 |
 | Text::Table::CSV              |      8.6  |  0.8               |               421.31% |                 9.92% | 1.2e-05 |      21 |
 | Text::Table::Org              |      8.6  |  0.8               |               422.82% |                 9.60% | 1.4e-05 |      20 |
 | Text::Table::Sprintf          |      8.4  |  0.600000000000001 |               431.64% |                 7.79% | 1.2e-05 |      20 |
 | perl -e1 (baseline)           |      7.8  |  0                 |               473.02% |                 0.00% | 4.2e-05 |      20 |
 +-------------------------------+-----------+--------------------+-----------------------+-----------------------+---------+---------+


To display as an interactive HTML table on a browser, you can add option C<--format html+datatables>.

=head1 ACME::CPANMODULES FEATURE COMPARISON MATRIX

 +-------------------------------+----------------+------------------+--------------+----------------+-----------------+-------------+-------------------+------------------+--------------------+--------------+----------------+
 | module                        | align_cell *1) | align_column *2) | box_char *3) | color_data *4) | color_theme *5) | colspan *6) | custom_border *7) | custom_color *8) | multiline_data *9) | rowspan *10) | wide_char_data |
 +-------------------------------+----------------+------------------+--------------+----------------+-----------------+-------------+-------------------+------------------+--------------------+--------------+----------------+
 | Text::ANSITable               | yes            | yes              | yes          | yes            | yes             | no          | yes               | yes              | yes                | no           | yes            |
 | Text::ASCIITable              | N/A            | N/A              | no           | no             | N/A             | N/A         | N/A               | N/A              | yes                | N/A          | no             |
 | Text::FormatTable             | N/A            | N/A              | no           | no             | N/A             | N/A         | N/A               | N/A              | yes                | N/A          | no             |
 | Text::MarkdownTable           | N/A            | N/A              | no           | no             | N/A             | N/A         | N/A               | N/A              | no *11)            | N/A          | no             |
 | Text::Table                   | N/A            | N/A              | N/A *12)     | no             | N/A             | N/A         | N/A               | N/A              | yes                | N/A          | no             |
 | Text::Table::Tiny             | N/A            | N/A              | yes          | yes            | N/A             | N/A         | N/A               | N/A              | no                 | N/A          | yes            |
 | Text::Table::TinyBorderStyle  | N/A            | N/A              | yes          | no             | N/A             | N/A         | N/A               | N/A              | no                 | N/A          | no             |
 | Text::Table::Span             | no             | no               | yes          | no             | yes             | yes         | yes               | yes              | yes                | yes          | no             |
 | Text::Table::Sprintf          | N/A            | N/A              | no           | no             | N/A             | N/A         | N/A               | N/A              | no                 | N/A          | no             |
 | Text::Table::TinyColor        | N/A            | N/A              | no           | yes            | N/A             | N/A         | N/A               | N/A              | no                 | N/A          | no             |
 | Text::Table::TinyColorWide    | N/A            | N/A              | no           | yes            | N/A             | N/A         | N/A               | N/A              | no                 | N/A          | yes            |
 | Text::Table::TinyWide         | N/A            | N/A              | no           | no             | N/A             | N/A         | N/A               | N/A              | N/A                | N/A          | yes            |
 | Text::Table::Org              | N/A            | N/A              | no           | no             | N/A             | N/A         | N/A               | N/A              | no                 | N/A          | no             |
 | Text::Table::CSV              | N/A            | N/A              | N/A *13)     | no             | N/A             | N/A         | N/A               | N/A              | yes *14)           | N/A          | yes            |
 | Text::Table::HTML             | N/A            | N/A              | no           | no *15)        | N/A             | N/A         | N/A               | N/A              | yes                | N/A          | yes            |
 | Text::Table::HTML::DataTables | N/A            | N/A              | no           | no *16)        | N/A             | N/A         | N/A               | N/A              | yes                | N/A          | yes            |
 | Text::TabularDisplay          | N/A            | N/A              | N/A *17)     | no             | N/A             | N/A         | N/A               | N/A              | yes                | N/A          | yes            |
 +-------------------------------+----------------+------------------+--------------+----------------+-----------------+-------------+-------------------+------------------+--------------------+--------------+----------------+


Notes:

=over

=item 1. align_cell: Whether module supports aligning text in individual cells (left/right/middle)

=item 2. align_column: Whether module supports aligning text in a column (left/right/middle)

=item 3. box_char: Whether module can utilize box-drawing characters

=item 4. color_data: Whether module supports ANSI colors (i.e. text with ANSI color codes can still be aligned properly)

=item 5. color_theme: Whether the module supports color theme/scheme

=item 6. colspan: Whether module supports column spans

=item 7. custom_border: Whether module allows customizing border in some way

=item 8. custom_color: Whether the module produces colored table and supports customizing color in some way

=item 9. multiline_data: Whether module supports aligning data cells that contain newlines

=item 10. rowspan: Whether module supports row spans

=item 11. Newlines stripped

=item 12. Does not draw borders

=item 13. Irrelevant

=item 14. But make sure your CSV parser can handle multiline cell

=item 15. Not converted to HTML color elements

=item 16. Not converted to HTML color elements

=item 17. Irrelevant

=back

=head1 ACME::MODULES ENTRIES

=over

=item * L<Text::ANSITable>

=item * L<Text::ASCIITable>

=item * L<Text::FormatTable>

=item * L<Text::MarkdownTable>

=item * L<Text::Table>

=item * L<Text::Table::Tiny>

=item * L<Text::Table::TinyBorderStyle>

=item * L<Text::Table::Span>

=item * L<Text::Table::Sprintf>

=item * L<Text::Table::TinyColor>

=item * L<Text::Table::TinyColorWide>

=item * L<Text::Table::TinyWide>

=item * L<Text::Table::Org>

=item * L<Text::Table::CSV>

=item * L<Text::Table::HTML>

=item * L<Text::Table::HTML::DataTables>

=item * L<Text::TabularDisplay>

=back

=head1 FAQ

=head2 What is an Acme::CPANModules::* module?

An Acme::CPANModules::* module, like this module, contains just a list of module
names that share a common characteristics. It is a way to categorize modules and
document CPAN. See L<Acme::CPANModules> for more details.

=head2 What are ways to use this Acme::CPANModules module?

Aside from reading this Acme::CPANModules module's POD documentation, you can
install all the listed modules (entries) using L<cpanmodules> CLI (from
L<App::cpanmodules> distribution):

    % cpanmodules ls-entries TextTable | cpanm -n

or L<Acme::CM::Get>:

    % perl -MAcme::CM::Get=TextTable -E'say $_->{module} for @{ $LIST->{entries} }' | cpanm -n

or directly:

    % perl -MAcme::CPANModules::TextTable -E'say $_->{module} for @{ $Acme::CPANModules::TextTable::LIST->{entries} }' | cpanm -n

This Acme::CPANModules module contains benchmark instructions. You can run a
benchmark for some/all the modules listed in this Acme::CPANModules module using
the L<bencher> CLI (from L<Bencher> distribution):

    % bencher --cpanmodules-module TextTable

This Acme::CPANModules module also helps L<lcpan> produce a more meaningful
result for C<lcpan related-mods> command when it comes to finding related
modules for the modules listed in this Acme::CPANModules module.

=head1 HOMEPAGE

Please visit the project's homepage at L<https://metacpan.org/release/Acme-CPANModules-TextTable>.

=head1 SOURCE

Source repository is at L<https://github.com/perlancar/perl-Acme-CPANModules-TextTable>.

=head1 BUGS

Please report any bugs or feature requests on the bugtracker website L<https://github.com/perlancar/perl-Acme-CPANModules-TextTable/issues>

When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.

=head1 SEE ALSO

L<Acme::CPANModules> - about the Acme::CPANModules namespace

L<cpanmodules> - CLI tool to let you browse/view the lists

=head1 AUTHOR

perlancar <perlancar@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2021, 2020, 2019 by perlancar@cpan.org.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
