File Coverage

blib/lib/Term/FormatColumns.pm
Criterion Covered Total %
statement 36 43 83.7
branch 2 4 50.0
condition n/a
subroutine 8 10 80.0
pod 3 3 100.0
total 49 60 81.6


line stmt bran cond sub pod time code
1             package Term::FormatColumns;
2             {
3             $Term::FormatColumns::VERSION = '0.005';
4             }
5              
6 2         18 use Sub::Exporter -setup => [
7             exports => (
8             'format_columns', 'format_columns_for_fh', 'format_columns_for_width',
9             ),
10 2     2   35956 ];
  2         32176  
11              
12 2     2   2789 use Term::ReadKey qw( GetTerminalSize );
  2         11187  
  2         151  
13 2     2   40 use List::Util qw( max );
  2         4  
  2         226  
14 2     2   1754 use List::MoreUtils qw( part each_arrayref );
  2         2146  
  2         161  
15 2     2   1721 use POSIX qw( ceil );
  2         15704  
  2         14  
16 2     2   3933 use Symbol qw(qualify_to_ref);
  2         1735  
  2         755  
17              
18             sub format_columns(@) {
19 0     0 1 0 return format_columns_for_fh( STDOUT, @_ );
20             }
21              
22             sub format_columns_for_fh(*@) {
23 0     0 1 0 my $fh = qualify_to_ref( shift, caller );
24 0         0 my @data = @_;
25            
26             # If we're not attached to a terminal, one column, seperated by newlines
27 0 0       0 if ( !-t $fh ) {
28 0         0 return join "\n", @data;
29             }
30            
31             # We're attached to a terminal, print column-wise alphabetically to fit the
32             # terminal width
33 0         0 my ( $term_width, undef, undef, undef ) = GetTerminalSize();
34 0         0 return format_columns_for_width( $term_width, @data );
35             }
36              
37             sub format_columns_for_width($@) {
38 3     3 1 947 my ( $term_width, @data ) = @_;
39 3         8 my $max_width = max map { length } @data;
  18         41  
40 3         75 $max_width += 2; # make sure at least two spaces between data values
41 3         8 my $columns = int( $term_width / $max_width );
42 3 100       8 if ( $columns <= 1 ) {
43             # Only one column, let the terminal handle things
44 1         8 return join "\n", @data, undef; # Add a \n to the end
45             }
46 2         4 my $output = '';
47 2         4 my $column_width = int( $term_width / $columns );
48 2         10 my $format = "\%-${column_width}s" x ($columns-1) . "\%s\n";
49 2         19 my $rows = ceil( @data / $columns );
50 2     12   23 my @index = part { int( $_ / $rows ) } 0..$#data;
  12         32  
51 2         29 my $iter = each_arrayref @index;
52 2         23 while ( my @row_vals = $iter->() ) {
53 5         7 $output .= sprintf $format, map { $data[$_] } @row_vals;
  12         49  
54             }
55 2         13 return $output;
56             }
57              
58             1;
59              
60             =head1 NAME
61              
62             Term::FormatColumns - Format lists of data into columns across the terminal's width
63              
64             =head1 SYNOPSIS
65              
66             use Term::FormatColumns qw( format_columns );
67             my @list = 0..1000;
68             print format_columns @list;
69              
70             =head1 DESCRIPTION
71              
72             This module will take a list and format it into columns that stretch across the
73             current terminal's width, much like the output of ls(1).
74              
75             If the filehandle is not attached to a tty, will simply write one column of output
76             (again, like ls(1)).
77              
78             =head1 FUNCTIONS
79              
80             =head2 format_columns
81              
82             my $string = format_columns @array;
83              
84             Format the list of data for STDOUT. Returns a single string formatted and ready for output.
85              
86             =head2 format_columns_for_fh
87              
88             my $string = format_columns_for_fh $fh, @array;
89             my $string = format_columns_for_fh STDOUT, @array;
90              
91             Format the given data for the given filehandle. If the filehandle is attached to a tty,
92             will get the tty's width to determine how to format the data.
93              
94             =head2 format_columns_for_width
95              
96             my $string = format_columns_for_width 78, @array;
97              
98             Format the given data for the given width. This allows you to use this module without
99             being attached to a known/knowable terminal.
100              
101             =head1 COPYRIGHT
102              
103             Copyright 2012, Doug Bell
104              
105             =head1 LICENSE
106              
107             This distribution is free software; you can redistribute it and/or modify it
108             under the same terms as Perl 5.14.2.
109              
110             This program is distributed in the hope that it will be
111             useful, but without any warranty; without even the implied
112             warranty of merchantability or fitness for a particular purpose.