package Acme::CPANModules::TextTable;

our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
our $DATE = '2021-01-31'; # DATE
our $DIST = 'Acme-CPANModules-TextTable'; # DIST
our $VERSION = '0.007'; # 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 => {summary => 'Whether the module supports ANSI colors (i.e. text with ANSI color codes can still be aligned properly)'},
        box_char => {summary => 'Whether the module can utilize box-drawing characters'},
        multiline_data => {summary => 'Whether the module supports aligning data cells that contain newlines'},
    },
    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 => {
                wide_char => 1,
                color => 1,
                box_char => 1,
                multiline_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 => 0,
                color => 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 => 0,
                color => 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 => 0,
                color => 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 => 0,
                color => 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 => 1,
                color => 1,
                box_char => 1,
                multiline_data => 0,
            },
        },
        {
            module => 'Text::Table::Sprintf',
            bench_code => sub {
                my ($table) = @_;
                Text::Table::Sprintf::table(rows=>$table, header_row=>1);
            },
            features => {
                wide_char => 0,
                color => 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 => 0,
                color => 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 => 1,
                color => 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 => 1,
                color => 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 => 0,
                color => 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 => 1,
                color => 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 => 1,
                color => {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 => 1,
                color => {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 => 1,
                color => 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.007 of Acme::CPANModules::TextTable (from Perl distribution Acme-CPANModules-TextTable), released on 2021-01-31.

=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::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::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.5 |    400    |                 0.00% |             18928.56% |   0.00073 |      20 |
 | Text::ASCIITable              |      12   |     81    |               395.62% |              3739.35% |   0.0003  |      20 |
 | Text::Table::TinyColorWide    |      14   |     71    |               471.69% |              3228.46% |   0.0007  |      20 |
 | Text::FormatTable             |      19   |     53    |               665.28% |              2386.50% |   7e-05   |      20 |
 | Text::Table::TinyWide         |      23   |     43    |               829.64% |              1946.88% |   0.0002  |      20 |
 | Text::TabularDisplay          |      49.4 |     20.2  |              1894.65% |               853.98% | 1.6e-05   |      20 |
 | Text::Table::Tiny             |      61   |     17    |              2345.84% |               678.00% |   0.00014 |      21 |
 | Text::Table::TinyColor        |      65.6 |     15.3  |              2546.30% |               619.06% | 9.2e-06   |      20 |
 | Text::MarkdownTable           |      96.8 |     10.3  |              3808.48% |               386.85% | 6.2e-06   |      20 |
 | Text::Table                   |     120   |      8.1  |              4882.65% |               281.90% | 1.4e-05   |      21 |
 | Text::Table::HTML             |     130   |      7.6  |              5225.51% |               257.31% | 1.7e-05   |      20 |
 | Text::Table::HTML::DataTables |     133   |      7.5  |              5279.64% |               253.71% | 4.1e-06   |      20 |
 | Text::Table::Org              |     240   |      4.2  |              9620.41% |                95.76% | 1.6e-05   |      20 |
 | Text::Table::CSV              |     242   |      4.14 |              9652.55% |                95.11% | 3.1e-06   |      20 |
 | Text::Table::Sprintf          |     470   |      2.1  |             18928.56% |                 0.00% | 2.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% |             13927.39% |   0.00014 |      22 |
 | Text::ASCIITable              |       130 |     7.6   |               466.40% |              2376.60% | 1.9e-05   |      20 |
 | Text::Table::TinyColorWide    |       160 |     6.1   |               603.49% |              1893.96% | 1.3e-05   |      20 |
 | Text::FormatTable             |       170 |     5.89  |               633.90% |              1811.34% | 4.7e-06   |      20 |
 | Text::Table::TinyWide         |       200 |     5     |               762.73% |              1525.93% | 8.4e-05   |      20 |
 | Text::TabularDisplay          |       360 |     2.8   |              1467.82% |               794.71% | 3.1e-06   |      20 |
 | Text::MarkdownTable           |       455 |     2.2   |              1867.65% |               612.90% | 1.1e-06   |      20 |
 | Text::Table                   |       544 |     1.84  |              2254.65% |               495.73% | 1.3e-06   |      20 |
 | Text::Table::Tiny             |       590 |     1.7   |              2450.28% |               450.03% | 1.8e-06   |      20 |
 | Text::Table::TinyColor        |       620 |     1.6   |              2561.86% |               426.98% | 3.3e-06   |      21 |
 | Text::Table::HTML::DataTables |      1060 |     0.947 |              4470.11% |               206.94% | 4.3e-07   |      20 |
 | Text::Table::HTML             |      1110 |     0.898 |              4718.73% |               191.10% | 4.3e-07   |      20 |
 | Text::Table::Org              |      1800 |     0.55  |              7756.02% |                78.56% | 1.1e-06   |      20 |
 | Text::Table::CSV              |      1830 |     0.546 |              7830.18% |                76.89% | 2.1e-07   |      20 |
 | Text::Table::Sprintf          |      3200 |     0.31  |             13927.39% |                 0.00% | 9.1e-07   |      20 |
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+-----------+---------+

 #table3#
 {dataset=>"small (3x5)"}
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+
 | participant                   | rate (/s) | time (μs) | pct_faster_vs_slowest | pct_slower_vs_fastest |  errors | samples |
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+
 | Text::ANSITable               |       910 |    1100   |                 0.00% |             10895.11% | 1.4e-06 |      20 |
 | Text::Table::TinyColorWide    |      4000 |     200   |               350.12% |              2342.71% | 2.7e-06 |      21 |
 | Text::ASCIITable              |      5000 |     200   |               449.75% |              1900.02% | 2.4e-07 |      24 |
 | Text::FormatTable             |      7200 |     140   |               689.94% |              1291.89% | 2.1e-07 |      20 |
 | Text::Table                   |      7800 |     130   |               759.56% |              1179.15% | 2.1e-07 |      20 |
 | Text::Table::TinyWide         |      9000 |     100   |               863.28% |              1041.42% | 2.4e-06 |      20 |
 | Text::MarkdownTable           |     13000 |      78   |              1312.45% |               678.44% | 1.1e-07 |      20 |
 | Text::TabularDisplay          |     15000 |      65   |              1577.01% |               555.64% | 8.4e-08 |      32 |
 | Text::Table::HTML::DataTables |     16000 |      63   |              1631.44% |               535.03% | 1.2e-07 |      24 |
 | Text::Table::Tiny             |     20000 |      60   |              1839.05% |               467.04% | 6.7e-07 |      20 |
 | Text::Table::TinyColor        |     24000 |      42   |              2520.81% |               319.53% | 1.6e-07 |      20 |
 | Text::Table::HTML             |     47700 |      20.9 |              5134.20% |               110.06% |   2e-08 |      21 |
 | Text::Table::Org              |     50000 |      20   |              5620.27% |                92.21% | 2.5e-07 |      21 |
 | Text::Table::CSV              |     80900 |      12.4 |              8769.01% |                23.97% | 3.3e-09 |      20 |
 | Text::Table::Sprintf          |    100000 |      10   |             10895.11% |                 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               |      3400 |    300    |                 0.00% |              8614.88% | 3.9e-07 |      24 |
 | Text::ASCIITable              |     20000 |     60    |               381.45% |              1710.14% |   1e-06 |      25 |
 | Text::Table                   |     21000 |     48    |               525.48% |              1293.31% | 6.2e-08 |      23 |
 | Text::Table::HTML::DataTables |     22000 |     45    |               555.02% |              1230.47% | 6.7e-08 |      20 |
 | Text::Table::TinyColorWide    |     20000 |     50    |               559.05% |              1222.35% | 5.7e-07 |      20 |
 | Text::MarkdownTable           |     26000 |     39    |               660.43% |              1046.04% | 6.2e-08 |      23 |
 | Text::FormatTable             |     35000 |     29    |               936.63% |               740.69% | 5.4e-08 |      31 |
 | Text::Table::TinyWide         |     40000 |     20    |              1140.10% |               602.75% | 6.1e-07 |      20 |
 | Text::TabularDisplay          |     61000 |     16.4  |              1713.10% |               380.66% | 6.7e-09 |      20 |
 | Text::Table::Tiny             |     66100 |     15.1  |              1865.03% |               343.50% | 6.7e-09 |      20 |
 | Text::Table::TinyColor        |     95000 |     11    |              2719.89% |               209.05% | 1.3e-08 |      20 |
 | Text::Table::Org              |    150000 |      6.8  |              4297.97% |                98.16% | 1.3e-08 |      20 |
 | Text::Table::HTML             |    186000 |      5.37 |              5437.74% |                57.37% |   5e-09 |      20 |
 | Text::Table::Sprintf          |    290000 |      3.4  |              8527.96% |                 1.01% |   5e-09 |      20 |
 | Text::Table::CSV              |    290000 |      3.4  |              8614.88% |                 0.00% | 4.9e-09 |      21 |
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+

 #table5#
 {dataset=>"wide (30x5)"}
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+
 | participant                   | rate (/s) | time (ms) | pct_faster_vs_slowest | pct_slower_vs_fastest |  errors | samples |
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+
 | Text::ANSITable               |       110 |    8.7    |                 0.00% |             13644.36% | 1.2e-05 |      20 |
 | Text::Table::TinyColorWide    |       500 |    2      |               344.43% |              2992.56% | 9.6e-05 |      20 |
 | Text::ASCIITable              |       540 |    1.85   |               370.80% |              2819.39% | 9.6e-07 |      20 |
 | Text::FormatTable             |       750 |    1.33   |               554.66% |              1999.46% | 6.9e-07 |      20 |
 | Text::Table::TinyWide         |      1000 |    0.9    |               894.25% |              1282.39% | 1.1e-05 |      20 |
 | Text::Table                   |      1230 |    0.811  |               976.06% |              1177.29% | 4.8e-07 |      20 |
 | Text::TabularDisplay          |      2350 |    0.425  |              1951.27% |               570.04% |   2e-07 |      23 |
 | Text::Table::Tiny             |      3000 |    0.33   |              2549.76% |               418.70% | 3.4e-07 |      24 |
 | Text::Table::TinyColor        |      3100 |    0.32   |              2604.83% |               408.14% | 4.2e-07 |      21 |
 | Text::MarkdownTable           |      3680 |    0.272  |              3111.40% |               327.99% | 2.1e-07 |      20 |
 | Text::Table::HTML::DataTables |      5150 |    0.194  |              4393.70% |               205.86% | 1.5e-07 |      22 |
 | Text::Table::HTML             |      6700 |    0.15   |              5731.49% |               135.69% | 2.1e-07 |      20 |
 | Text::Table::Org              |      8500 |    0.12   |              7300.58% |                85.72% | 1.1e-06 |      20 |
 | Text::Table::CSV              |     12300 |    0.0813 |             10629.24% |                28.10% | 2.5e-08 |      22 |
 | Text::Table::Sprintf          |     15800 |    0.0635 |             13644.36% |                 0.00% | 2.2e-08 |      30 |
 +-------------------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+


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               |      45   | 35                  |                 0.00% |               433.86% | 8.3e-05   |      20 |
 | Text::MarkdownTable           |      41   | 31                  |                 8.78% |               390.76% | 8.6e-05   |      20 |
 | Text::Table::TinyColorWide    |      34   | 24                  |                30.86% |               307.96% |   0.00024 |      20 |
 | Text::Table::TinyWide         |      31   | 21                  |                43.78% |               271.30% |   0.00027 |      20 |
 | Text::Table                   |      22   | 12                  |                99.57% |               167.50% | 7.6e-05   |      20 |
 | Text::ASCIITable              |      18   |  8                  |               154.32% |               109.92% | 6.1e-05   |      20 |
 | Text::FormatTable             |      16   |  6                  |               174.56% |                94.45% |   0.00011 |      20 |
 | Text::Table::Tiny             |      15   |  5                  |               194.53% |                81.26% | 5.7e-05   |      21 |
 | Text::Table::TinyColor        |      15   |  5                  |               206.28% |                74.30% | 8.6e-05   |      20 |
 | Text::TabularDisplay          |      10   |  0                  |               327.55% |                24.86% |   3e-05   |      20 |
 | Text::Table::HTML             |      10   |  0                  |               329.91% |                24.18% | 7.1e-05   |      22 |
 | Text::Table::Sprintf          |      10   |  0                  |               337.99% |                21.89% | 7.4e-05   |      21 |
 | perl -e1 (baseline)           |      10   |  0                  |               353.07% |                17.83% |   0.00019 |      20 |
 | Text::Table::HTML::DataTables |       9.9 | -0.0999999999999996 |               354.89% |                17.36% | 1.4e-05   |      21 |
 | Text::Table::CSV              |       8.7 | -1.3                |               414.64% |                 3.74% | 2.8e-05   |      21 |
 | Text::Table::Org              |       8.4 | -1.6                |               433.86% |                 0.00% | 9.9e-06   |      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                        | box_char *1) | color *2) | multiline_data *3) | wide_char *4) |
 +-------------------------------+--------------+-----------+--------------------+---------------+
 | Text::ANSITable               | yes          | yes       | yes                | yes           |
 | Text::ASCIITable              | no           | no        | yes                | no            |
 | Text::FormatTable             | no           | no        | yes                | no            |
 | Text::MarkdownTable           | no           | no        | no *5)             | no            |
 | Text::Table                   | N/A *6)      | no        | yes                | no            |
 | Text::Table::Tiny             | yes          | yes       | no                 | yes           |
 | Text::Table::Sprintf          | no           | no        | no                 | no            |
 | Text::Table::TinyColor        | no           | yes       | no                 | no            |
 | Text::Table::TinyColorWide    | no           | yes       | no                 | yes           |
 | Text::Table::TinyWide         | no           | no        | N/A                | yes           |
 | Text::Table::Org              | no           | no        | no                 | no            |
 | Text::Table::CSV              | N/A *7)      | no        | yes *8)            | yes           |
 | Text::Table::HTML             | no           | no *9)    | yes                | yes           |
 | Text::Table::HTML::DataTables | no           | no *10)   | yes                | yes           |
 | Text::TabularDisplay          | N/A *11)     | no        | yes                | yes           |
 +-------------------------------+--------------+-----------+--------------------+---------------+


Notes:

=over

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

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

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

=item 4. wide_char: Whether the use of wide characters (e.g. Kanji) in cells does not cause the table to be misaligned

=item 5. Newlines stripped

=item 6. Does not draw borders

=item 7. Irrelevant

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

=item 9. Not converted to HTML color elements

=item 10. Not converted to HTML color elements

=item 11. 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::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
