line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
use 5.010001; |
3
|
2
|
|
|
2
|
|
174579
|
use Carp; |
|
2
|
|
|
|
|
25
|
|
4
|
2
|
|
|
2
|
|
11
|
use Log::ger; |
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
115
|
|
5
|
2
|
|
|
2
|
|
2825
|
use Moo; |
|
2
|
|
|
|
|
83
|
|
|
2
|
|
|
|
|
8
|
|
6
|
2
|
|
|
2
|
|
1243
|
use experimental 'smartmatch'; |
|
2
|
|
|
|
|
18393
|
|
|
2
|
|
|
|
|
7
|
|
7
|
2
|
|
|
2
|
|
3189
|
|
|
2
|
|
|
|
|
5630
|
|
|
2
|
|
|
|
|
10
|
|
8
|
|
|
|
|
|
|
use ColorThemeUtil::ANSI qw(item_color_to_ansi); |
9
|
2
|
|
|
2
|
|
884
|
#use List::Util qw(first); |
|
2
|
|
|
|
|
713
|
|
|
2
|
|
|
|
|
88
|
|
10
|
|
|
|
|
|
|
use Scalar::Util 'looks_like_number'; |
11
|
2
|
|
|
2
|
|
12
|
require Win32::Console::ANSI if $^O =~ /Win/; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
19472
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY |
14
|
|
|
|
|
|
|
our $DATE = '2022-02-14'; # DATE |
15
|
|
|
|
|
|
|
our $DIST = 'Text-ANSITable'; # DIST |
16
|
|
|
|
|
|
|
our $VERSION = '0.608'; # VERSION |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# see Module::Features for more details on this |
19
|
|
|
|
|
|
|
our %FEATURES = ( |
20
|
|
|
|
|
|
|
set_v => { |
21
|
|
|
|
|
|
|
TextTable => 1, |
22
|
|
|
|
|
|
|
}, |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
features => { |
25
|
|
|
|
|
|
|
PerlTrove => { |
26
|
|
|
|
|
|
|
"Development Status" => "5 - Production/Stable", |
27
|
|
|
|
|
|
|
"Environment" => "Console", |
28
|
|
|
|
|
|
|
# Framework |
29
|
|
|
|
|
|
|
"Intended Audience" => ["Developers"], |
30
|
|
|
|
|
|
|
"License" => "OSI Approved :: Artistic License", |
31
|
|
|
|
|
|
|
# Natural Language |
32
|
|
|
|
|
|
|
# Operating System |
33
|
|
|
|
|
|
|
"Programming Language" => "Perl", |
34
|
|
|
|
|
|
|
"Topic" => ["Software Development :: Libraries :: Perl Modules", "Utilities"], |
35
|
|
|
|
|
|
|
# Typing |
36
|
|
|
|
|
|
|
}, |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
TextTable => { |
39
|
|
|
|
|
|
|
can_align_cell_containing_wide_character => 1, |
40
|
|
|
|
|
|
|
can_align_cell_containing_color_code => 1, |
41
|
|
|
|
|
|
|
can_align_cell_containing_newline => 1, |
42
|
|
|
|
|
|
|
can_use_box_character => 1, |
43
|
|
|
|
|
|
|
can_customize_border => 1, |
44
|
|
|
|
|
|
|
can_halign => 1, |
45
|
|
|
|
|
|
|
can_halign_individual_row => 1, |
46
|
|
|
|
|
|
|
can_halign_individual_column => 1, |
47
|
|
|
|
|
|
|
can_halign_individual_cell => 1, |
48
|
|
|
|
|
|
|
can_valign => 1, |
49
|
|
|
|
|
|
|
can_valign_individual_row => 1, |
50
|
|
|
|
|
|
|
can_valign_individual_column => 1, |
51
|
|
|
|
|
|
|
can_valign_individual_cell => 1, |
52
|
|
|
|
|
|
|
can_rowspan => 0, |
53
|
|
|
|
|
|
|
can_colspan => 0, |
54
|
|
|
|
|
|
|
can_color => 1, |
55
|
|
|
|
|
|
|
can_color_theme => 1, |
56
|
|
|
|
|
|
|
can_set_cell_height => 1, |
57
|
|
|
|
|
|
|
can_set_cell_height_of_individual_row => 1, |
58
|
|
|
|
|
|
|
can_set_cell_width => 1, |
59
|
|
|
|
|
|
|
can_set_cell_width_of_individual_column => 1, |
60
|
|
|
|
|
|
|
speed => 'slow', |
61
|
|
|
|
|
|
|
can_hpad => 1, |
62
|
|
|
|
|
|
|
can_hpad_individual_row => 1, |
63
|
|
|
|
|
|
|
can_hpad_individual_column => 1, |
64
|
|
|
|
|
|
|
can_hpad_individual_cell => 1, |
65
|
|
|
|
|
|
|
can_vpad => 1, |
66
|
|
|
|
|
|
|
can_vpad_individual_row => 1, |
67
|
|
|
|
|
|
|
can_vpad_individual_column => 1, |
68
|
|
|
|
|
|
|
can_vpad_individual_cell => 1, |
69
|
|
|
|
|
|
|
}, |
70
|
|
|
|
|
|
|
}, |
71
|
|
|
|
|
|
|
); |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
my $ATTRS = [qw( |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
use_color color_depth use_box_chars use_utf8 columns rows |
76
|
|
|
|
|
|
|
column_filter row_filter show_row_separator show_header |
77
|
|
|
|
|
|
|
show_header cell_width cell_height cell_pad cell_lpad |
78
|
|
|
|
|
|
|
cell_rpad cell_vpad cell_tpad cell_bpad cell_fgcolor |
79
|
|
|
|
|
|
|
cell_bgcolor cell_align cell_valign header_align header_valign |
80
|
|
|
|
|
|
|
header_vpad header_tpad header_bpad header_fgcolor |
81
|
|
|
|
|
|
|
header_bgcolor |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
)]; |
84
|
|
|
|
|
|
|
my $STYLES = $ATTRS; |
85
|
|
|
|
|
|
|
my $COLUMN_STYLES = [qw( |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
type width align valign pad lpad rpad formats fgcolor |
88
|
|
|
|
|
|
|
bgcolor wrap |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
)]; |
91
|
|
|
|
|
|
|
my $ROW_STYLES = [qw( |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
height align valign vpad tpad bpad fgcolor bgcolor |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
)]; |
96
|
|
|
|
|
|
|
my $CELL_STYLES = [qw( |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
align valign formats fgcolor bgcolor |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
)]; |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
has border_style => ( |
103
|
|
|
|
|
|
|
is => 'rw', |
104
|
|
|
|
|
|
|
trigger => sub { |
105
|
|
|
|
|
|
|
require Module::Load::Util; |
106
|
|
|
|
|
|
|
my ($self, $val) = @_; |
107
|
|
|
|
|
|
|
$self->{border_style_obj} = |
108
|
|
|
|
|
|
|
Module::Load::Util::instantiate_class_with_optional_args( |
109
|
|
|
|
|
|
|
{ns_prefixes=>['BorderStyle::Text::ANSITable', 'BorderStyle', 'BorderStyle::Text::ANSITable::OldCompat']}, $val); |
110
|
|
|
|
|
|
|
}, |
111
|
|
|
|
|
|
|
); |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
has color_theme => ( |
114
|
|
|
|
|
|
|
is => 'rw', |
115
|
|
|
|
|
|
|
trigger => sub { |
116
|
|
|
|
|
|
|
require Module::Load::Util; |
117
|
|
|
|
|
|
|
my ($self, $val) = @_; |
118
|
|
|
|
|
|
|
$self->{color_theme_obj} = |
119
|
|
|
|
|
|
|
Module::Load::Util::instantiate_class_with_optional_args( |
120
|
|
|
|
|
|
|
{ns_prefixes=>['ColorTheme::Text::ANSITable', 'ColorTheme', 'ColorTheme::Text::ANSITable::OldCompat']}, $val); |
121
|
|
|
|
|
|
|
}, |
122
|
|
|
|
|
|
|
); |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
has columns => ( |
125
|
|
|
|
|
|
|
is => 'rw', |
126
|
|
|
|
|
|
|
default => sub { [] }, |
127
|
|
|
|
|
|
|
trigger => sub { |
128
|
|
|
|
|
|
|
my $self = shift; |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# check that column names are unique |
131
|
|
|
|
|
|
|
my %seen; |
132
|
|
|
|
|
|
|
for (@{$_[0]}) { die "Duplicate column name '$_'" if $seen{$_}++ } |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
$self->{_columns_set}++; |
135
|
|
|
|
|
|
|
}, |
136
|
|
|
|
|
|
|
); |
137
|
|
|
|
|
|
|
has rows => ( |
138
|
|
|
|
|
|
|
is => 'rw', |
139
|
|
|
|
|
|
|
default => sub { [] }, |
140
|
|
|
|
|
|
|
trigger => sub { |
141
|
|
|
|
|
|
|
my ($self, $rows) = @_; |
142
|
|
|
|
|
|
|
$self->_set_default_cols($rows->[0]); |
143
|
|
|
|
|
|
|
}, |
144
|
|
|
|
|
|
|
); |
145
|
|
|
|
|
|
|
has column_filter => ( |
146
|
|
|
|
|
|
|
is => 'rw', |
147
|
|
|
|
|
|
|
); |
148
|
|
|
|
|
|
|
has column_wrap => ( |
149
|
|
|
|
|
|
|
is => 'rw', |
150
|
|
|
|
|
|
|
); |
151
|
|
|
|
|
|
|
has row_filter => ( |
152
|
|
|
|
|
|
|
is => 'rw', |
153
|
|
|
|
|
|
|
); |
154
|
|
|
|
|
|
|
has _row_separators => ( # [index after which sep should be drawn, ...] sorted |
155
|
|
|
|
|
|
|
is => 'rw', |
156
|
|
|
|
|
|
|
default => sub { [] }, |
157
|
|
|
|
|
|
|
); |
158
|
|
|
|
|
|
|
has show_row_separator => ( |
159
|
|
|
|
|
|
|
is => 'rw', |
160
|
|
|
|
|
|
|
default => sub { 2 }, |
161
|
|
|
|
|
|
|
); |
162
|
|
|
|
|
|
|
has show_header => ( |
163
|
|
|
|
|
|
|
is => 'rw', |
164
|
|
|
|
|
|
|
default => sub { 1 }, |
165
|
|
|
|
|
|
|
); |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
has _column_styles => ( # store per-column styles |
168
|
|
|
|
|
|
|
is => 'rw', |
169
|
|
|
|
|
|
|
default => sub { [] }, |
170
|
|
|
|
|
|
|
); |
171
|
|
|
|
|
|
|
has _row_styles => ( # store per-row styles |
172
|
|
|
|
|
|
|
is => 'rw', |
173
|
|
|
|
|
|
|
default => sub { [] }, |
174
|
|
|
|
|
|
|
); |
175
|
|
|
|
|
|
|
has _cell_styles => ( # store per-cell styles |
176
|
|
|
|
|
|
|
is => 'rw', |
177
|
|
|
|
|
|
|
default => sub { [] }, |
178
|
|
|
|
|
|
|
); |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
# each element of _cond_*styles is a two-element [$cond, ], where $cond is code |
181
|
|
|
|
|
|
|
# (str|coderef) and the second element is a hashref containing styles. |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
has _cond_column_styles => ( # store conditional column styles |
184
|
|
|
|
|
|
|
is => 'rw', |
185
|
|
|
|
|
|
|
default => sub { [] }, |
186
|
|
|
|
|
|
|
); |
187
|
|
|
|
|
|
|
has _cond_row_styles => ( # store conditional row styles |
188
|
|
|
|
|
|
|
is => 'rw', |
189
|
|
|
|
|
|
|
default => sub { [] }, |
190
|
|
|
|
|
|
|
); |
191
|
|
|
|
|
|
|
has _cond_cell_styles => ( # store conditional cell styles |
192
|
|
|
|
|
|
|
is => 'rw', |
193
|
|
|
|
|
|
|
default => sub { [] }, |
194
|
|
|
|
|
|
|
); |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
has cell_width => ( |
197
|
|
|
|
|
|
|
is => 'rw', |
198
|
|
|
|
|
|
|
); |
199
|
|
|
|
|
|
|
has cell_height => ( |
200
|
|
|
|
|
|
|
is => 'rw', |
201
|
|
|
|
|
|
|
); |
202
|
|
|
|
|
|
|
has cell_pad => ( |
203
|
|
|
|
|
|
|
is => 'rw', |
204
|
|
|
|
|
|
|
default => sub { 1 }, |
205
|
|
|
|
|
|
|
); |
206
|
|
|
|
|
|
|
has cell_lpad => ( |
207
|
|
|
|
|
|
|
is => 'rw', |
208
|
|
|
|
|
|
|
); |
209
|
|
|
|
|
|
|
has cell_rpad => ( |
210
|
|
|
|
|
|
|
is => 'rw', |
211
|
|
|
|
|
|
|
); |
212
|
|
|
|
|
|
|
has cell_vpad => ( |
213
|
|
|
|
|
|
|
is => 'rw', |
214
|
|
|
|
|
|
|
default => sub { 0 }, |
215
|
|
|
|
|
|
|
); |
216
|
|
|
|
|
|
|
has cell_tpad => ( |
217
|
|
|
|
|
|
|
is => 'rw', |
218
|
|
|
|
|
|
|
); |
219
|
|
|
|
|
|
|
has cell_bpad => ( |
220
|
|
|
|
|
|
|
is => 'rw', |
221
|
|
|
|
|
|
|
); |
222
|
|
|
|
|
|
|
has cell_fgcolor => ( |
223
|
|
|
|
|
|
|
is => 'rw', |
224
|
|
|
|
|
|
|
); |
225
|
|
|
|
|
|
|
has cell_bgcolor => ( |
226
|
|
|
|
|
|
|
is => 'rw', |
227
|
|
|
|
|
|
|
); |
228
|
|
|
|
|
|
|
has cell_align => ( |
229
|
|
|
|
|
|
|
is => 'rw', |
230
|
|
|
|
|
|
|
); |
231
|
|
|
|
|
|
|
has cell_valign => ( |
232
|
|
|
|
|
|
|
is => 'rw', |
233
|
|
|
|
|
|
|
); |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
has header_align => ( |
236
|
|
|
|
|
|
|
is => 'rw', |
237
|
|
|
|
|
|
|
); |
238
|
|
|
|
|
|
|
has header_valign => ( |
239
|
|
|
|
|
|
|
is => 'rw', |
240
|
|
|
|
|
|
|
); |
241
|
|
|
|
|
|
|
has header_vpad => ( |
242
|
|
|
|
|
|
|
is => 'rw', |
243
|
|
|
|
|
|
|
); |
244
|
|
|
|
|
|
|
has header_tpad => ( |
245
|
|
|
|
|
|
|
is => 'rw', |
246
|
|
|
|
|
|
|
); |
247
|
|
|
|
|
|
|
has header_bpad => ( |
248
|
|
|
|
|
|
|
is => 'rw', |
249
|
|
|
|
|
|
|
); |
250
|
|
|
|
|
|
|
has header_fgcolor => ( |
251
|
|
|
|
|
|
|
is => 'rw', |
252
|
|
|
|
|
|
|
); |
253
|
|
|
|
|
|
|
has header_bgcolor => ( |
254
|
|
|
|
|
|
|
is => 'rw', |
255
|
|
|
|
|
|
|
); |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
with 'Term::App::Role::Attrs'; |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
my ($self, $item, $args, $is_bg) = @_; |
260
|
|
|
|
|
|
|
item_color_to_ansi( |
261
|
8
|
|
|
8
|
|
8964
|
($self->{color_theme_obj}->get_item_color($item, $args) // undef), # because sometimes get_item_color() might return an empty list |
262
|
|
|
|
|
|
|
$is_bg) |
263
|
8
|
|
50
|
|
|
36
|
// ''; |
|
|
|
50
|
|
|
|
|
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
my ($self, $args) = @_; |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
if ($ENV{ANSITABLE_STYLE_SETS}) { |
269
|
3
|
|
|
3
|
0
|
29
|
require JSON::MaybeXS; |
270
|
|
|
|
|
|
|
my $sets = JSON::MaybeXS::decode_json($ENV{ANSITABLE_STYLE_SETS}); |
271
|
3
|
50
|
|
|
|
13
|
croak "ANSITABLE_STYLE_SETS must be an array" |
272
|
0
|
|
|
|
|
0
|
unless ref($sets) eq 'ARRAY'; |
273
|
0
|
|
|
|
|
0
|
for my $set (@$sets) { |
274
|
0
|
0
|
|
|
|
0
|
if (ref($set) eq 'ARRAY') { |
275
|
|
|
|
|
|
|
$self->apply_style_set($set->[0], $set->[1]); |
276
|
0
|
|
|
|
|
0
|
} else { |
277
|
0
|
0
|
|
|
|
0
|
$self->apply_style_set($set); |
278
|
0
|
|
|
|
|
0
|
} |
279
|
|
|
|
|
|
|
} |
280
|
0
|
|
|
|
|
0
|
} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
if ($ENV{ANSITABLE_STYLE}) { |
283
|
|
|
|
|
|
|
require JSON::MaybeXS; |
284
|
|
|
|
|
|
|
my $s = JSON::MaybeXS::decode_json($ENV{ANSITABLE_STYLE}); |
285
|
3
|
50
|
|
|
|
10
|
for my $k (keys %$s) { |
286
|
0
|
|
|
|
|
0
|
my $v = $s->{$k}; |
287
|
0
|
|
|
|
|
0
|
croak "Unknown table style '$k' in ANSITABLE_STYLE environment, ". |
288
|
0
|
|
|
|
|
0
|
"please use one of [".join(", ", @$STYLES)."]" |
289
|
0
|
|
|
|
|
0
|
unless $k ~~ $STYLES; |
290
|
0
|
0
|
|
|
|
0
|
$self->{$k} = $v; |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
} |
293
|
0
|
|
|
|
|
0
|
|
294
|
|
|
|
|
|
|
# pick a default border style |
295
|
|
|
|
|
|
|
unless ($self->{border_style}) { |
296
|
|
|
|
|
|
|
my $bs; |
297
|
|
|
|
|
|
|
|
298
|
3
|
50
|
|
|
|
9
|
my $use_utf8 = $self->use_utf8; |
299
|
3
|
|
|
|
|
5
|
|
300
|
|
|
|
|
|
|
# even though Term::Detect::Software decides that linux virtual console |
301
|
3
|
|
|
|
|
48
|
# does not support unicode, it actually can display some uni characters |
302
|
|
|
|
|
|
|
# like single borders, so we use it as the default here instead of |
303
|
|
|
|
|
|
|
# singleo_ascii (linux vc doesn't seem to support box_chars). |
304
|
|
|
|
|
|
|
my $emu_eng = $self->detect_terminal->{emulator_engine} // ''; |
305
|
|
|
|
|
|
|
my $linux_vc = $emu_eng eq 'linux' && !defined($ENV{UTF8}); |
306
|
|
|
|
|
|
|
if ($linux_vc) { |
307
|
3
|
|
50
|
|
|
34446
|
$use_utf8 = 1; |
308
|
3
|
|
33
|
|
|
72
|
$bs = 'UTF8::SingleLineOuterOnly'; |
309
|
3
|
50
|
|
|
|
53
|
} |
310
|
0
|
|
|
|
|
0
|
# use statement modifier style to avoid block and make local work |
311
|
0
|
|
|
|
|
0
|
local $self->{use_utf8} = 1 if $linux_vc; |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
# we only default to utf8 border if user has set something like |
314
|
3
|
50
|
|
|
|
22
|
# binmode(STDOUT, ":utf8") to avoid 'Wide character in print' warning. |
315
|
|
|
|
|
|
|
unless (defined $ENV{UTF8}) { |
316
|
|
|
|
|
|
|
require PerlIO; |
317
|
|
|
|
|
|
|
my @layers = PerlIO::get_layers(STDOUT); |
318
|
3
|
50
|
|
|
|
22
|
$use_utf8 = 0 unless 'utf8' ~~ @layers; |
319
|
3
|
|
|
|
|
46
|
} |
320
|
3
|
|
|
|
|
44
|
|
321
|
3
|
50
|
|
|
|
31
|
if (defined $ENV{ANSITABLE_BORDER_STYLE}) { |
322
|
|
|
|
|
|
|
$bs = $ENV{ANSITABLE_BORDER_STYLE}; |
323
|
|
|
|
|
|
|
} elsif (defined $ENV{BORDER_STYLE}) { |
324
|
3
|
50
|
|
|
|
215
|
$bs = $ENV{BORDER_STYLE}; |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
325
|
0
|
|
|
|
|
0
|
} elsif ($use_utf8) { |
326
|
|
|
|
|
|
|
$bs //= 'UTF8::BrickOuterOnly'; |
327
|
0
|
|
|
|
|
0
|
} elsif ($self->use_box_chars) { |
328
|
|
|
|
|
|
|
$bs = 'BoxChar::SingleLineOuterOnly'; |
329
|
0
|
|
0
|
|
|
0
|
} else { |
330
|
|
|
|
|
|
|
$bs = 'ASCII::SingleLineOuterOnly'; |
331
|
0
|
|
|
|
|
0
|
} |
332
|
|
|
|
|
|
|
|
333
|
3
|
|
|
|
|
2233
|
$self->border_style($bs); |
334
|
|
|
|
|
|
|
} |
335
|
|
|
|
|
|
|
|
336
|
3
|
|
|
|
|
82
|
# pick a default color theme |
337
|
|
|
|
|
|
|
unless ($self->{color_theme}) { |
338
|
|
|
|
|
|
|
my $ct; |
339
|
|
|
|
|
|
|
if (defined $ENV{ANSITABLE_COLOR_THEME}) { |
340
|
3
|
50
|
|
|
|
17300
|
$ct = $ENV{ANSITABLE_COLOR_THEME}; |
341
|
3
|
|
|
|
|
5
|
} elsif ($self->use_color) { |
342
|
3
|
50
|
|
|
|
80
|
my $bg = $self->detect_terminal->{default_bgcolor} // ''; |
|
|
50
|
|
|
|
|
|
343
|
0
|
|
|
|
|
0
|
if ($self->color_depth >= 2**24) { |
344
|
|
|
|
|
|
|
$ct = 'Standard::Gradation' . |
345
|
0
|
|
0
|
|
|
0
|
($bg eq 'ffffff' ? 'WhiteBG' : ''); |
346
|
0
|
0
|
|
|
|
0
|
} else { |
347
|
0
|
0
|
|
|
|
0
|
$ct = 'Standard::NoGradation' . |
348
|
|
|
|
|
|
|
($bg eq 'ffffff' ? 'WhiteBG' : '');; |
349
|
|
|
|
|
|
|
} |
350
|
0
|
0
|
|
|
|
0
|
} else { |
351
|
|
|
|
|
|
|
$ct = 'NoColor'; |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
$self->color_theme($ct); |
354
|
3
|
|
|
|
|
2390
|
} |
355
|
|
|
|
|
|
|
|
356
|
3
|
|
|
|
|
79
|
unless (defined $self->{wide}) { |
357
|
|
|
|
|
|
|
$self->{wide} = eval { require Text::ANSI::WideUtil; 1 } ? 1:0; |
358
|
|
|
|
|
|
|
} |
359
|
3
|
50
|
|
|
|
6768
|
require Text::ANSI::Util; |
360
|
3
|
50
|
|
|
|
6
|
$self->{_func_add_color_resets} = \&Text::ANSI::Util::ta_add_color_resets; |
|
3
|
|
|
|
|
787
|
|
|
3
|
|
|
|
|
117839
|
|
361
|
|
|
|
|
|
|
if ($self->{wide}) { |
362
|
3
|
|
|
|
|
1306
|
require Text::ANSI::WideUtil; |
363
|
3
|
|
|
|
|
573
|
$self->{_func_length_height} = \&Text::ANSI::WideUtil::ta_mbswidth_height; |
364
|
3
|
50
|
|
|
|
12
|
$self->{_func_pad} = \&Text::ANSI::WideUtil::ta_mbpad; |
365
|
3
|
|
|
|
|
74
|
$self->{_func_wrap} = \&Text::ANSI::WideUtil::ta_mbwrap; |
366
|
3
|
|
|
|
|
6
|
} else { |
367
|
3
|
|
|
|
|
7
|
$self->{_func_length_height} = \&Text::ANSI::Util::ta_length_height; |
368
|
3
|
|
|
|
|
75
|
$self->{_func_pad} = \&Text::ANSI::Util::ta_pad; |
369
|
|
|
|
|
|
|
$self->{_func_wrap} = \&Text::ANSI::Util::ta_wrap; |
370
|
0
|
|
|
|
|
0
|
} |
371
|
0
|
|
|
|
|
0
|
} |
372
|
0
|
|
|
|
|
0
|
|
373
|
|
|
|
|
|
|
my ($self, $row) = @_; |
374
|
|
|
|
|
|
|
return if $self->{_columns_set}++; |
375
|
|
|
|
|
|
|
$self->columns([map {"col$_"} 0..@$row-1]) if $row; |
376
|
|
|
|
|
|
|
} |
377
|
1
|
|
|
1
|
|
2
|
|
378
|
1
|
50
|
|
|
|
3
|
my ($self, $row, $styles) = @_; |
379
|
0
|
0
|
|
|
|
0
|
croak "Row must be arrayref" unless ref($row) eq 'ARRAY'; |
|
0
|
|
|
|
|
0
|
|
380
|
|
|
|
|
|
|
push @{ $self->{rows} }, $row; |
381
|
|
|
|
|
|
|
$self->_set_default_cols($row) unless $self->{_columns_set}++; |
382
|
|
|
|
|
|
|
if ($styles) { |
383
|
7
|
|
|
7
|
1
|
833
|
my $i = @{ $self->{rows} }-1; |
384
|
7
|
100
|
|
|
|
60
|
for my $s (keys %$styles) { |
385
|
6
|
|
|
|
|
9
|
$self->set_row_style($i, $s, $styles->{$s}); |
|
6
|
|
|
|
|
11
|
|
386
|
6
|
100
|
|
|
|
18
|
} |
387
|
6
|
50
|
|
|
|
11
|
} |
388
|
0
|
|
|
|
|
0
|
$self; |
|
0
|
|
|
|
|
0
|
|
389
|
0
|
|
|
|
|
0
|
} |
390
|
0
|
|
|
|
|
0
|
|
391
|
|
|
|
|
|
|
my ($self) = @_; |
392
|
|
|
|
|
|
|
my $idx = ~~@{$self->{rows}}-1; |
393
|
6
|
|
|
|
|
11
|
# ignore duplicate separators |
394
|
|
|
|
|
|
|
push @{ $self->{_row_separators} }, $idx |
395
|
|
|
|
|
|
|
unless @{ $self->{_row_separators} } && |
396
|
|
|
|
|
|
|
$self->{_row_separators}[-1] == $idx; |
397
|
0
|
|
|
0
|
1
|
0
|
$self; |
398
|
0
|
|
|
|
|
0
|
} |
|
0
|
|
|
|
|
0
|
|
399
|
|
|
|
|
|
|
|
400
|
0
|
|
|
|
|
0
|
my ($self, $rows, $styles) = @_; |
401
|
0
|
|
|
|
|
0
|
croak "Rows must be arrayref" unless ref($rows) eq 'ARRAY'; |
402
|
0
|
0
|
0
|
|
|
0
|
$self->add_row($_, $styles) for @$rows; |
403
|
0
|
|
|
|
|
0
|
$self; |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
my $self = shift; |
407
|
2
|
|
|
2
|
1
|
45
|
my $colname = shift; |
408
|
2
|
100
|
|
|
|
13
|
|
409
|
1
|
|
|
|
|
3
|
return $colname if looks_like_number($colname); |
410
|
1
|
|
|
|
|
2
|
my $cols = $self->{columns}; |
411
|
|
|
|
|
|
|
for my $i (0..@$cols-1) { |
412
|
|
|
|
|
|
|
return $i if $cols->[$i] eq $colname; |
413
|
|
|
|
|
|
|
} |
414
|
36
|
|
|
36
|
|
43
|
croak "Unknown column name '$colname'"; |
415
|
36
|
|
|
|
|
44
|
} |
416
|
|
|
|
|
|
|
|
417
|
36
|
100
|
|
|
|
110
|
my ($self, $rownum, $col) = @_; |
418
|
10
|
|
|
|
|
16
|
|
419
|
10
|
|
|
|
|
24
|
$col = $self->_colnum($col); |
420
|
14
|
100
|
|
|
|
43
|
|
421
|
|
|
|
|
|
|
$self->{rows}[$rownum][$col]; |
422
|
1
|
|
|
|
|
69
|
} |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
my ($self, $rownum, $col, $val) = @_; |
425
|
|
|
|
|
|
|
|
426
|
6
|
|
|
6
|
1
|
1588
|
$col = $self->_colnum($col); |
427
|
|
|
|
|
|
|
|
428
|
6
|
|
|
|
|
14
|
my $oldval = $self->{rows}[$rownum][$col]; |
429
|
|
|
|
|
|
|
$self->{rows}[$rownum][$col] = $val; |
430
|
5
|
|
|
|
|
18
|
$oldval; |
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
my ($self, $col, $style) = @_; |
434
|
1
|
|
|
1
|
1
|
3
|
|
435
|
|
|
|
|
|
|
$col = $self->_colnum($col); |
436
|
1
|
|
|
|
|
3
|
$self->{_column_styles}[$col]{$style}; |
437
|
|
|
|
|
|
|
} |
438
|
1
|
|
|
|
|
4
|
|
439
|
1
|
|
|
|
|
2
|
my $self = shift; |
440
|
1
|
|
|
|
|
4
|
my $col = shift; |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
$col = $self->_colnum($col); |
443
|
|
|
|
|
|
|
|
444
|
0
|
|
|
0
|
1
|
0
|
my %sets = ref($_[0]) eq 'HASH' ? %{$_[0]} : @_; |
445
|
|
|
|
|
|
|
|
446
|
0
|
|
|
|
|
0
|
for my $style (keys %sets) { |
447
|
0
|
|
|
|
|
0
|
my $val = $sets{$style}; |
448
|
|
|
|
|
|
|
croak "Unknown per-column style '$style', please use one of [". |
449
|
|
|
|
|
|
|
join(", ", @$COLUMN_STYLES) . "]" unless $style ~~ $COLUMN_STYLES; |
450
|
|
|
|
|
|
|
$self->{_column_styles}[$col]{$style} = $val; |
451
|
0
|
|
|
0
|
1
|
0
|
} |
452
|
0
|
|
|
|
|
0
|
} |
453
|
|
|
|
|
|
|
|
454
|
0
|
|
|
|
|
0
|
my $self = shift; |
455
|
|
|
|
|
|
|
$self->{_cond_column_styles}; |
456
|
0
|
0
|
|
|
|
0
|
} |
|
0
|
|
|
|
|
0
|
|
457
|
|
|
|
|
|
|
|
458
|
0
|
|
|
|
|
0
|
#sub set_cond_column_style { |
459
|
0
|
|
|
|
|
0
|
# my ($self, $styles) = @_; |
460
|
0
|
0
|
|
|
|
0
|
# $self->{_cond_column_styles} = $styles; |
461
|
|
|
|
|
|
|
#} |
462
|
0
|
|
|
|
|
0
|
|
463
|
|
|
|
|
|
|
my $self = shift; |
464
|
|
|
|
|
|
|
my $cond = shift; |
465
|
|
|
|
|
|
|
if (ref($cond) ne 'CODE') { |
466
|
|
|
|
|
|
|
croak "cond must be a coderef"; |
467
|
0
|
|
|
0
|
1
|
0
|
} |
468
|
0
|
|
|
|
|
0
|
|
469
|
|
|
|
|
|
|
my $styles; |
470
|
|
|
|
|
|
|
if (ref($_[0]) eq 'HASH') { |
471
|
|
|
|
|
|
|
$styles = shift; |
472
|
|
|
|
|
|
|
} else { |
473
|
|
|
|
|
|
|
$styles = { @_ }; |
474
|
|
|
|
|
|
|
} |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
for my $style (keys %$styles) { |
477
|
0
|
|
|
0
|
1
|
0
|
croak "Unknown per-column style '$style', please use one of [". |
478
|
0
|
|
|
|
|
0
|
join(", ", @$COLUMN_STYLES) . "]" unless $style ~~ $COLUMN_STYLES; |
479
|
0
|
0
|
|
|
|
0
|
} |
480
|
0
|
|
|
|
|
0
|
|
481
|
|
|
|
|
|
|
push @{ $self->{_cond_column_styles} }, [$cond, $styles]; |
482
|
|
|
|
|
|
|
} |
483
|
0
|
|
|
|
|
0
|
|
484
|
0
|
0
|
|
|
|
0
|
#sub clear_cond_column_styles { |
485
|
0
|
|
|
|
|
0
|
# my $self = shift; |
486
|
|
|
|
|
|
|
# $self->{_cond_column_styles} = []; |
487
|
0
|
|
|
|
|
0
|
#} |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
my ($self, $col, $style) = @_; |
490
|
0
|
|
|
|
|
0
|
|
491
|
0
|
0
|
|
|
|
0
|
$col = $self->_colnum($col); |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
# the result of calculation is cached here |
494
|
|
|
|
|
|
|
if (defined $self->{_draw}{eff_column_styles}[$col]) { |
495
|
0
|
|
|
|
|
0
|
return $self->{_draw}{eff_column_styles}[$col]{$style}; |
|
0
|
|
|
|
|
0
|
|
496
|
|
|
|
|
|
|
} |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
my $cols = $self->{columns}; |
499
|
|
|
|
|
|
|
my %styles; |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
# apply conditional styles |
502
|
|
|
|
|
|
|
COND: |
503
|
|
|
|
|
|
|
for my $ei (0..@{ $self->{_cond_column_styles} }-1) { |
504
|
17
|
|
|
17
|
1
|
45
|
my $e = $self->{_cond_column_styles}[$ei]; |
505
|
|
|
|
|
|
|
local $_ = $col; |
506
|
17
|
|
|
|
|
32
|
my $res = $e->[0]->( |
507
|
|
|
|
|
|
|
$self, |
508
|
|
|
|
|
|
|
col => $col, |
509
|
17
|
100
|
|
|
|
36
|
colname => $cols->[$col], |
510
|
16
|
|
|
|
|
120
|
); |
511
|
|
|
|
|
|
|
next COND unless $res; |
512
|
|
|
|
|
|
|
if (ref($res) eq 'HASH') { |
513
|
1
|
|
|
|
|
2
|
$styles{$_} = $res->{$_} for keys %$res; |
514
|
1
|
|
|
|
|
1
|
} |
515
|
|
|
|
|
|
|
$styles{$_} = $e->[1]{$_} for keys %{ $e->[1] }; |
516
|
|
|
|
|
|
|
} |
517
|
|
|
|
|
|
|
|
518
|
1
|
|
|
|
|
2
|
# apply per-column styles |
|
1
|
|
|
|
|
7
|
|
519
|
0
|
|
|
|
|
0
|
my $rss = $self->{_column_styles}[$col]; |
520
|
0
|
|
|
|
|
0
|
if ($rss) { |
521
|
0
|
|
|
|
|
0
|
$styles{$_} = $rss->{$_} for keys %$rss; |
522
|
|
|
|
|
|
|
} |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
$self->{_draw}{eff_column_styles}[$col] = \%styles; |
525
|
|
|
|
|
|
|
|
526
|
0
|
0
|
|
|
|
0
|
$styles{$style}; |
527
|
0
|
0
|
|
|
|
0
|
} |
528
|
0
|
|
|
|
|
0
|
|
529
|
|
|
|
|
|
|
my ($self, $row, $style) = @_; |
530
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
531
|
|
|
|
|
|
|
$self->{_row_styles}[$row]{$style}; |
532
|
|
|
|
|
|
|
} |
533
|
|
|
|
|
|
|
|
534
|
1
|
|
|
|
|
4
|
my $self = shift; |
535
|
1
|
50
|
|
|
|
3
|
my $row = shift; |
536
|
0
|
|
|
|
|
0
|
|
537
|
|
|
|
|
|
|
my %sets = ref($_[0]) eq 'HASH' ? %{$_[0]} : @_; |
538
|
|
|
|
|
|
|
|
539
|
1
|
|
|
|
|
3
|
for my $style (keys %sets) { |
540
|
|
|
|
|
|
|
my $val = $sets{$style}; |
541
|
1
|
|
|
|
|
6
|
croak "Unknown per-row style '$style', please use one of [". |
542
|
|
|
|
|
|
|
join(", ", @$ROW_STYLES) . "]" unless $style ~~ $ROW_STYLES; |
543
|
|
|
|
|
|
|
$self->{_row_styles}[$row]{$style} = $val; |
544
|
|
|
|
|
|
|
} |
545
|
0
|
|
|
0
|
1
|
0
|
} |
546
|
|
|
|
|
|
|
|
547
|
0
|
|
|
|
|
0
|
my $self = shift; |
548
|
|
|
|
|
|
|
$self->{_cond_row_styles}; |
549
|
|
|
|
|
|
|
} |
550
|
|
|
|
|
|
|
|
551
|
0
|
|
|
0
|
1
|
0
|
#sub set_cond_row_style { |
552
|
0
|
|
|
|
|
0
|
# my ($self, $styles) = @_; |
553
|
|
|
|
|
|
|
# $self->{_cond_row_styles} = $styles; |
554
|
0
|
0
|
|
|
|
0
|
#} |
|
0
|
|
|
|
|
0
|
|
555
|
|
|
|
|
|
|
|
556
|
0
|
|
|
|
|
0
|
my $self = shift; |
557
|
0
|
|
|
|
|
0
|
my $cond = shift; |
558
|
0
|
0
|
|
|
|
0
|
if (ref($cond) ne 'CODE') { |
559
|
|
|
|
|
|
|
croak "cond must be a coderef"; |
560
|
0
|
|
|
|
|
0
|
} |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
my $styles; |
563
|
|
|
|
|
|
|
if (ref($_[0]) eq 'HASH') { |
564
|
|
|
|
|
|
|
$styles = shift; |
565
|
0
|
|
|
0
|
1
|
0
|
} else { |
566
|
0
|
|
|
|
|
0
|
$styles = { @_ }; |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
for my $style (keys %$styles) { |
570
|
|
|
|
|
|
|
croak "Unknown per-row style '$style', please use one of [". |
571
|
|
|
|
|
|
|
join(", ", @$ROW_STYLES) . "]" unless $style ~~ $ROW_STYLES; |
572
|
|
|
|
|
|
|
} |
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
push @{ $self->{_cond_row_styles} }, [$cond, $styles]; |
575
|
0
|
|
|
0
|
1
|
0
|
} |
576
|
0
|
|
|
|
|
0
|
|
577
|
0
|
0
|
|
|
|
0
|
#sub clear_cond_row_styles { |
578
|
0
|
|
|
|
|
0
|
# my $self = shift; |
579
|
|
|
|
|
|
|
# $self->{_cond_row_styles} = []; |
580
|
|
|
|
|
|
|
#} |
581
|
0
|
|
|
|
|
0
|
|
582
|
0
|
0
|
|
|
|
0
|
my ($self, $row, $style) = @_; |
583
|
0
|
|
|
|
|
0
|
|
584
|
|
|
|
|
|
|
# the result of calculation is cached here |
585
|
0
|
|
|
|
|
0
|
if (defined $self->{_draw}{eff_row_styles}[$row]) { |
586
|
|
|
|
|
|
|
return $self->{_draw}{eff_row_styles}[$row]{$style}; |
587
|
|
|
|
|
|
|
} |
588
|
0
|
|
|
|
|
0
|
|
589
|
0
|
0
|
|
|
|
0
|
my $rows = $self->{rows}; |
590
|
|
|
|
|
|
|
my %styles; |
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
# apply conditional styles |
593
|
0
|
|
|
|
|
0
|
COND: |
|
0
|
|
|
|
|
0
|
|
594
|
|
|
|
|
|
|
for my $ei (0..@{ $self->{_cond_row_styles} }-1) { |
595
|
|
|
|
|
|
|
my $e = $self->{_cond_row_styles}[$ei]; |
596
|
|
|
|
|
|
|
local $_ = $row; |
597
|
|
|
|
|
|
|
my $res = $e->[0]->( |
598
|
|
|
|
|
|
|
$self, |
599
|
|
|
|
|
|
|
row => $row, |
600
|
|
|
|
|
|
|
row_data => $rows->[$row], |
601
|
|
|
|
|
|
|
); |
602
|
20
|
|
|
20
|
1
|
39
|
next COND unless $res; |
603
|
|
|
|
|
|
|
if (ref($res) eq 'HASH') { |
604
|
|
|
|
|
|
|
$styles{$_} = $res->{$_} for keys %$res; |
605
|
20
|
100
|
|
|
|
38
|
} |
606
|
18
|
|
|
|
|
79
|
$styles{$_} = $e->[1]{$_} for keys %{ $e->[1] }; |
607
|
|
|
|
|
|
|
} |
608
|
|
|
|
|
|
|
|
609
|
2
|
|
|
|
|
4
|
# apply per-row styles |
610
|
2
|
|
|
|
|
4
|
my $rss = $self->{_row_styles}[$row]; |
611
|
|
|
|
|
|
|
if ($rss) { |
612
|
|
|
|
|
|
|
$styles{$_} = $rss->{$_} for keys %$rss; |
613
|
|
|
|
|
|
|
} |
614
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
8
|
|
615
|
0
|
|
|
|
|
0
|
$self->{_draw}{eff_row_styles}[$row] = \%styles; |
616
|
0
|
|
|
|
|
0
|
|
617
|
0
|
|
|
|
|
0
|
$styles{$style}; |
618
|
|
|
|
|
|
|
} |
619
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
my ($self, $row, $col, $style) = @_; |
621
|
|
|
|
|
|
|
|
622
|
0
|
0
|
|
|
|
0
|
$col = $self->_colnum($col); |
623
|
0
|
0
|
|
|
|
0
|
$self->{_cell_styles}[$row][$col]{$style}; |
624
|
0
|
|
|
|
|
0
|
} |
625
|
|
|
|
|
|
|
|
626
|
0
|
|
|
|
|
0
|
my $self = shift; |
|
0
|
|
|
|
|
0
|
|
627
|
|
|
|
|
|
|
my $row = shift; |
628
|
|
|
|
|
|
|
my $col = shift; |
629
|
|
|
|
|
|
|
|
630
|
2
|
|
|
|
|
6
|
$col = $self->_colnum($col); |
631
|
2
|
50
|
|
|
|
4
|
|
632
|
0
|
|
|
|
|
0
|
my %sets = ref($_[0]) eq 'HASH' ? %{$_[0]} : @_; |
633
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
for my $style (keys %sets) { |
635
|
2
|
|
|
|
|
4
|
my $val = $sets{$style}; |
636
|
|
|
|
|
|
|
croak "Unknown per-cell style '$style', please use one of [". |
637
|
2
|
|
|
|
|
11
|
join(", ", @$CELL_STYLES) . "]" unless $style ~~ $CELL_STYLES; |
638
|
|
|
|
|
|
|
$self->{_cell_styles}[$row][$col]{$style} = $val; |
639
|
|
|
|
|
|
|
} |
640
|
|
|
|
|
|
|
} |
641
|
0
|
|
|
0
|
1
|
0
|
|
642
|
|
|
|
|
|
|
my $self = shift; |
643
|
0
|
|
|
|
|
0
|
$self->{_cond_cell_styles}; |
644
|
0
|
|
|
|
|
0
|
} |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
#sub set_cond_cell_style { |
647
|
|
|
|
|
|
|
# my ($self, $styles) = @_; |
648
|
2
|
|
|
2
|
1
|
28
|
# $self->{_cond_cell_styles} = $styles; |
649
|
2
|
|
|
|
|
4
|
#} |
650
|
2
|
|
|
|
|
2
|
|
651
|
|
|
|
|
|
|
my $self = shift; |
652
|
2
|
|
|
|
|
7
|
my $cond = shift; |
653
|
|
|
|
|
|
|
if (ref($cond) ne 'CODE') { |
654
|
2
|
50
|
|
|
|
9
|
croak "cond must be a coderef"; |
|
0
|
|
|
|
|
0
|
|
655
|
|
|
|
|
|
|
} |
656
|
2
|
|
|
|
|
6
|
|
657
|
2
|
|
|
|
|
3
|
my $styles; |
658
|
2
|
50
|
|
|
|
14
|
if (ref($_[0]) eq 'HASH') { |
659
|
|
|
|
|
|
|
$styles = shift; |
660
|
2
|
|
|
|
|
8
|
} else { |
661
|
|
|
|
|
|
|
$styles = { @_ }; |
662
|
|
|
|
|
|
|
} |
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
for my $style (keys %$styles) { |
665
|
0
|
|
|
0
|
1
|
0
|
croak "Unknown per-cell style '$style', please use one of [". |
666
|
0
|
|
|
|
|
0
|
join(", ", @$CELL_STYLES) . "]" unless $style ~~ $CELL_STYLES; |
667
|
|
|
|
|
|
|
} |
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
push @{ $self->{_cond_cell_styles} }, [$cond, $styles]; |
670
|
|
|
|
|
|
|
} |
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
#sub clear_cond_cell_styles { |
673
|
|
|
|
|
|
|
# my $self = shift; |
674
|
|
|
|
|
|
|
# $self->{_cond_cell_styles} = []; |
675
|
0
|
|
|
0
|
1
|
0
|
#} |
676
|
0
|
|
|
|
|
0
|
|
677
|
0
|
0
|
|
|
|
0
|
my ($self, $row, $col, $style) = @_; |
678
|
0
|
|
|
|
|
0
|
|
679
|
|
|
|
|
|
|
# the result of calculation is cached here |
680
|
|
|
|
|
|
|
if (defined $self->{_draw}{eff_cell_styles}[$row][$col]) { |
681
|
0
|
|
|
|
|
0
|
return $self->{_draw}{eff_cell_styles}[$row][$col]{$style}; |
682
|
0
|
0
|
|
|
|
0
|
} |
683
|
0
|
|
|
|
|
0
|
|
684
|
|
|
|
|
|
|
my $rows = $self->{rows}; |
685
|
0
|
|
|
|
|
0
|
my %styles; |
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
# apply conditional styles |
688
|
0
|
|
|
|
|
0
|
COND: |
689
|
0
|
0
|
|
|
|
0
|
for my $ei (0..@{ $self->{_cond_cell_styles} }-1) { |
690
|
|
|
|
|
|
|
my $e = $self->{_cond_cell_styles}[$ei]; |
691
|
|
|
|
|
|
|
local $_ = $rows->[$row][$col]; |
692
|
|
|
|
|
|
|
my $res = $e->[0]->( |
693
|
0
|
|
|
|
|
0
|
$self, |
|
0
|
|
|
|
|
0
|
|
694
|
|
|
|
|
|
|
content => $_, |
695
|
|
|
|
|
|
|
col => $col, |
696
|
|
|
|
|
|
|
row => $row, |
697
|
|
|
|
|
|
|
row_data => $rows->[$row], |
698
|
|
|
|
|
|
|
); |
699
|
|
|
|
|
|
|
next COND unless $res; |
700
|
|
|
|
|
|
|
if (ref($res) eq 'HASH') { |
701
|
|
|
|
|
|
|
$styles{$_} = $res->{$_} for keys %$res; |
702
|
10
|
|
|
10
|
1
|
24
|
} |
703
|
|
|
|
|
|
|
$styles{$_} = $e->[1]{$_} for keys %{ $e->[1] }; |
704
|
|
|
|
|
|
|
} |
705
|
10
|
100
|
|
|
|
27
|
|
706
|
8
|
|
|
|
|
38
|
# apply per-cell styles |
707
|
|
|
|
|
|
|
my $css = $self->{_cell_styles}[$row][$col]; |
708
|
|
|
|
|
|
|
if ($css) { |
709
|
2
|
|
|
|
|
5
|
$styles{$_} = $css->{$_} for keys %$css; |
710
|
2
|
|
|
|
|
3
|
} |
711
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
$self->{_draw}{eff_cell_styles}[$row][$col] = \%styles; |
713
|
|
|
|
|
|
|
|
714
|
2
|
|
|
|
|
3
|
$styles{$style}; |
|
2
|
|
|
|
|
10
|
|
715
|
0
|
|
|
|
|
0
|
} |
716
|
0
|
|
|
|
|
0
|
|
717
|
0
|
|
|
|
|
0
|
my $self = shift; |
718
|
|
|
|
|
|
|
my $name = shift; |
719
|
|
|
|
|
|
|
$name =~ /\A[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\z/ |
720
|
|
|
|
|
|
|
or croak "Invalid style set name, please use alphanums only"; |
721
|
|
|
|
|
|
|
{ |
722
|
|
|
|
|
|
|
my $name = $name; |
723
|
|
|
|
|
|
|
$name =~ s!::!/!g; |
724
|
0
|
0
|
|
|
|
0
|
require "Text/ANSITable/StyleSet/$name.pm"; ## no critic: Modules::RequireBarewordIncludes |
725
|
0
|
0
|
|
|
|
0
|
} |
726
|
0
|
|
|
|
|
0
|
my %args = ref($_[0]) eq 'HASH' ? %{$_[0]} : @_; |
727
|
|
|
|
|
|
|
my $obj = "Text::ANSITable::StyleSet::$name"->new(%args); |
728
|
0
|
|
|
|
|
0
|
$obj->apply($self); |
|
0
|
|
|
|
|
0
|
|
729
|
|
|
|
|
|
|
} |
730
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
require Module::List; |
732
|
2
|
|
|
|
|
7
|
my ($self) = @_; |
733
|
2
|
50
|
|
|
|
5
|
|
734
|
2
|
|
|
|
|
11
|
my $mods = Module::List::list_modules( |
735
|
|
|
|
|
|
|
"BorderStyle::", {list_modules=>1, recurse=>1}); |
736
|
|
|
|
|
|
|
my @res; |
737
|
2
|
|
|
|
|
6
|
for (sort keys %$mods) { |
738
|
|
|
|
|
|
|
s/\ABorderStyle:://; |
739
|
2
|
|
|
|
|
4
|
push @res, $_; |
740
|
|
|
|
|
|
|
} |
741
|
|
|
|
|
|
|
@res; |
742
|
|
|
|
|
|
|
} |
743
|
0
|
|
|
0
|
1
|
0
|
|
744
|
0
|
|
|
|
|
0
|
require Module::List; |
745
|
0
|
0
|
|
|
|
0
|
my ($self) = @_; |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
my $mods = Module::List::list_modules( |
748
|
0
|
|
|
|
|
0
|
"ColorTheme::", {list_modules=>1, recurse=>1}); |
|
0
|
|
|
|
|
0
|
|
749
|
0
|
|
|
|
|
0
|
my @res; |
750
|
0
|
|
|
|
|
0
|
for (sort keys %$mods) { |
751
|
|
|
|
|
|
|
s/\AColorTheme:://; |
752
|
0
|
0
|
|
|
|
0
|
push @res, $_; |
|
0
|
|
|
|
|
0
|
|
753
|
0
|
|
|
|
|
0
|
} |
754
|
0
|
|
|
|
|
0
|
@res; |
755
|
|
|
|
|
|
|
} |
756
|
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
require Module::List; |
758
|
0
|
|
|
0
|
1
|
0
|
require Module::Load; |
759
|
0
|
|
|
|
|
0
|
require Package::MoreUtil; |
760
|
|
|
|
|
|
|
|
761
|
0
|
|
|
|
|
0
|
my ($self, $detail) = @_; |
762
|
|
|
|
|
|
|
|
763
|
0
|
|
|
|
|
0
|
my $prefix = (ref($self) ? ref($self) : $self ) . |
764
|
0
|
|
|
|
|
0
|
'::StyleSet'; # XXX allow override |
765
|
0
|
|
|
|
|
0
|
my $all_sets = $self->{_all_style_sets}; |
766
|
0
|
|
|
|
|
0
|
|
767
|
|
|
|
|
|
|
if (!$all_sets) { |
768
|
0
|
|
|
|
|
0
|
my $mods = Module::List::list_modules("$prefix\::", |
769
|
|
|
|
|
|
|
{list_modules=>1, recurse=>1}); |
770
|
|
|
|
|
|
|
$all_sets = {}; |
771
|
|
|
|
|
|
|
for my $mod (sort keys %$mods) { |
772
|
0
|
|
|
0
|
1
|
0
|
#$log->tracef("Loading style set module '%s' ...", $mod); |
773
|
0
|
|
|
|
|
0
|
Module::Load::load($mod); |
774
|
|
|
|
|
|
|
my $name = $mod; $name =~ s/\A\Q$prefix\:://; |
775
|
0
|
|
|
|
|
0
|
my $summary = $mod->summary; |
776
|
|
|
|
|
|
|
# we don't have meta, so dig it ourselves |
777
|
0
|
|
|
|
|
0
|
my %ct = Package::MoreUtil::list_package_contents($mod); |
778
|
0
|
|
|
|
|
0
|
my $args = [sort grep {!/\W/ && !/\A(new|summary|apply)\z/} |
779
|
0
|
|
|
|
|
0
|
keys %ct]; |
780
|
0
|
|
|
|
|
0
|
$all_sets->{$name} = {name=>$name, summary=>$summary, args=>$args}; |
781
|
|
|
|
|
|
|
} |
782
|
0
|
|
|
|
|
0
|
$self->{_all_style_sets} = $all_sets; |
783
|
|
|
|
|
|
|
} |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
if ($detail) { |
786
|
0
|
|
|
0
|
1
|
0
|
return $all_sets; |
787
|
0
|
|
|
|
|
0
|
} else { |
788
|
0
|
|
|
|
|
0
|
return (sort keys %$all_sets); |
789
|
|
|
|
|
|
|
} |
790
|
0
|
|
|
|
|
0
|
} |
791
|
|
|
|
|
|
|
|
792
|
0
|
0
|
|
|
|
0
|
# read environment variables for style, this will only be done once per object |
793
|
|
|
|
|
|
|
my $self = shift; |
794
|
0
|
|
|
|
|
0
|
|
795
|
|
|
|
|
|
|
return if $self->{_read_style_envs}++; |
796
|
0
|
0
|
|
|
|
0
|
|
797
|
0
|
|
|
|
|
0
|
if ($ENV{ANSITABLE_COLUMN_STYLES}) { |
798
|
|
|
|
|
|
|
require JSON::MaybeXS; |
799
|
0
|
|
|
|
|
0
|
my $ss = JSON::MaybeXS::decode_json($ENV{ANSITABLE_COLUMN_STYLES}); |
800
|
0
|
|
|
|
|
0
|
croak "ANSITABLE_COLUMN_STYLES must be a hash" |
801
|
|
|
|
|
|
|
unless ref($ss) eq 'HASH'; |
802
|
0
|
|
|
|
|
0
|
for my $col (keys %$ss) { |
803
|
0
|
|
|
|
|
0
|
my $ci = $self->_colnum($col); |
|
0
|
|
|
|
|
0
|
|
804
|
0
|
|
|
|
|
0
|
my $s = $ss->{$col}; |
805
|
|
|
|
|
|
|
for my $k (keys %$s) { |
806
|
0
|
|
|
|
|
0
|
my $v = $s->{$k}; |
807
|
0
|
|
0
|
|
|
0
|
croak "Unknown column style '$k' (for column $col) in ". |
|
0
|
|
|
|
|
0
|
|
808
|
|
|
|
|
|
|
"ANSITABLE_COLUMN_STYLES environment, ". |
809
|
0
|
|
|
|
|
0
|
"please use one of [".join(", ", @$COLUMN_STYLES)."]" |
810
|
|
|
|
|
|
|
unless $k ~~ $COLUMN_STYLES; |
811
|
0
|
|
|
|
|
0
|
$self->{_column_styles}[$ci]{$k} //= $v; |
812
|
|
|
|
|
|
|
} |
813
|
|
|
|
|
|
|
} |
814
|
0
|
0
|
|
|
|
0
|
} |
815
|
0
|
|
|
|
|
0
|
|
816
|
|
|
|
|
|
|
if ($ENV{ANSITABLE_ROW_STYLES}) { |
817
|
0
|
|
|
|
|
0
|
require JSON::MaybeXS; |
818
|
|
|
|
|
|
|
my $ss = JSON::MaybeXS::decode_json($ENV{ANSITABLE_ROW_STYLES}); |
819
|
|
|
|
|
|
|
croak "ANSITABLE_ROW_STYLES must be a hash" |
820
|
|
|
|
|
|
|
unless ref($ss) eq 'HASH'; |
821
|
|
|
|
|
|
|
for my $row (keys %$ss) { |
822
|
|
|
|
|
|
|
my $s = $ss->{$row}; |
823
|
1
|
|
|
1
|
|
2
|
for my $k (keys %$s) { |
824
|
|
|
|
|
|
|
my $v = $s->{$k}; |
825
|
1
|
50
|
|
|
|
5
|
croak "Unknown row style '$k' (for row $row) in ". |
826
|
|
|
|
|
|
|
"ANSITABLE_ROW_STYLES environment, ". |
827
|
1
|
50
|
|
|
|
5
|
"please use one of [".join(", ", @$ROW_STYLES)."]" |
828
|
0
|
|
|
|
|
0
|
unless $k ~~ $ROW_STYLES; |
829
|
0
|
|
|
|
|
0
|
$self->{_row_styles}[$row]{$k} //= $v; |
830
|
0
|
0
|
|
|
|
0
|
} |
831
|
|
|
|
|
|
|
} |
832
|
0
|
|
|
|
|
0
|
} |
833
|
0
|
|
|
|
|
0
|
|
834
|
0
|
|
|
|
|
0
|
if ($ENV{ANSITABLE_CELL_STYLES}) { |
835
|
0
|
|
|
|
|
0
|
require JSON::MaybeXS; |
836
|
0
|
|
|
|
|
0
|
my $ss = JSON::MaybeXS::decode_json($ENV{ANSITABLE_CELL_STYLES}); |
837
|
0
|
0
|
|
|
|
0
|
croak "ANSITABLE_CELL_STYLES must be a hash" |
838
|
|
|
|
|
|
|
unless ref($ss) eq 'HASH'; |
839
|
|
|
|
|
|
|
for my $cell (keys %$ss) { |
840
|
|
|
|
|
|
|
croak "Invalid cell specification in ANSITABLE_CELL_STYLES: ". |
841
|
0
|
|
0
|
|
|
0
|
"$cell, please use 'row,col'" |
842
|
|
|
|
|
|
|
unless $cell =~ /^(.+),(.+)$/; |
843
|
|
|
|
|
|
|
my $row = $1; |
844
|
|
|
|
|
|
|
my $col = $2; |
845
|
|
|
|
|
|
|
my $ci = $self->_colnum($col); |
846
|
1
|
50
|
|
|
|
3
|
my $s = $ss->{$cell}; |
847
|
0
|
|
|
|
|
0
|
for my $k (keys %$s) { |
848
|
0
|
|
|
|
|
0
|
my $v = $s->{$k}; |
849
|
0
|
0
|
|
|
|
0
|
croak "Unknown cell style '$k' (for cell $row,$col) in ". |
850
|
|
|
|
|
|
|
"ANSITABLE_CELL_STYLES environment, ". |
851
|
0
|
|
|
|
|
0
|
"please use one of [".join(", ", @$CELL_STYLES)."]" |
852
|
0
|
|
|
|
|
0
|
unless $k ~~ $CELL_STYLES; |
853
|
0
|
|
|
|
|
0
|
$self->{_cell_styles}[$row][$ci]{$k} //= $v; |
854
|
0
|
|
|
|
|
0
|
} |
855
|
0
|
0
|
|
|
|
0
|
} |
856
|
|
|
|
|
|
|
} |
857
|
|
|
|
|
|
|
} |
858
|
|
|
|
|
|
|
|
859
|
0
|
|
0
|
|
|
0
|
# determine which columns to show (due to column_filter) |
860
|
|
|
|
|
|
|
my $self = shift; |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
my $cols = $self->{columns}; |
863
|
|
|
|
|
|
|
my $cf = $self->{column_filter}; |
864
|
1
|
50
|
|
|
|
4
|
|
865
|
0
|
|
|
|
|
0
|
my $fcols; |
866
|
0
|
|
|
|
|
0
|
if (ref($cf) eq 'CODE') { |
867
|
0
|
0
|
|
|
|
0
|
$fcols = [grep {$cf->($_)} @$cols]; |
868
|
|
|
|
|
|
|
} elsif (ref($cf) eq 'ARRAY') { |
869
|
0
|
|
|
|
|
0
|
$fcols = [grep {defined} map {looks_like_number($_) ? |
870
|
0
|
0
|
|
|
|
0
|
$cols->[$_] : $_} @$cf]; |
871
|
|
|
|
|
|
|
} else { |
872
|
|
|
|
|
|
|
$fcols = $cols; |
873
|
0
|
|
|
|
|
0
|
} |
874
|
0
|
|
|
|
|
0
|
$self->{_draw}{fcols} = $fcols; |
875
|
0
|
|
|
|
|
0
|
} |
876
|
0
|
|
|
|
|
0
|
|
877
|
0
|
|
|
|
|
0
|
# calculate widths/heights of header, store width settings, column [lr]pads |
878
|
0
|
|
|
|
|
0
|
my $self = shift; |
879
|
0
|
0
|
|
|
|
0
|
|
880
|
|
|
|
|
|
|
my $cols = $self->{columns}; |
881
|
|
|
|
|
|
|
my $fcols = $self->{_draw}{fcols}; |
882
|
|
|
|
|
|
|
|
883
|
0
|
|
0
|
|
|
0
|
my $fcol_widths = []; # index = [colnum] |
884
|
|
|
|
|
|
|
my $header_height = 1; |
885
|
|
|
|
|
|
|
my $fcol_lpads = []; # index = [colnum] |
886
|
|
|
|
|
|
|
my $fcol_rpads = []; # ditto |
887
|
|
|
|
|
|
|
my $fcol_setwidths = []; # index = [colnum], from cell_width/col width |
888
|
|
|
|
|
|
|
my $frow_setheights = []; # index = [frownum], from cell_height/row height |
889
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
my %seen; |
891
|
1
|
|
|
1
|
|
2
|
my $lpad = $self->{cell_lpad} // $self->{cell_pad}; # tbl-lvl leftp |
892
|
|
|
|
|
|
|
my $rpad = $self->{cell_rpad} // $self->{cell_pad}; # tbl-lvl rightp |
893
|
1
|
|
|
|
|
2
|
for my $i (0..@$cols-1) { |
894
|
1
|
|
|
|
|
2
|
next unless $cols->[$i] ~~ $fcols; |
895
|
|
|
|
|
|
|
next if $seen{$cols->[$i]}++; |
896
|
1
|
|
|
|
|
2
|
|
897
|
1
|
50
|
|
|
|
4
|
$fcol_setwidths->[$i] = $self->get_eff_column_style($i, 'width') // |
|
|
50
|
|
|
|
|
|
898
|
0
|
|
|
|
|
0
|
$self->{cell_width}; |
|
0
|
|
|
|
|
0
|
|
899
|
|
|
|
|
|
|
my $wh = $self->_opt_calc_cell_width_height(undef, $i, $cols->[$i]); |
900
|
0
|
0
|
|
|
|
0
|
$fcol_widths->[$i] = $wh->[0]; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
901
|
|
|
|
|
|
|
$header_height = $wh->[1] |
902
|
|
|
|
|
|
|
if !defined($header_height) || $header_height < $wh->[1]; |
903
|
1
|
|
|
|
|
27
|
$fcol_lpads->[$i] = $self->get_eff_column_style($i, 'lpad') // |
904
|
|
|
|
|
|
|
$self->get_eff_column_style($i, 'pad') // $lpad; |
905
|
1
|
|
|
|
|
4
|
$fcol_rpads->[$i] = $self->get_eff_column_style($i, 'rpad') // |
906
|
|
|
|
|
|
|
$self->get_eff_column_style($i, 'pad') // $rpad; |
907
|
|
|
|
|
|
|
} |
908
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
$self->{_draw}{header_height} = $header_height; |
910
|
1
|
|
|
1
|
|
16
|
$self->{_draw}{fcol_lpads} = $fcol_lpads; |
911
|
|
|
|
|
|
|
$self->{_draw}{fcol_rpads} = $fcol_rpads; |
912
|
1
|
|
|
|
|
4
|
$self->{_draw}{fcol_setwidths} = $fcol_setwidths; |
913
|
1
|
|
|
|
|
2
|
$self->{_draw}{frow_setheights} = $frow_setheights; |
914
|
|
|
|
|
|
|
$self->{_draw}{fcol_widths} = $fcol_widths; |
915
|
1
|
|
|
|
|
2
|
} |
916
|
1
|
|
|
|
|
2
|
|
917
|
1
|
|
|
|
|
2
|
# determine which rows to show, calculate vertical paddings of data rows, store |
918
|
1
|
|
|
|
|
1
|
# height settings |
919
|
1
|
|
|
|
|
2
|
my $self = shift; |
920
|
1
|
|
|
|
|
2
|
|
921
|
|
|
|
|
|
|
my $rows = $self->{rows}; |
922
|
1
|
|
|
|
|
2
|
my $rf = $self->{row_filter}; |
923
|
1
|
|
33
|
|
|
7
|
my $frow_setheights = $self->{_draw}{frow_setheights}; |
924
|
1
|
|
33
|
|
|
5
|
|
925
|
1
|
|
|
|
|
8
|
my $frow_tpads = []; # index = [frownum] |
926
|
1
|
50
|
|
|
|
5
|
my $frow_bpads = []; # ditto |
927
|
1
|
50
|
|
|
|
6
|
my $frows = []; |
928
|
|
|
|
|
|
|
my $frow_separators = []; |
929
|
|
|
|
|
|
|
my $frow_orig_indices = []; # needed when accessing original row data |
930
|
1
|
|
33
|
|
|
8
|
|
931
|
1
|
|
|
|
|
9
|
my $tpad = $self->{cell_tpad} // $self->{cell_vpad}; # tbl-lvl top pad |
932
|
1
|
|
|
|
|
2
|
my $bpad = $self->{cell_bpad} // $self->{cell_vpad}; # tbl-lvl botom pad |
933
|
1
|
50
|
33
|
|
|
11
|
my $i = -1; |
934
|
|
|
|
|
|
|
my $j = -1; |
935
|
1
|
|
33
|
|
|
4
|
for my $row (@$rows) { |
|
|
|
33
|
|
|
|
|
936
|
|
|
|
|
|
|
$i++; |
937
|
1
|
|
33
|
|
|
6
|
if (ref($rf) eq 'CODE') { |
|
|
|
33
|
|
|
|
|
938
|
|
|
|
|
|
|
next unless $rf->($row, $i); |
939
|
|
|
|
|
|
|
} elsif ($rf) { |
940
|
|
|
|
|
|
|
next unless $i ~~ $rf; |
941
|
1
|
|
|
|
|
2
|
} |
942
|
1
|
|
|
|
|
2
|
$j++; |
943
|
1
|
|
|
|
|
3
|
push @$frow_setheights, $self->get_eff_row_style($i, 'height') // |
944
|
1
|
|
|
|
|
2
|
$self->{cell_height}; |
945
|
1
|
|
|
|
|
1
|
push @$frows, [@$row]; # 1-level clone, for storing formatted values |
946
|
1
|
|
|
|
|
3
|
push @$frow_separators, $j if $i ~~ $self->{_row_separators}; |
947
|
|
|
|
|
|
|
push @$frow_tpads, $self->get_eff_row_style($i, 'tpad') // |
948
|
|
|
|
|
|
|
$self->get_eff_row_style($i, 'vpad') // $tpad; |
949
|
|
|
|
|
|
|
push @$frow_bpads, $self->get_eff_row_style($i, 'bpad') // |
950
|
|
|
|
|
|
|
$self->get_eff_row_style($i, 'vpad') // $bpad; |
951
|
|
|
|
|
|
|
push @$frow_orig_indices, $i; |
952
|
1
|
|
|
1
|
|
2
|
} |
953
|
|
|
|
|
|
|
|
954
|
1
|
|
|
|
|
2
|
$self->{_draw}{frows} = $frows; |
955
|
1
|
|
|
|
|
2
|
$self->{_draw}{frow_separators} = $frow_separators; |
956
|
1
|
|
|
|
|
2
|
$self->{_draw}{frow_tpads} = $frow_tpads; |
957
|
|
|
|
|
|
|
$self->{_draw}{frow_bpads} = $frow_bpads; |
958
|
1
|
|
|
|
|
2
|
$self->{_draw}{frow_orig_indices} = $frow_orig_indices; |
959
|
1
|
|
|
|
|
2
|
} |
960
|
1
|
|
|
|
|
1
|
|
961
|
1
|
|
|
|
|
2
|
# detect column type from data/header name. assign default column align, valign, |
962
|
1
|
|
|
|
|
2
|
# fgcolor, bgcolor, formats. |
963
|
|
|
|
|
|
|
my $self = shift; |
964
|
1
|
|
33
|
|
|
5
|
|
965
|
1
|
|
33
|
|
|
8
|
my $cols = $self->{columns}; |
966
|
1
|
|
|
|
|
2
|
my $rows = $self->{rows}; |
967
|
1
|
|
|
|
|
2
|
|
968
|
1
|
|
|
|
|
3
|
my $fcol_detect = []; |
969
|
2
|
|
|
|
|
3
|
my %seen; |
970
|
2
|
50
|
|
|
|
6
|
for my $i (0..@$cols-1) { |
|
|
50
|
|
|
|
|
|
971
|
0
|
0
|
|
|
|
0
|
my $col = $cols->[$i]; |
972
|
|
|
|
|
|
|
my $res = {}; |
973
|
0
|
0
|
|
|
|
0
|
$fcol_detect->[$i] = $res; |
974
|
|
|
|
|
|
|
|
975
|
2
|
|
|
|
|
3
|
# optim: skip detecting columns we're not showing |
976
|
|
|
|
|
|
|
next unless $col ~~ $self->{_draw}{fcols}; |
977
|
2
|
|
33
|
|
|
9
|
|
978
|
2
|
|
|
|
|
5
|
# but detect from all rows, not just ones we're showing |
979
|
2
|
50
|
|
|
|
6
|
my $type = $self->get_eff_column_style($col, 'type'); |
980
|
2
|
|
33
|
|
|
4
|
my $subtype; |
|
|
|
33
|
|
|
|
|
981
|
|
|
|
|
|
|
DETECT: |
982
|
2
|
|
33
|
|
|
6
|
{ |
|
|
|
33
|
|
|
|
|
983
|
|
|
|
|
|
|
last DETECT if $type; |
984
|
2
|
|
|
|
|
5
|
if ($col =~ /^(can|is|has|does)_|\?$/) { |
985
|
|
|
|
|
|
|
$type = 'bool'; |
986
|
|
|
|
|
|
|
last DETECT; |
987
|
1
|
|
|
|
|
3
|
} |
988
|
1
|
|
|
|
|
2
|
|
989
|
1
|
|
|
|
|
2
|
require Parse::VarName; |
990
|
1
|
|
|
|
|
2
|
my @words = map {lc} @{ Parse::VarName::split_varname_words( |
991
|
1
|
|
|
|
|
2
|
varname=>$col) }; |
992
|
|
|
|
|
|
|
for (qw/date time ctime mtime utime atime stime/) { |
993
|
|
|
|
|
|
|
if ($_ ~~ @words) { |
994
|
|
|
|
|
|
|
$type = 'date'; |
995
|
|
|
|
|
|
|
last DETECT; |
996
|
|
|
|
|
|
|
} |
997
|
1
|
|
|
1
|
|
2
|
} |
998
|
|
|
|
|
|
|
|
999
|
1
|
|
|
|
|
2
|
my $pass = 1; |
1000
|
1
|
|
|
|
|
2
|
for my $j (0..@$rows) { |
1001
|
|
|
|
|
|
|
my $v = $rows->[$j][$i]; |
1002
|
1
|
|
|
|
|
2
|
next unless defined($v); |
1003
|
1
|
|
|
|
|
2
|
do { $pass=0; last } unless looks_like_number($v); |
1004
|
1
|
|
|
|
|
8
|
} |
1005
|
1
|
|
|
|
|
3
|
if ($pass) { |
1006
|
1
|
|
|
|
|
2
|
$type = 'num'; |
1007
|
1
|
|
|
|
|
2
|
if ($col =~ /(pct|percent(?:age))\b|\%/) { |
1008
|
|
|
|
|
|
|
$subtype = 'pct'; |
1009
|
|
|
|
|
|
|
} |
1010
|
1
|
50
|
|
|
|
5
|
last DETECT; |
1011
|
|
|
|
|
|
|
} |
1012
|
|
|
|
|
|
|
$type = 'str'; |
1013
|
1
|
|
|
|
|
3
|
} # DETECT |
1014
|
1
|
|
|
|
|
2
|
|
1015
|
|
|
|
|
|
|
$res->{type} = $type; |
1016
|
|
|
|
|
|
|
if ($type eq 'bool') { |
1017
|
1
|
50
|
|
|
|
2
|
$res->{align} = 'center'; |
|
1
|
|
|
|
|
2
|
|
1018
|
1
|
50
|
|
|
|
7
|
$res->{valign} = 'center'; |
1019
|
0
|
|
|
|
|
0
|
$res->{fgcolor} = $self->{color_theme_obj}->get_item_color('bool_data'); |
1020
|
0
|
|
|
|
|
0
|
$res->{formats} = [[bool => {style => $self->{use_utf8} ? |
1021
|
|
|
|
|
|
|
"check_cross" : "Y_N"}]]; |
1022
|
|
|
|
|
|
|
} elsif ($type eq 'date') { |
1023
|
1
|
|
|
|
|
374
|
$res->{align} = 'middle'; |
1024
|
1
|
|
|
|
|
336
|
$res->{fgcolor} = $self->{color_theme_obj}->get_item_color('date_data'); |
|
1
|
|
|
|
|
29
|
|
|
1
|
|
|
|
|
3
|
|
1025
|
|
|
|
|
|
|
$res->{formats} = [['date' => {}]]; |
1026
|
1
|
|
|
|
|
3
|
} elsif ($type =~ /\A(num|float|int)\z/) { |
1027
|
7
|
50
|
|
|
|
15
|
$res->{align} = 'right'; |
1028
|
0
|
|
|
|
|
0
|
$res->{fgcolor} = $self->{color_theme_obj}->get_item_color('num_data'); |
1029
|
0
|
|
|
|
|
0
|
if (($subtype//"") eq 'pct') { |
1030
|
|
|
|
|
|
|
$res->{formats} = [[num => {style=>'percent'}]]; |
1031
|
|
|
|
|
|
|
} |
1032
|
|
|
|
|
|
|
} else { |
1033
|
1
|
|
|
|
|
2
|
$res->{fgcolor} = $self->{color_theme_obj}->get_item_color('str_data'); |
1034
|
1
|
|
|
|
|
4
|
$res->{wrap} = $ENV{WRAP} // 1; |
1035
|
1
|
|
|
|
|
3
|
} |
1036
|
1
|
50
|
|
|
|
2
|
} |
1037
|
1
|
50
|
|
|
|
5
|
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
3
|
|
1038
|
|
|
|
|
|
|
#use Data::Dump; print "D:fcol_detect: "; dd $fcol_detect; |
1039
|
1
|
50
|
|
|
|
2
|
$self->{_draw}{fcol_detect} = $fcol_detect; |
1040
|
0
|
|
|
|
|
0
|
} |
1041
|
0
|
0
|
|
|
|
0
|
|
1042
|
0
|
|
|
|
|
0
|
# calculate width and height of a cell, but skip calculating (to save some |
1043
|
|
|
|
|
|
|
# cycles) if width is already set by frow_setheights / fcol_setwidths. |
1044
|
0
|
|
|
|
|
0
|
my ($self, $frownum, $col, $text) = @_; |
1045
|
|
|
|
|
|
|
|
1046
|
1
|
|
|
|
|
3
|
$col = $self->_colnum($col); |
1047
|
|
|
|
|
|
|
my $setw = $self->{_draw}{fcol_setwidths}[$col]; |
1048
|
|
|
|
|
|
|
my $calcw = !defined($setw) || $setw < 0; |
1049
|
1
|
|
|
|
|
3
|
my $seth = defined($frownum) ? |
1050
|
1
|
50
|
|
|
|
18
|
$self->{_draw}{frow_setheights}[$frownum] : undef; |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1051
|
0
|
|
|
|
|
0
|
my $calch = !defined($seth) || $seth < 0; |
1052
|
0
|
|
|
|
|
0
|
|
1053
|
0
|
|
|
|
|
0
|
my $wh; |
1054
|
|
|
|
|
|
|
if ($calcw) { |
1055
|
0
|
0
|
|
|
|
0
|
$wh = $self->{_func_length_height}->($text); |
1056
|
|
|
|
|
|
|
$wh->[0] = -$setw if defined($setw) && $setw<0 && $wh->[0] < -$setw; |
1057
|
0
|
|
|
|
|
0
|
$wh->[1] = $seth if !$calch; |
1058
|
0
|
|
|
|
|
0
|
$wh->[1] = -$seth if defined($seth) && $seth<0 && $wh->[1] < -$seth; |
1059
|
0
|
|
|
|
|
0
|
} elsif ($calch) { |
1060
|
|
|
|
|
|
|
my $h = 1; $h++ while $text =~ /\n/go; |
1061
|
0
|
|
|
|
|
0
|
$h = -$seth if defined($seth) && $seth<0 && $h < -$seth; |
1062
|
0
|
|
|
|
|
0
|
$wh = [$setw, $h]; |
1063
|
0
|
0
|
0
|
|
|
0
|
} else { |
1064
|
0
|
|
|
|
|
0
|
$wh = [$setw, $seth]; |
1065
|
|
|
|
|
|
|
} |
1066
|
|
|
|
|
|
|
#say "D:_opt_calc_cell_width_height(", $frownum//"undef", ", $col) = $wh->[0], $wh->[1]"; |
1067
|
1
|
|
|
|
|
13
|
$wh; |
1068
|
1
|
|
50
|
|
|
28
|
} |
1069
|
|
|
|
|
|
|
|
1070
|
|
|
|
|
|
|
my $self = shift; |
1071
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
my $cols = $self->{columns}; |
1073
|
1
|
|
|
|
|
3
|
my $frows = $self->{_draw}{frows}; |
1074
|
|
|
|
|
|
|
my $fcols = $self->{_draw}{fcols}; |
1075
|
|
|
|
|
|
|
my $fcol_detect = $self->{_draw}{fcol_detect}; |
1076
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
my %seen; |
1078
|
|
|
|
|
|
|
for my $i (0..@$cols-1) { |
1079
|
3
|
|
|
3
|
|
9
|
next unless $cols->[$i] ~~ $fcols; |
1080
|
|
|
|
|
|
|
next if $seen{$cols->[$i]}++; |
1081
|
3
|
|
|
|
|
6
|
my @fmts = @{ $self->get_eff_column_style($i, 'formats') // |
1082
|
3
|
|
|
|
|
7
|
$fcol_detect->[$i]{formats} // [] }; |
1083
|
3
|
|
33
|
|
|
9
|
if (@fmts) { |
1084
|
|
|
|
|
|
|
require Data::Unixish::Apply; |
1085
|
3
|
100
|
|
|
|
7
|
my $res = Data::Unixish::Apply::apply( |
1086
|
3
|
|
33
|
|
|
7
|
in => [map {$frows->[$_][$i]} 0..@$frows-1], |
1087
|
|
|
|
|
|
|
functions => \@fmts, |
1088
|
3
|
|
|
|
|
3
|
); |
1089
|
3
|
50
|
|
|
|
5
|
croak "Can't format column $cols->[$i]: $res->[0] - $res->[1]" |
|
|
0
|
|
|
|
|
|
1090
|
3
|
|
|
|
|
10
|
unless $res->[0] == 200; |
1091
|
3
|
0
|
33
|
|
|
154
|
$res = $res->[2]; |
|
|
|
33
|
|
|
|
|
1092
|
3
|
50
|
|
|
|
7
|
for (0..@$frows-1) { $frows->[$_][$i] = $res->[$_] // "" } |
1093
|
3
|
0
|
33
|
|
|
7
|
} else { |
|
|
|
33
|
|
|
|
|
1094
|
|
|
|
|
|
|
# change null to '' |
1095
|
0
|
|
|
|
|
0
|
for (0..@$frows-1) { $frows->[$_][$i] //= "" } |
|
0
|
|
|
|
|
0
|
|
1096
|
0
|
0
|
0
|
|
|
0
|
} |
|
|
|
0
|
|
|
|
|
1097
|
0
|
|
|
|
|
0
|
} |
1098
|
|
|
|
|
|
|
} |
1099
|
0
|
|
|
|
|
0
|
|
1100
|
|
|
|
|
|
|
my $self = shift; |
1101
|
|
|
|
|
|
|
|
1102
|
3
|
|
|
|
|
5
|
my $cols = $self->{columns}; |
1103
|
|
|
|
|
|
|
my $rows = $self->{rows}; |
1104
|
|
|
|
|
|
|
my $fcols = $self->{_draw}{fcols}; |
1105
|
|
|
|
|
|
|
my $frows = $self->{_draw}{frows}; |
1106
|
1
|
|
|
1
|
|
2
|
my $frow_orig_indices = $self->{_draw}{frow_orig_indices}; |
1107
|
|
|
|
|
|
|
|
1108
|
1
|
|
|
|
|
2
|
for my $i (0..@$frows-1) { |
1109
|
1
|
|
|
|
|
3
|
my %seen; |
1110
|
1
|
|
|
|
|
2
|
my $origi = $frow_orig_indices->[$i]; |
1111
|
1
|
|
|
|
|
2
|
for my $j (0..@$cols-1) { |
1112
|
|
|
|
|
|
|
next unless $cols->[$j] ~~ $fcols; |
1113
|
1
|
|
|
|
|
2
|
next if $seen{$cols->[$j]}++; |
1114
|
1
|
|
|
|
|
7
|
|
1115
|
1
|
50
|
|
|
|
7
|
my $fmts = $self->get_eff_cell_style($origi, $j, 'formats'); |
1116
|
1
|
50
|
|
|
|
4
|
if (defined $fmts) { |
1117
|
1
|
|
|
|
|
2
|
require Data::Unixish::Apply; |
1118
|
1
|
|
33
|
|
|
3
|
my $res = Data::Unixish::Apply::apply( |
|
|
|
50
|
|
|
|
|
1119
|
1
|
50
|
|
|
|
3
|
in => [ $frows->[$i][$j] ], |
1120
|
0
|
|
|
|
|
0
|
functions => $fmts, |
1121
|
|
|
|
|
|
|
); |
1122
|
0
|
|
|
|
|
0
|
croak "Can't format cell ($origi, $cols->[$j]): ". |
|
0
|
|
|
|
|
0
|
|
1123
|
|
|
|
|
|
|
"$res->[0] - $res->[1]" unless $res->[0] == 200; |
1124
|
|
|
|
|
|
|
$frows->[$i][$j] = $res->[2][0] // ""; |
1125
|
0
|
0
|
|
|
|
0
|
} |
1126
|
|
|
|
|
|
|
} # col |
1127
|
0
|
|
|
|
|
0
|
} |
1128
|
0
|
|
0
|
|
|
0
|
} |
|
0
|
|
|
|
|
0
|
|
1129
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
my $self = shift; |
1131
|
1
|
|
50
|
|
|
7
|
|
|
2
|
|
|
|
|
8
|
|
1132
|
|
|
|
|
|
|
my $cols = $self->{columns}; |
1133
|
|
|
|
|
|
|
my $fcols = $self->{_draw}{fcols}; |
1134
|
|
|
|
|
|
|
my $frows = $self->{_draw}{frows}; |
1135
|
|
|
|
|
|
|
|
1136
|
|
|
|
|
|
|
my $frow_heights = []; |
1137
|
1
|
|
|
1
|
|
3
|
my $fcol_widths = $self->{_draw}{fcol_widths}; |
1138
|
|
|
|
|
|
|
my $frow_orig_indices = $self->{_draw}{frow_orig_indices}; |
1139
|
1
|
|
|
|
|
2
|
|
1140
|
1
|
|
|
|
|
2
|
my $height = $self->{cell_height}; |
1141
|
1
|
|
|
|
|
2
|
my $tpad = $self->{cell_tpad} // $self->{cell_vpad}; # tbl-lvl tpad |
1142
|
1
|
|
|
|
|
2
|
my $bpad = $self->{cell_bpad} // $self->{cell_vpad}; # tbl-lvl bpad |
1143
|
1
|
|
|
|
|
2
|
my $cswidths = [map {$self->get_eff_column_style($_, 'width')} 0..@$cols-1]; |
1144
|
|
|
|
|
|
|
for my $i (0..@$frows-1) { |
1145
|
1
|
|
|
|
|
3
|
my %seen; |
1146
|
2
|
|
|
|
|
4
|
my $origi = $frow_orig_indices->[$i]; |
1147
|
2
|
|
|
|
|
5
|
my $rsheight = $self->get_eff_row_style($origi, 'height'); |
1148
|
2
|
|
|
|
|
5
|
for my $j (0..@$cols-1) { |
1149
|
2
|
50
|
|
|
|
8
|
next unless $cols->[$j] ~~ $fcols; |
1150
|
2
|
50
|
|
|
|
8
|
next if $seen{$cols->[$j]}++; |
1151
|
|
|
|
|
|
|
|
1152
|
2
|
|
|
|
|
13
|
my $wh = $self->_opt_calc_cell_width_height($i,$j,$frows->[$i][$j]); |
1153
|
2
|
50
|
|
|
|
5
|
|
1154
|
2
|
|
|
|
|
11
|
$fcol_widths->[$j] = $wh->[0] if $fcol_widths->[$j] < $wh->[0]; |
1155
|
2
|
|
|
|
|
10
|
$frow_heights->[$i] = $wh->[1] if !defined($frow_heights->[$i]) |
1156
|
|
|
|
|
|
|
|| $frow_heights->[$i] < $wh->[1]; |
1157
|
|
|
|
|
|
|
} # col |
1158
|
|
|
|
|
|
|
} |
1159
|
2
|
50
|
|
|
|
23381
|
$self->{_draw}{frow_heights} = $frow_heights; |
1160
|
|
|
|
|
|
|
} |
1161
|
2
|
|
50
|
|
|
20
|
|
1162
|
|
|
|
|
|
|
my $self = shift; |
1163
|
|
|
|
|
|
|
|
1164
|
|
|
|
|
|
|
my $cols = $self->{columns}; |
1165
|
|
|
|
|
|
|
my $fcols = $self->{_draw}{fcols}; |
1166
|
|
|
|
|
|
|
my $frows = $self->{_draw}{frows}; |
1167
|
|
|
|
|
|
|
my $fcol_detect = $self->{_draw}{fcol_detect}; |
1168
|
1
|
|
|
1
|
|
2
|
my $fcol_setwidths = $self->{_draw}{fcol_setwidths}; |
1169
|
|
|
|
|
|
|
|
1170
|
1
|
|
|
|
|
4
|
my %seen; |
1171
|
1
|
|
|
|
|
2
|
for my $i (0..@$cols-1) { |
1172
|
1
|
|
|
|
|
2
|
next unless $cols->[$i] ~~ $fcols; |
1173
|
|
|
|
|
|
|
next if $seen{$cols->[$i]}++; |
1174
|
1
|
|
|
|
|
3
|
|
1175
|
1
|
|
|
|
|
2
|
if (($self->get_eff_column_style($i, 'wrap') // $self->{column_wrap} // |
1176
|
1
|
|
|
|
|
3
|
$fcol_detect->[$i]{wrap}) && |
1177
|
|
|
|
|
|
|
defined($fcol_setwidths->[$i]) && |
1178
|
1
|
|
|
|
|
2
|
$fcol_setwidths->[$i]>0) { |
1179
|
1
|
|
33
|
|
|
11
|
for (0..@$frows-1) { |
1180
|
1
|
|
33
|
|
|
7
|
$frows->[$_][$i] = $self->{_func_wrap}->( |
1181
|
1
|
|
|
|
|
5
|
$frows->[$_][$i], $fcol_setwidths->[$i]); |
|
1
|
|
|
|
|
3
|
|
1182
|
1
|
|
|
|
|
6
|
} |
1183
|
2
|
|
|
|
|
4
|
} |
1184
|
2
|
|
|
|
|
4
|
} |
1185
|
2
|
|
|
|
|
6
|
} |
1186
|
2
|
|
|
|
|
5
|
|
1187
|
2
|
50
|
|
|
|
7
|
my $self = shift; |
1188
|
2
|
50
|
|
|
|
8
|
|
1189
|
|
|
|
|
|
|
my $cols = $self->{columns}; |
1190
|
2
|
|
|
|
|
6
|
my $fcols = $self->{_draw}{fcols}; |
1191
|
|
|
|
|
|
|
my $frows = $self->{_draw}{frows}; |
1192
|
2
|
50
|
|
|
|
7
|
my $fcol_widths = $self->{_draw}{fcol_widths}; |
1193
|
2
|
50
|
33
|
|
|
12
|
my $fcol_lpads = $self->{_draw}{fcol_lpads}; |
1194
|
|
|
|
|
|
|
my $fcol_rpads = $self->{_draw}{fcol_rpads}; |
1195
|
|
|
|
|
|
|
my $frow_tpads = $self->{_draw}{frow_tpads}; |
1196
|
|
|
|
|
|
|
my $frow_bpads = $self->{_draw}{frow_bpads}; |
1197
|
1
|
|
|
|
|
3
|
my $frow_heights = $self->{_draw}{frow_heights}; |
1198
|
|
|
|
|
|
|
|
1199
|
|
|
|
|
|
|
my $w = 0; |
1200
|
|
|
|
|
|
|
$w += 1 if length($self->{border_style_obj}->get_border_char(char=>'v_l')); |
1201
|
1
|
|
|
1
|
|
3
|
my $has_vsep = length($self->{border_style_obj}->get_border_char(char=>'v_i')); |
1202
|
|
|
|
|
|
|
for my $i (0..@$cols-1) { |
1203
|
1
|
|
|
|
|
3
|
next unless $cols->[$i] ~~ $fcols; |
1204
|
1
|
|
|
|
|
3
|
$w += $fcol_lpads->[$i] + $fcol_widths->[$i] + $fcol_rpads->[$i]; |
1205
|
1
|
|
|
|
|
2
|
if ($i < @$cols-1) { |
1206
|
1
|
|
|
|
|
4
|
$w += 1 if $has_vsep; |
1207
|
1
|
|
|
|
|
3
|
} |
1208
|
|
|
|
|
|
|
} |
1209
|
1
|
|
|
|
|
2
|
$w += 1 if length($self->{border_style_obj}->get_border_char(char=>'v_r')); |
1210
|
1
|
|
|
|
|
8
|
$self->{_draw}{table_width} = $w; |
1211
|
1
|
50
|
|
|
|
7
|
|
1212
|
1
|
50
|
|
|
|
5
|
my $h = 0; |
1213
|
|
|
|
|
|
|
$h += 1 if length($self->{border_style_obj}->get_border_char(char=>'rd_t')); # top border line |
1214
|
1
|
50
|
33
|
|
|
5
|
$h += $self->{header_tpad} // $self->{header_vpad} // |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
1215
|
|
|
|
|
|
|
$self->{cell_tpad} // $self->{cell_vpad}; |
1216
|
|
|
|
|
|
|
$h += $self->{_draw}{header_height} // 0; |
1217
|
|
|
|
|
|
|
$h += $self->{header_bpad} // $self->{header_vpad} // |
1218
|
0
|
|
|
|
|
0
|
$self->{cell_bpad} // $self->{cell_vpad}; |
1219
|
0
|
|
|
|
|
0
|
$h += 1 if length($self->{border_style_obj}->get_border_char(char=>'rv_l')); |
1220
|
|
|
|
|
|
|
for my $i (0..@$frows-1) { |
1221
|
|
|
|
|
|
|
$h += ($frow_tpads->[$i] // 0) + |
1222
|
|
|
|
|
|
|
($frow_heights->[$i] // 0) + |
1223
|
|
|
|
|
|
|
($frow_bpads->[$i] // 0); |
1224
|
|
|
|
|
|
|
$h += 1 if $self->_should_draw_row_separator($i); |
1225
|
|
|
|
|
|
|
} |
1226
|
|
|
|
|
|
|
$h += 1 if length($self->{border_style_obj}->get_border_char(char=>'ru_b')); |
1227
|
1
|
|
|
1
|
|
3
|
$self->{_draw}{table_height} = $h; |
1228
|
|
|
|
|
|
|
} |
1229
|
1
|
|
|
|
|
4
|
|
1230
|
1
|
|
|
|
|
2
|
# if there are text columns with no width set, and the column width is wider |
1231
|
1
|
|
|
|
|
2
|
# than terminal, try to adjust widths so it fit into the terminal, if possible. |
1232
|
1
|
|
|
|
|
2
|
# return 1 if widths (fcol_widths) adjusted. |
1233
|
1
|
|
|
|
|
2
|
my $self = shift; |
1234
|
1
|
|
|
|
|
2
|
|
1235
|
1
|
|
|
|
|
3
|
# try to find wrappable columns that do not have their widths set. currently |
1236
|
1
|
|
|
|
|
3
|
# the algorithm is not proper, it just targets columns which are wider than |
1237
|
1
|
|
|
|
|
2
|
# a hard-coded value (30). it should take into account the longest word in |
1238
|
|
|
|
|
|
|
# the content/header, but this will require another pass at the text to |
1239
|
1
|
|
|
|
|
2
|
# analyze it. |
1240
|
1
|
50
|
|
|
|
31
|
|
1241
|
1
|
|
|
|
|
176
|
my $fcols = $self->{_draw}{fcols}; |
1242
|
1
|
|
|
|
|
82
|
my $frows = $self->{_draw}{frows}; |
1243
|
1
|
50
|
|
|
|
7
|
my $fcol_setwidths = $self->{_draw}{fcol_setwidths}; |
1244
|
1
|
|
|
|
|
10
|
my $fcol_detect = $self->{_draw}{fcol_detect}; |
1245
|
1
|
50
|
|
|
|
6
|
my $fcol_widths = $self->{_draw}{fcol_widths}; |
1246
|
0
|
0
|
|
|
|
0
|
my %acols; |
1247
|
|
|
|
|
|
|
my %origw; |
1248
|
|
|
|
|
|
|
for my $i (0..@$fcols-1) { |
1249
|
1
|
50
|
|
|
|
22
|
my $ci = $self->_colnum($fcols->[$i]); |
1250
|
1
|
|
|
|
|
59
|
next if defined($fcol_setwidths->[$ci]) && $fcol_setwidths->[$ci]>0; |
1251
|
|
|
|
|
|
|
next if $fcol_widths->[$ci] < 30; |
1252
|
1
|
|
|
|
|
3
|
next unless $self->get_eff_column_style($ci, 'wrap') // |
1253
|
1
|
50
|
|
|
|
17
|
$self->{column_wrap} // $fcol_detect->[$ci]{wrap}; |
1254
|
|
|
|
|
|
|
$acols{$ci}++; |
1255
|
1
|
|
33
|
|
|
80
|
$origw{$ci} = $fcol_widths->[$ci]; |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
1256
|
1
|
|
50
|
|
|
5
|
} |
1257
|
|
|
|
|
|
|
return 0 unless %acols; |
1258
|
1
|
|
33
|
|
|
15
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
1259
|
1
|
50
|
|
|
|
22
|
# only do this if table width exceeds terminal width |
1260
|
1
|
|
|
|
|
59
|
my $termw = $self->term_width; |
1261
|
2
|
|
50
|
|
|
19
|
return 0 unless $termw > 0; |
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
1262
|
|
|
|
|
|
|
my $excess = $self->{_draw}{table_width} - $termw; |
1263
|
|
|
|
|
|
|
return 0 unless $excess > 0; |
1264
|
2
|
50
|
|
|
|
12
|
|
1265
|
|
|
|
|
|
|
# reduce text columns proportionally |
1266
|
1
|
50
|
|
|
|
23
|
my $w = 0; # total width of all to-be-adjusted columns |
1267
|
1
|
|
|
|
|
65
|
$w += $fcol_widths->[$_] for keys %acols; |
1268
|
|
|
|
|
|
|
return 0 unless $w > 0; |
1269
|
|
|
|
|
|
|
my $reduced = 0; |
1270
|
|
|
|
|
|
|
REDUCE: |
1271
|
|
|
|
|
|
|
while (1) { |
1272
|
|
|
|
|
|
|
my $has_reduced; |
1273
|
|
|
|
|
|
|
for my $ci (keys %acols) { |
1274
|
1
|
|
|
1
|
|
4
|
last REDUCE if $reduced >= $excess; |
1275
|
|
|
|
|
|
|
if ($fcol_widths->[$ci] > 30) { |
1276
|
|
|
|
|
|
|
$fcol_widths->[$ci]--; |
1277
|
|
|
|
|
|
|
$reduced++; |
1278
|
|
|
|
|
|
|
$has_reduced++; |
1279
|
|
|
|
|
|
|
} |
1280
|
|
|
|
|
|
|
} |
1281
|
|
|
|
|
|
|
last if !$has_reduced; |
1282
|
1
|
|
|
|
|
2
|
} |
1283
|
1
|
|
|
|
|
3
|
|
1284
|
1
|
|
|
|
|
2
|
# reset widths |
1285
|
1
|
|
|
|
|
52
|
for my $ci (keys %acols) { |
1286
|
1
|
|
|
|
|
4
|
$fcol_setwidths->[$ci] = $fcol_widths->[$ci]; |
1287
|
1
|
|
|
|
|
2
|
$fcol_widths->[$ci] = 0; # reset |
1288
|
|
|
|
|
|
|
} |
1289
|
1
|
|
|
|
|
5
|
|
1290
|
1
|
|
|
|
|
4
|
# wrap and set setwidths so it doesn't grow again during recalculate |
1291
|
1
|
50
|
33
|
|
|
38
|
for my $ci (keys %acols) { |
1292
|
1
|
50
|
|
|
|
8
|
next unless $origw{$ci} != $fcol_widths->[$ci]; |
1293
|
|
|
|
|
|
|
for (0..@$frows-1) { |
1294
|
0
|
0
|
0
|
|
|
0
|
$frows->[$_][$ci] = $self->{_func_wrap}->( |
|
|
|
0
|
|
|
|
|
1295
|
0
|
|
|
|
|
0
|
$frows->[$_][$ci], $fcol_setwidths->[$ci]); |
1296
|
0
|
|
|
|
|
0
|
} |
1297
|
|
|
|
|
|
|
} |
1298
|
1
|
50
|
|
|
|
4
|
|
1299
|
|
|
|
|
|
|
# recalculate column widths |
1300
|
|
|
|
|
|
|
$self->_calc_row_widths_heights; |
1301
|
0
|
|
|
|
|
0
|
$self->_calc_table_width_height; |
1302
|
0
|
0
|
|
|
|
0
|
1; |
1303
|
0
|
|
|
|
|
0
|
} |
1304
|
0
|
0
|
|
|
|
0
|
|
1305
|
|
|
|
|
|
|
# filter columns & rows, calculate widths/paddings, format data, put the results |
1306
|
|
|
|
|
|
|
# in _draw (draw data) attribute. |
1307
|
0
|
|
|
|
|
0
|
my $self = shift; |
1308
|
0
|
|
|
|
|
0
|
|
1309
|
0
|
0
|
|
|
|
0
|
$self->{_draw} = {}; |
1310
|
0
|
|
|
|
|
0
|
|
1311
|
|
|
|
|
|
|
$self->_read_style_envs; |
1312
|
0
|
|
|
|
|
0
|
$self->_calc_fcols; |
1313
|
0
|
|
|
|
|
0
|
$self->_calc_header_height; |
1314
|
0
|
|
|
|
|
0
|
$self->_calc_frows; |
1315
|
0
|
0
|
|
|
|
0
|
$self->_detect_column_types; |
1316
|
0
|
0
|
|
|
|
0
|
$self->_apply_column_formats; |
1317
|
0
|
|
|
|
|
0
|
$self->_apply_cell_formats; |
1318
|
0
|
|
|
|
|
0
|
$self->_wrap_wrappable_columns; |
1319
|
0
|
|
|
|
|
0
|
$self->_calc_row_widths_heights; |
1320
|
|
|
|
|
|
|
$self->_calc_table_width_height; |
1321
|
|
|
|
|
|
|
$self->_adjust_column_widths; |
1322
|
0
|
0
|
|
|
|
0
|
} |
1323
|
|
|
|
|
|
|
|
1324
|
|
|
|
|
|
|
# push string into the drawing buffer. also updates "cursor" position. |
1325
|
|
|
|
|
|
|
my $self = shift; |
1326
|
0
|
|
|
|
|
0
|
# currently x position is not recorded because this involves doing |
1327
|
0
|
|
|
|
|
0
|
# ta_mbswidth() (or ta_mbswidth_height()) for every string, which is rather |
1328
|
0
|
|
|
|
|
0
|
# expensive. so only the y position is recorded by counting newlines. |
1329
|
|
|
|
|
|
|
|
1330
|
|
|
|
|
|
|
for (@_) { |
1331
|
|
|
|
|
|
|
my $num_nl = 0; |
1332
|
0
|
|
|
|
|
0
|
$num_nl++ while /\r?\n/og; |
1333
|
0
|
0
|
|
|
|
0
|
push @{$self->{_draw}{buf}}, $_; |
1334
|
0
|
|
|
|
|
0
|
$self->{_draw}{y} += $num_nl; |
1335
|
0
|
|
|
|
|
0
|
} |
1336
|
|
|
|
|
|
|
$self; |
1337
|
|
|
|
|
|
|
} |
1338
|
|
|
|
|
|
|
|
1339
|
|
|
|
|
|
|
my $self = shift; |
1340
|
|
|
|
|
|
|
my $c = $self->_color_theme_item_color_to_ansi(@_); |
1341
|
0
|
|
|
|
|
0
|
$self->draw_str($c) if length($c); |
1342
|
0
|
|
|
|
|
0
|
} |
1343
|
0
|
|
|
|
|
0
|
|
1344
|
|
|
|
|
|
|
my $self = shift; |
1345
|
|
|
|
|
|
|
return "" unless $self->use_color; |
1346
|
|
|
|
|
|
|
return "" if $self->{color_theme_obj}->get_struct->{_no_color}; |
1347
|
|
|
|
|
|
|
"\e[0m"; |
1348
|
|
|
|
|
|
|
} |
1349
|
1
|
|
|
1
|
|
3
|
|
1350
|
|
|
|
|
|
|
my $self = shift; |
1351
|
1
|
|
|
|
|
3
|
my $c = $self->get_color_reset; |
1352
|
|
|
|
|
|
|
$self->draw_str($c) if length($c); |
1353
|
1
|
|
|
|
|
4
|
} |
1354
|
1
|
|
|
|
|
3
|
|
1355
|
1
|
|
|
|
|
3
|
# draw border character(s). drawing border character involves setting border |
1356
|
1
|
|
|
|
|
4
|
# color, aside from drawing the actual characters themselves. arguments are list |
1357
|
1
|
|
|
|
|
3
|
# of (y, x, n) tuples where y and x are the row and col number of border |
1358
|
1
|
|
|
|
|
5
|
# character, n is the number of characters to print. n defaults to 1 if not |
1359
|
1
|
|
|
|
|
7
|
# specified. |
1360
|
1
|
|
|
|
|
11
|
my $self = shift; |
1361
|
1
|
|
|
|
|
5
|
my $args; $args = shift if ref($_[0]) eq 'HASH'; |
1362
|
1
|
|
|
|
|
10
|
|
1363
|
1
|
|
|
|
|
8
|
while (my ($name, $n) = splice @_, 0, 2) { |
1364
|
|
|
|
|
|
|
$n //= 1; |
1365
|
|
|
|
|
|
|
if (!$self->{use_color}) { |
1366
|
|
|
|
|
|
|
# save some CPU cycles |
1367
|
|
|
|
|
|
|
} elsif ($args) { |
1368
|
24
|
|
|
24
|
0
|
839
|
$self->draw_theme_color('border', |
1369
|
|
|
|
|
|
|
{table=>$self, border=>[$name, $n], %$args}); |
1370
|
|
|
|
|
|
|
} else { |
1371
|
|
|
|
|
|
|
$self->draw_theme_color('border', |
1372
|
|
|
|
|
|
|
{table=>$self, border=>[$name, $n]}); |
1373
|
24
|
|
|
|
|
40
|
} |
1374
|
24
|
|
|
|
|
26
|
$self->draw_str($self->{border_style_obj}->get_border_char(char=>$name, repeat=>$n)); |
1375
|
24
|
|
|
|
|
76
|
$self->draw_color_reset; |
1376
|
24
|
|
|
|
|
27
|
} |
|
24
|
|
|
|
|
55
|
|
1377
|
24
|
|
|
|
|
37
|
} |
1378
|
|
|
|
|
|
|
|
1379
|
24
|
|
|
|
|
32
|
my ($self, $i) = @_; |
1380
|
|
|
|
|
|
|
|
1381
|
|
|
|
|
|
|
return $i < @{$self->{_draw}{frows}}-1 && |
1382
|
|
|
|
|
|
|
(($self->{show_row_separator}==2 && $i~~$self->{_draw}{frow_separators}) |
1383
|
0
|
|
|
0
|
0
|
0
|
|| $self->{show_row_separator}==1); |
1384
|
0
|
|
|
|
|
0
|
} |
1385
|
0
|
0
|
|
|
|
0
|
|
1386
|
|
|
|
|
|
|
# apply align/valign, apply padding, apply default fgcolor/bgcolor to text, |
1387
|
|
|
|
|
|
|
# truncate to specified cell's width & height |
1388
|
|
|
|
|
|
|
my $self = shift; |
1389
|
18
|
|
|
18
|
0
|
20
|
#say "D: get_cell_lines ".join(", ", map{$_//""} @_); |
1390
|
18
|
50
|
|
|
|
276
|
my ($text, $width, $height, $align, $valign, |
1391
|
0
|
0
|
|
|
|
0
|
$lpad, $rpad, $tpad, $bpad, $color) = @_; |
1392
|
0
|
|
|
|
|
0
|
|
1393
|
|
|
|
|
|
|
my @lines; |
1394
|
|
|
|
|
|
|
push @lines, "" for 1..$tpad; |
1395
|
|
|
|
|
|
|
my @dlines = split(/\r?\n/, $text); |
1396
|
18
|
|
|
18
|
0
|
20
|
@dlines = ("") unless @dlines; |
1397
|
18
|
|
|
|
|
34
|
my ($la, $lb); |
1398
|
18
|
50
|
|
|
|
137
|
$valign //= 'top'; |
1399
|
|
|
|
|
|
|
if ($valign =~ /^[Bb]/o) { # bottom |
1400
|
|
|
|
|
|
|
$la = $height-@dlines; |
1401
|
|
|
|
|
|
|
$lb = 0; |
1402
|
|
|
|
|
|
|
} elsif ($valign =~ /^[MmCc]/o) { # middle/center |
1403
|
|
|
|
|
|
|
$la = int(($height-@dlines)/2); |
1404
|
|
|
|
|
|
|
$lb = $height-@dlines-$la; |
1405
|
|
|
|
|
|
|
} else { # top |
1406
|
|
|
|
|
|
|
$la = 0; |
1407
|
9
|
|
|
9
|
0
|
13
|
$lb = $height-@dlines; |
1408
|
9
|
100
|
|
|
|
9
|
} |
|
9
|
|
|
|
|
21
|
|
1409
|
|
|
|
|
|
|
push @lines, "" for 1..$la; |
1410
|
9
|
|
|
|
|
38
|
push @lines, @dlines; |
1411
|
15
|
|
100
|
|
|
40
|
push @lines, "" for 1..$lb; |
1412
|
15
|
50
|
|
|
|
31
|
push @lines, "" for 1..$bpad; |
|
|
0
|
|
|
|
|
|
1413
|
|
|
|
|
|
|
|
1414
|
|
|
|
|
|
|
$align //= 'left'; |
1415
|
0
|
|
|
|
|
0
|
my $pad = $align =~ /^[Ll]/o ? "right" : |
1416
|
|
|
|
|
|
|
($align =~ /^[Rr]/o ? "left" : "center"); |
1417
|
|
|
|
|
|
|
|
1418
|
0
|
|
|
|
|
0
|
for (@lines) { |
1419
|
|
|
|
|
|
|
$_ = (" "x$lpad) . $self->{_func_pad}->($_, $width, $pad, " ", 1) . (" "x$rpad); |
1420
|
|
|
|
|
|
|
if ($self->{use_color}) { |
1421
|
15
|
|
|
|
|
286
|
# add default color |
1422
|
15
|
|
|
|
|
26
|
s/\e\[0m(?=.)/\e[0m$color/g if length($color); |
1423
|
|
|
|
|
|
|
$_ = $color . $_; |
1424
|
|
|
|
|
|
|
} |
1425
|
|
|
|
|
|
|
} |
1426
|
|
|
|
|
|
|
|
1427
|
4
|
|
|
4
|
|
10
|
\@lines; |
1428
|
|
|
|
|
|
|
} |
1429
|
|
|
|
|
|
|
|
1430
|
|
|
|
|
|
|
my ($self, $i) = @_; |
1431
|
4
|
|
66
|
|
|
5
|
|
1432
|
|
|
|
|
|
|
my $ct = $self->{color_theme}; |
1433
|
|
|
|
|
|
|
|
1434
|
|
|
|
|
|
|
my $tmp; |
1435
|
|
|
|
|
|
|
my $fgcolor; |
1436
|
|
|
|
|
|
|
if (defined $self->{header_fgcolor}) { |
1437
|
3
|
|
|
3
|
|
12
|
$fgcolor = item_color_to_ansi($self->{header_fgcolor}); |
1438
|
|
|
|
|
|
|
} elsif (defined $self->{cell_fgcolor}) { |
1439
|
3
|
|
|
|
|
11
|
$fgcolor = item_color_to_ansi($self->{cell_fgcolor}); |
1440
|
|
|
|
|
|
|
#} elsif (defined $self->{_draw}{fcol_detect}[$i]{fgcolor}) { |
1441
|
|
|
|
|
|
|
# $fgcolor = item_color_to_ansi($self->{_draw}{fcol_detect}[$i]{fgcolor}); |
1442
|
3
|
|
|
|
|
4
|
} elsif ($tmp = $self->_color_theme_item_color_to_ansi('header')) { |
1443
|
3
|
|
|
|
|
8
|
$fgcolor = $tmp; |
1444
|
3
|
|
|
|
|
9
|
} elsif ($tmp = $self->_color_theme_item_color_to_ansi('cell')) { |
1445
|
3
|
50
|
|
|
|
8
|
$fgcolor = $tmp; |
1446
|
3
|
|
|
|
|
4
|
} else { |
1447
|
3
|
|
50
|
|
|
6
|
$fgcolor = ""; |
1448
|
3
|
50
|
|
|
|
22
|
} |
|
|
50
|
|
|
|
|
|
1449
|
0
|
|
|
|
|
0
|
|
1450
|
0
|
|
|
|
|
0
|
my $bgcolor; |
1451
|
|
|
|
|
|
|
if (defined $self->{header_bgcolor}) { |
1452
|
0
|
|
|
|
|
0
|
$bgcolor = item_color_to_ansi($self->{header_bgcolor}, 'bg'); |
1453
|
0
|
|
|
|
|
0
|
} elsif (defined $self->{cell_bgcolor}) { |
1454
|
|
|
|
|
|
|
$bgcolor = item_color_to_ansi($self->{cell_bgcolor}, 'bg'); |
1455
|
3
|
|
|
|
|
6
|
} elsif (defined $self->{_draw}{fcol_detect}[$i]{bgcolor}) { |
1456
|
3
|
|
|
|
|
5
|
$bgcolor = item_color_to_ansi($self->{_draw}{fcol_detect}[$i]{bgcolor}, 'bg'); |
1457
|
|
|
|
|
|
|
} elsif ($tmp = $self->_color_theme_item_color_to_ansi('header_bg', undef, 'bg')) { |
1458
|
3
|
|
|
|
|
5
|
$bgcolor = $tmp; |
1459
|
3
|
|
|
|
|
7
|
} elsif ($tmp = $self->_color_theme_item_color_to_ansi('cell_bg', undef, 'bg')) { |
1460
|
3
|
|
|
|
|
5
|
$bgcolor = $tmp; |
1461
|
3
|
|
|
|
|
5
|
} else { |
1462
|
|
|
|
|
|
|
$bgcolor = ""; |
1463
|
3
|
|
50
|
|
|
6
|
} |
1464
|
3
|
0
|
|
|
|
16
|
|
|
|
50
|
|
|
|
|
|
1465
|
|
|
|
|
|
|
my $align = |
1466
|
|
|
|
|
|
|
$self->{header_align} // |
1467
|
3
|
|
|
|
|
7
|
$self->{cell_align} // |
1468
|
3
|
|
|
|
|
13
|
$self->{_draw}{fcol_detect}[$i]{align} // |
1469
|
3
|
50
|
|
|
|
140
|
'left'; |
1470
|
|
|
|
|
|
|
my $valign = |
1471
|
0
|
0
|
|
|
|
0
|
$self->{header_valign} // |
1472
|
0
|
|
|
|
|
0
|
$self->{cell_valign} // |
1473
|
|
|
|
|
|
|
$self->{_draw}{fcol_detect}[$i]{valign} // |
1474
|
|
|
|
|
|
|
'top'; |
1475
|
|
|
|
|
|
|
|
1476
|
3
|
|
|
|
|
12
|
my $lpad = $self->{_draw}{fcol_lpads}[$i]; |
1477
|
|
|
|
|
|
|
my $rpad = $self->{_draw}{fcol_rpads}[$i]; |
1478
|
|
|
|
|
|
|
my $tpad = $self->{header_tpad} // $self->{header_vpad} // 0; |
1479
|
|
|
|
|
|
|
my $bpad = $self->{header_bpad} // $self->{header_vpad} // 0; |
1480
|
1
|
|
|
1
|
|
3
|
|
1481
|
|
|
|
|
|
|
#use Data::Dump; print "D:header cell: "; dd {i=>$i, col=>$self->{columns}[$i], fgcolor=>$fgcolor, bgcolor=>$bgcolor}; |
1482
|
1
|
|
|
|
|
3
|
my $res = $self->_get_cell_lines( |
1483
|
|
|
|
|
|
|
$self->{columns}[$i], # text |
1484
|
1
|
|
|
|
|
1
|
$self->{_draw}{fcol_widths}[$i], # width |
1485
|
|
|
|
|
|
|
$self->{_draw}{header_height}, # height |
1486
|
1
|
50
|
|
|
|
8
|
$align, $valign, # aligns |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1487
|
0
|
|
|
|
|
0
|
$lpad, $rpad, $tpad, $bpad, # paddings |
1488
|
|
|
|
|
|
|
$fgcolor . $bgcolor); |
1489
|
0
|
|
|
|
|
0
|
#use Data::Dump; print "D:res: "; dd $res; |
1490
|
|
|
|
|
|
|
$res; |
1491
|
|
|
|
|
|
|
} |
1492
|
|
|
|
|
|
|
|
1493
|
0
|
|
|
|
|
0
|
my ($self, $y, $x) = @_; |
1494
|
|
|
|
|
|
|
|
1495
|
0
|
|
|
|
|
0
|
my $ct = $self->{color_theme}; |
1496
|
|
|
|
|
|
|
my $oy = $self->{_draw}{frow_orig_indices}[$y]; |
1497
|
1
|
|
|
|
|
43
|
my $cell = $self->{_draw}{frows}[$y][$x]; |
1498
|
|
|
|
|
|
|
my $args = {table=>$self, rownum=>$y, colnum=>$x, data=>$cell, |
1499
|
|
|
|
|
|
|
orig_data=>$self->{rows}[$oy][$x]}; |
1500
|
1
|
|
|
|
|
3
|
|
1501
|
1
|
50
|
|
|
|
14
|
my $tmp; |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1502
|
0
|
|
|
|
|
0
|
my $fgcolor; |
1503
|
|
|
|
|
|
|
if (defined ($tmp = $self->get_eff_cell_style($oy, $x, 'fgcolor'))) { |
1504
|
0
|
|
|
|
|
0
|
$fgcolor = item_color_to_ansi($tmp); |
1505
|
|
|
|
|
|
|
} elsif (defined ($tmp = $self->get_eff_row_style($oy, 'fgcolor'))) { |
1506
|
0
|
|
|
|
|
0
|
$fgcolor = item_color_to_ansi($tmp); |
1507
|
|
|
|
|
|
|
} elsif (defined ($tmp = $self->get_eff_column_style($x, 'fgcolor'))) { |
1508
|
0
|
|
|
|
|
0
|
$fgcolor = item_color_to_ansi($tmp); |
1509
|
|
|
|
|
|
|
} elsif (defined ($tmp = $self->{cell_fgcolor})) { |
1510
|
0
|
|
|
|
|
0
|
$fgcolor = item_color_to_ansi($tmp); |
1511
|
|
|
|
|
|
|
} elsif (defined ($tmp = $self->{_draw}{fcol_detect}[$x]{fgcolor})) { |
1512
|
1
|
|
|
|
|
16
|
$fgcolor = item_color_to_ansi($tmp); |
1513
|
|
|
|
|
|
|
} elsif ($tmp = $self->_color_theme_item_color_to_ansi('cell', $args)) { |
1514
|
|
|
|
|
|
|
$fgcolor = $tmp; |
1515
|
|
|
|
|
|
|
} else { |
1516
|
|
|
|
|
|
|
$fgcolor = ""; |
1517
|
|
|
|
|
|
|
} |
1518
|
|
|
|
|
|
|
|
1519
|
1
|
|
33
|
|
|
15
|
my $bgcolor; |
|
|
|
33
|
|
|
|
|
|
|
|
50
|
|
|
|
|
1520
|
|
|
|
|
|
|
if (defined ($tmp = $self->get_eff_cell_style($oy, $x, 'bgcolor'))) { |
1521
|
|
|
|
|
|
|
$bgcolor = item_color_to_ansi($tmp, 'bg'); |
1522
|
|
|
|
|
|
|
} elsif (defined ($tmp = $self->get_eff_row_style($oy, 'bgcolor'))) { |
1523
|
|
|
|
|
|
|
$bgcolor = item_color_to_ansi($tmp, 'bg'); |
1524
|
1
|
|
33
|
|
|
16
|
} elsif (defined ($tmp = $self->get_eff_column_style($x, 'bgcolor'))) { |
|
|
|
33
|
|
|
|
|
|
|
|
50
|
|
|
|
|
1525
|
|
|
|
|
|
|
$bgcolor = item_color_to_ansi($tmp, 'bg'); |
1526
|
1
|
|
|
|
|
4
|
} elsif (defined ($tmp = $self->{cell_bgcolor})) { |
1527
|
1
|
|
|
|
|
2
|
$bgcolor = item_color_to_ansi($tmp, 'bg'); |
1528
|
1
|
|
33
|
|
|
8
|
} elsif (defined ($tmp = $self->{_draw}{fcol_detect}[$x]{bgcolor})) { |
|
|
|
50
|
|
|
|
|
1529
|
1
|
|
33
|
|
|
21
|
$bgcolor = item_color_to_ansi($tmp, 'bg'); |
|
|
|
50
|
|
|
|
|
1530
|
|
|
|
|
|
|
} elsif ($tmp = $self->_color_theme_item_color_to_ansi('cell_bg', $args, 'bg')) { |
1531
|
|
|
|
|
|
|
$bgcolor = $tmp; |
1532
|
|
|
|
|
|
|
} else { |
1533
|
|
|
|
|
|
|
$bgcolor = ""; |
1534
|
|
|
|
|
|
|
} |
1535
|
|
|
|
|
|
|
|
1536
|
1
|
|
|
|
|
9
|
my $align = |
1537
|
|
|
|
|
|
|
$self->get_eff_cell_style($oy, $x, 'align') // |
1538
|
|
|
|
|
|
|
$self->get_eff_row_style($oy, 'align') // |
1539
|
|
|
|
|
|
|
$self->get_eff_column_style($x, 'align') // |
1540
|
1
|
|
|
|
|
6
|
$self->{cell_align} // |
1541
|
|
|
|
|
|
|
$self->{_draw}{fcol_detect}[$x]{align} // |
1542
|
|
|
|
|
|
|
'left'; |
1543
|
|
|
|
|
|
|
my $valign = |
1544
|
2
|
|
|
2
|
|
4
|
$self->get_eff_cell_style($oy, $x, 'valign') // |
1545
|
|
|
|
|
|
|
$self->get_eff_row_style($oy, 'valign') // |
1546
|
2
|
|
|
|
|
4
|
$self->get_eff_column_style($x, 'valign') // |
1547
|
2
|
|
|
|
|
3
|
$self->{cell_valign} // |
1548
|
2
|
|
|
|
|
5
|
$self->{_draw}{fcol_detect}[$x]{valign} // |
1549
|
|
|
|
|
|
|
'top'; |
1550
|
2
|
|
|
|
|
12
|
#say "D:y=$y, x=$x, align=$align, valign=$valign"; |
1551
|
|
|
|
|
|
|
|
1552
|
2
|
|
|
|
|
3
|
my $lpad = $self->{_draw}{fcol_lpads}[$x]; |
1553
|
|
|
|
|
|
|
my $rpad = $self->{_draw}{fcol_rpads}[$x]; |
1554
|
2
|
50
|
|
|
|
5
|
my $tpad = $self->{_draw}{frow_tpads}[$y]; |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1555
|
0
|
|
|
|
|
0
|
my $bpad = $self->{_draw}{frow_bpads}[$y]; |
1556
|
|
|
|
|
|
|
|
1557
|
0
|
|
|
|
|
0
|
my $res = $self->_get_cell_lines( |
1558
|
|
|
|
|
|
|
$cell, # text |
1559
|
0
|
|
|
|
|
0
|
$self->{_draw}{fcol_widths}[$x], # width |
1560
|
|
|
|
|
|
|
$self->{_draw}{frow_heights}[$y], # height |
1561
|
0
|
|
|
|
|
0
|
$align, $valign, # aligns |
1562
|
|
|
|
|
|
|
$lpad, $rpad, $tpad, $bpad, # paddings |
1563
|
0
|
|
|
|
|
0
|
$fgcolor . $bgcolor); |
1564
|
|
|
|
|
|
|
$res; |
1565
|
0
|
|
|
|
|
0
|
} |
1566
|
|
|
|
|
|
|
|
1567
|
2
|
|
|
|
|
39
|
my ($self) = @_; |
1568
|
|
|
|
|
|
|
|
1569
|
|
|
|
|
|
|
$self->_prepare_draw; |
1570
|
2
|
|
|
|
|
4
|
|
1571
|
2
|
50
|
|
|
|
13
|
$self->{_draw}{buf} = []; # output buffer |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
1572
|
0
|
|
|
|
|
0
|
$self->{_draw}{y} = 0; # current line |
1573
|
|
|
|
|
|
|
|
1574
|
0
|
|
|
|
|
0
|
my $cols = $self->{columns}; |
1575
|
|
|
|
|
|
|
my $fcols = $self->{_draw}{fcols}; |
1576
|
0
|
|
|
|
|
0
|
my $frows = $self->{_draw}{frows}; |
1577
|
|
|
|
|
|
|
my $frow_heights = $self->{_draw}{frow_heights}; |
1578
|
0
|
|
|
|
|
0
|
my $frow_tpads = $self->{_draw}{frow_tpads}; |
1579
|
|
|
|
|
|
|
my $frow_bpads = $self->{_draw}{frow_bpads}; |
1580
|
0
|
|
|
|
|
0
|
my $fcol_lpads = $self->{_draw}{fcol_lpads}; |
1581
|
|
|
|
|
|
|
my $fcol_rpads = $self->{_draw}{fcol_rpads}; |
1582
|
0
|
|
|
|
|
0
|
my $fcol_widths = $self->{_draw}{fcol_widths}; |
1583
|
|
|
|
|
|
|
|
1584
|
2
|
|
|
|
|
35
|
# draw border top line |
1585
|
|
|
|
|
|
|
{ |
1586
|
|
|
|
|
|
|
last unless length($self->{border_style_obj}->get_border_char(char=>'rd_t')); |
1587
|
|
|
|
|
|
|
my @b; |
1588
|
|
|
|
|
|
|
push @b, 'rd_t', 1; |
1589
|
|
|
|
|
|
|
for my $i (0..@$fcols-1) { |
1590
|
|
|
|
|
|
|
my $ci = $self->_colnum($fcols->[$i]); |
1591
|
|
|
|
|
|
|
push @b, 'h_t', |
1592
|
|
|
|
|
|
|
$fcol_lpads->[$ci] + $fcol_widths->[$ci] + $fcol_rpads->[$ci]; |
1593
|
2
|
|
33
|
|
|
5
|
push @b, 'hd_t', 1 if $i < @$fcols-1; |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
50
|
|
|
|
|
1594
|
|
|
|
|
|
|
} |
1595
|
|
|
|
|
|
|
push @b, 'ld_t', 1; |
1596
|
|
|
|
|
|
|
$self->draw_border_char(@b); |
1597
|
|
|
|
|
|
|
$self->draw_str("\n"); |
1598
|
|
|
|
|
|
|
} |
1599
|
|
|
|
|
|
|
|
1600
|
2
|
|
33
|
|
|
7
|
# draw header |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
50
|
|
|
|
|
1601
|
|
|
|
|
|
|
if ($self->{show_header}) { |
1602
|
|
|
|
|
|
|
my %seen; |
1603
|
2
|
|
|
|
|
5
|
my $hcell_lines = []; # index = [fcolnum] |
1604
|
2
|
|
|
|
|
4
|
if (@$fcols) { |
1605
|
2
|
|
|
|
|
3
|
for my $i (0..@$fcols-1) { |
1606
|
2
|
|
|
|
|
4
|
my $ci = $self->_colnum($fcols->[$i]); |
1607
|
|
|
|
|
|
|
if (defined($seen{$i})) { |
1608
|
|
|
|
|
|
|
$hcell_lines->[$i] = $hcell_lines->[$seen{$i}]; |
1609
|
|
|
|
|
|
|
} |
1610
|
|
|
|
|
|
|
$seen{$i} = $ci; |
1611
|
2
|
|
|
|
|
8
|
$hcell_lines->[$i] = $self->_get_header_cell_lines($ci); |
1612
|
|
|
|
|
|
|
} |
1613
|
|
|
|
|
|
|
} else { |
1614
|
|
|
|
|
|
|
# so we can still draw header |
1615
|
2
|
|
|
|
|
10
|
$hcell_lines->[0] = [""]; |
1616
|
|
|
|
|
|
|
} |
1617
|
|
|
|
|
|
|
#use Data::Dump; print "D:hcell_lines: "; dd $hcell_lines; |
1618
|
|
|
|
|
|
|
for my $l (0..@{ $hcell_lines->[0] }-1) { |
1619
|
1
|
|
|
1
|
1
|
11
|
$self->draw_border_char('v_l'); |
1620
|
|
|
|
|
|
|
for my $i (0..@$fcols-1) { |
1621
|
1
|
|
|
|
|
10
|
$self->draw_str($hcell_lines->[$i][$l]); |
1622
|
|
|
|
|
|
|
$self->draw_color_reset; |
1623
|
1
|
|
|
|
|
4
|
$self->draw_border_char('v_i') unless $i == @$fcols-1; |
1624
|
1
|
|
|
|
|
3
|
} |
1625
|
|
|
|
|
|
|
$self->draw_border_char('v_r'); |
1626
|
1
|
|
|
|
|
3
|
$self->draw_str("\n"); |
1627
|
1
|
|
|
|
|
2
|
} |
1628
|
1
|
|
|
|
|
3
|
} |
1629
|
1
|
|
|
|
|
2
|
|
1630
|
1
|
|
|
|
|
1
|
# draw header-data row separator |
1631
|
1
|
|
|
|
|
2
|
if ($self->{show_header} && length($self->{border_style_obj}->get_border_char(char=>'rv_l'))) { |
1632
|
1
|
|
|
|
|
2
|
my @b; |
1633
|
1
|
|
|
|
|
3
|
push @b, 'rv_l', 1; |
1634
|
1
|
|
|
|
|
3
|
for my $i (0..@$fcols-1) { |
1635
|
|
|
|
|
|
|
my $ci = $self->_colnum($fcols->[$i]); |
1636
|
|
|
|
|
|
|
push @b, 'h_i', |
1637
|
|
|
|
|
|
|
$fcol_lpads->[$ci] + $fcol_widths->[$ci] + $fcol_rpads->[$ci]; |
1638
|
1
|
50
|
|
|
|
1
|
push @b, 'hv_i', 1 unless $i==@$fcols-1; |
|
1
|
|
|
|
|
23
|
|
1639
|
1
|
|
|
|
|
86
|
} |
1640
|
1
|
|
|
|
|
7
|
push @b, 'lv_r', 1; |
1641
|
1
|
|
|
|
|
5
|
$self->draw_border_char(@b); |
1642
|
1
|
|
|
|
|
4
|
$self->draw_str("\n"); |
1643
|
1
|
|
|
|
|
4
|
} |
1644
|
|
|
|
|
|
|
|
1645
|
1
|
50
|
|
|
|
4
|
# draw data rows |
1646
|
|
|
|
|
|
|
{ |
1647
|
1
|
|
|
|
|
3
|
for my $r (0..@$frows-1) { |
1648
|
1
|
|
|
|
|
6
|
#$self->draw_str("r$r"); |
1649
|
1
|
|
|
|
|
3
|
my $dcell_lines = []; # index = [fcolnum] |
1650
|
|
|
|
|
|
|
my %seen; |
1651
|
|
|
|
|
|
|
if (@$fcols) { |
1652
|
|
|
|
|
|
|
for my $i (0..@$fcols-1) { |
1653
|
1
|
50
|
|
|
|
3
|
my $ci = $self->_colnum($fcols->[$i]); |
1654
|
1
|
|
|
|
|
3
|
if (defined($seen{$i})) { |
1655
|
1
|
|
|
|
|
2
|
$dcell_lines->[$i] = $dcell_lines->[$seen{$i}]; |
1656
|
1
|
50
|
|
|
|
4
|
} |
1657
|
1
|
|
|
|
|
3
|
$seen{$i} = $ci; |
1658
|
1
|
|
|
|
|
4
|
$dcell_lines->[$i] = $self->_get_data_cell_lines($r, $ci); |
1659
|
1
|
50
|
|
|
|
4
|
} |
1660
|
0
|
|
|
|
|
0
|
} else { |
1661
|
|
|
|
|
|
|
# so we can still print row |
1662
|
1
|
|
|
|
|
4
|
$dcell_lines->[0] = [" "]; |
1663
|
1
|
|
|
|
|
4
|
} |
1664
|
|
|
|
|
|
|
#use Data::Dump; print "TMP: dcell_lines: "; dd $dcell_lines; |
1665
|
|
|
|
|
|
|
for my $l (0..@{ $dcell_lines->[0] }-1) { |
1666
|
|
|
|
|
|
|
$self->draw_border_char({rownum=>$r}, 'v_l'); |
1667
|
0
|
|
|
|
|
0
|
for my $i (0..@$fcols-1) { |
1668
|
|
|
|
|
|
|
$self->draw_str($dcell_lines->[$i][$l]); |
1669
|
|
|
|
|
|
|
$self->draw_color_reset; |
1670
|
1
|
|
|
|
|
8
|
$self->draw_border_char({rownum=>$r}, 'v_i') |
|
1
|
|
|
|
|
6
|
|
1671
|
1
|
|
|
|
|
4
|
unless $i == @$fcols-1; |
1672
|
1
|
|
|
|
|
5
|
} |
1673
|
1
|
|
|
|
|
4
|
$self->draw_border_char({rownum=>$r}, 'v_r'); |
1674
|
1
|
|
|
|
|
3
|
$self->draw_str("\n"); |
1675
|
1
|
50
|
|
|
|
4
|
} |
1676
|
|
|
|
|
|
|
|
1677
|
1
|
|
|
|
|
4
|
# draw separators between row |
1678
|
1
|
|
|
|
|
3
|
if ($self->_should_draw_row_separator($r)) { |
1679
|
|
|
|
|
|
|
my @b; |
1680
|
|
|
|
|
|
|
push @b, 'rv_l', 1; |
1681
|
|
|
|
|
|
|
for my $i (0..@$fcols-1) { |
1682
|
|
|
|
|
|
|
my $ci = $self->_colnum($fcols->[$i]); |
1683
|
1
|
50
|
33
|
|
|
31
|
push @b, 'h_i', |
1684
|
1
|
|
|
|
|
72
|
$fcol_lpads->[$ci] + $fcol_widths->[$ci] + |
1685
|
1
|
|
|
|
|
5
|
$fcol_rpads->[$ci]; |
1686
|
1
|
|
|
|
|
4
|
push @b, ($i==@$fcols-1 ? 'lv_r' : 'hv_i'), 1; |
1687
|
1
|
|
|
|
|
4
|
} |
1688
|
1
|
|
|
|
|
4
|
$self->draw_border_char({rownum=>$r}, @b); |
1689
|
|
|
|
|
|
|
$self->draw_str("\n"); |
1690
|
1
|
50
|
|
|
|
5
|
} |
1691
|
|
|
|
|
|
|
} # for frow |
1692
|
1
|
|
|
|
|
7
|
} |
1693
|
1
|
|
|
|
|
6
|
|
1694
|
1
|
|
|
|
|
3
|
# draw border bottom line |
1695
|
|
|
|
|
|
|
{ |
1696
|
|
|
|
|
|
|
last unless length($self->{border_style_obj}->get_border_char(char=>'ru_b')); |
1697
|
|
|
|
|
|
|
my @b; |
1698
|
|
|
|
|
|
|
push @b, 'ru_b', 1; |
1699
|
1
|
|
|
|
|
12
|
for my $i (0..@$fcols-1) { |
1700
|
|
|
|
|
|
|
my $ci = $self->_colnum($fcols->[$i]); |
1701
|
2
|
|
|
|
|
6
|
push @b, 'h_b', |
1702
|
2
|
|
|
|
|
3
|
$fcol_lpads->[$ci] + $fcol_widths->[$ci] + $fcol_rpads->[$ci]; |
1703
|
2
|
50
|
|
|
|
5
|
push @b, 'hu_b', 1 unless $i == @$fcols-1; |
1704
|
2
|
|
|
|
|
4
|
} |
1705
|
2
|
|
|
|
|
6
|
push @b, 'lu_b', 1; |
1706
|
2
|
50
|
|
|
|
6
|
$self->draw_border_char(@b); |
1707
|
0
|
|
|
|
|
0
|
$self->draw_str("\n"); |
1708
|
|
|
|
|
|
|
} |
1709
|
2
|
|
|
|
|
5
|
|
1710
|
2
|
|
|
|
|
8
|
join "", @{$self->{_draw}{buf}}; |
1711
|
|
|
|
|
|
|
} |
1712
|
|
|
|
|
|
|
|
1713
|
|
|
|
|
|
|
1; |
1714
|
0
|
|
|
|
|
0
|
# ABSTRACT: Create nice formatted tables using extended ASCII and ANSI colors |
1715
|
|
|
|
|
|
|
|
1716
|
|
|
|
|
|
|
|
1717
|
2
|
|
|
|
|
3
|
=pod |
|
2
|
|
|
|
|
6
|
|
1718
|
2
|
|
|
|
|
9
|
|
1719
|
2
|
|
|
|
|
7
|
=encoding UTF-8 |
1720
|
2
|
|
|
|
|
7
|
|
1721
|
2
|
|
|
|
|
5
|
=head1 NAME |
1722
|
2
|
50
|
|
|
|
6
|
|
1723
|
|
|
|
|
|
|
Text::ANSITable - Create nice formatted tables using extended ASCII and ANSI colors |
1724
|
|
|
|
|
|
|
|
1725
|
2
|
|
|
|
|
8
|
=head1 VERSION |
1726
|
2
|
|
|
|
|
5
|
|
1727
|
|
|
|
|
|
|
This document describes version 0.608 of Text::ANSITable (from Perl distribution Text-ANSITable), released on 2022-02-14. |
1728
|
|
|
|
|
|
|
|
1729
|
|
|
|
|
|
|
=head1 SYNOPSIS |
1730
|
2
|
50
|
|
|
|
4
|
|
1731
|
0
|
|
|
|
|
0
|
use 5.010; |
1732
|
0
|
|
|
|
|
0
|
use Text::ANSITable; |
1733
|
0
|
|
|
|
|
0
|
|
1734
|
0
|
|
|
|
|
0
|
# don't forget this if you want to output utf8 characters |
1735
|
0
|
|
|
|
|
0
|
binmode(STDOUT, ":utf8"); |
1736
|
|
|
|
|
|
|
|
1737
|
|
|
|
|
|
|
my $t = Text::ANSITable->new; |
1738
|
0
|
0
|
|
|
|
0
|
|
1739
|
|
|
|
|
|
|
# set styles |
1740
|
0
|
|
|
|
|
0
|
$t->border_style('UTF8::SingleLineBold'); # if not, a nice default is picked |
1741
|
0
|
|
|
|
|
0
|
$t->color_theme('Standard::NoGradation'); # if not, a nice default is picked |
1742
|
|
|
|
|
|
|
|
1743
|
|
|
|
|
|
|
# fill data |
1744
|
|
|
|
|
|
|
$t->columns(["name" , "color" , "price"]); |
1745
|
|
|
|
|
|
|
$t->add_row(["chiki" , "yellow", 2000]); |
1746
|
|
|
|
|
|
|
$t->add_row(["lays" , "green" , 7000]); |
1747
|
|
|
|
|
|
|
$t->add_row(["tao kae noi", "blue" , 18500]); |
1748
|
1
|
50
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
18
|
|
1749
|
1
|
|
|
|
|
56
|
# draw it! |
1750
|
1
|
|
|
|
|
11
|
print $t->draw; |
1751
|
1
|
|
|
|
|
5
|
|
1752
|
1
|
|
|
|
|
3
|
Samples of output: |
1753
|
1
|
|
|
|
|
13
|
|
1754
|
|
|
|
|
|
|
=head1 DESCRIPTION |
1755
|
1
|
50
|
|
|
|
6
|
|
1756
|
|
|
|
|
|
|
This module is yet another text table formatter module like L<Text::ASCIITable> |
1757
|
1
|
|
|
|
|
3
|
or L<Text::SimpleTable>, with the following differences: |
1758
|
1
|
|
|
|
|
3
|
|
1759
|
1
|
|
|
|
|
3
|
=over |
1760
|
|
|
|
|
|
|
|
1761
|
|
|
|
|
|
|
=item * Colors and color themes |
1762
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
8
|
|
1763
|
|
|
|
|
|
|
ANSI color codes will be used by default (even 256 and 24bit colors), but will |
1764
|
|
|
|
|
|
|
degrade to lower color depth and black/white according to terminal support. |
1765
|
|
|
|
|
|
|
|
1766
|
|
|
|
|
|
|
=item * Box-drawing characters |
1767
|
|
|
|
|
|
|
|
1768
|
|
|
|
|
|
|
Box-drawing characters will be used by default, but will degrade to using normal |
1769
|
|
|
|
|
|
|
ASCII characters if terminal does not support them. |
1770
|
|
|
|
|
|
|
|
1771
|
|
|
|
|
|
|
=item * Unicode and wide character support |
1772
|
|
|
|
|
|
|
|
1773
|
|
|
|
|
|
|
Border styles using Unicode characters (double lines, bold/heavy lines, brick |
1774
|
|
|
|
|
|
|
style, etc). Columns containing wide characters stay aligned. (Note: support for |
1775
|
|
|
|
|
|
|
wide characters requires L<Text::ANSI::WideUtil> which is currently set as an |
1776
|
|
|
|
|
|
|
optional prereq, so you'll need to install it explicitly or set your CPAN client |
1777
|
|
|
|
|
|
|
to install 'recommends' prereq). |
1778
|
|
|
|
|
|
|
|
1779
|
|
|
|
|
|
|
=back |
1780
|
|
|
|
|
|
|
|
1781
|
|
|
|
|
|
|
Compared to Text::ASCIITable, it uses C<lower_case> method/attr names instead of |
1782
|
|
|
|
|
|
|
C<CamelCase>, and it uses arrayref for C<columns> and C<add_row>. When |
1783
|
|
|
|
|
|
|
specifying border styles, the order of characters are slightly different. More |
1784
|
|
|
|
|
|
|
fine-grained options to customize appearance. |
1785
|
|
|
|
|
|
|
|
1786
|
|
|
|
|
|
|
=for Pod::Coverage ^(BUILD|draw_.+|get_color_reset)$ |
1787
|
|
|
|
|
|
|
|
1788
|
|
|
|
|
|
|
=begin HTML |
1789
|
|
|
|
|
|
|
|
1790
|
|
|
|
|
|
|
<p><img src="http://blogs.perl.org/users/steven_haryanto/ansitable1.png" /></p> |
1791
|
|
|
|
|
|
|
|
1792
|
|
|
|
|
|
|
<p><img src="http://blogs.perl.org/users/steven_haryanto/ansitable2.png" /></p> |
1793
|
|
|
|
|
|
|
|
1794
|
|
|
|
|
|
|
<p><img src="http://blogs.perl.org/users/steven_haryanto/ansitable3.png" /></p> |
1795
|
|
|
|
|
|
|
|
1796
|
|
|
|
|
|
|
<p><img src="http://blogs.perl.org/users/steven_haryanto/ansitable4.png" /></p> |
1797
|
|
|
|
|
|
|
|
1798
|
|
|
|
|
|
|
<p><img src="http://blogs.perl.org/users/steven_haryanto/ansitable5.png" /></p> |
1799
|
|
|
|
|
|
|
|
1800
|
|
|
|
|
|
|
=end HTML |
1801
|
|
|
|
|
|
|
|
1802
|
|
|
|
|
|
|
=head1 DECLARED FEATURES |
1803
|
|
|
|
|
|
|
|
1804
|
|
|
|
|
|
|
Features declared by this module: |
1805
|
|
|
|
|
|
|
|
1806
|
|
|
|
|
|
|
=head2 From feature set PerlTrove |
1807
|
|
|
|
|
|
|
|
1808
|
|
|
|
|
|
|
Features from feature set L<PerlTrove|Module::Features::PerlTrove> declared by this module: |
1809
|
|
|
|
|
|
|
|
1810
|
|
|
|
|
|
|
=over |
1811
|
|
|
|
|
|
|
|
1812
|
|
|
|
|
|
|
=item * Development Status |
1813
|
|
|
|
|
|
|
|
1814
|
|
|
|
|
|
|
Value: "5 - ProductionE<sol>Stable". |
1815
|
|
|
|
|
|
|
|
1816
|
|
|
|
|
|
|
=item * Environment |
1817
|
|
|
|
|
|
|
|
1818
|
|
|
|
|
|
|
Value: "Console". |
1819
|
|
|
|
|
|
|
|
1820
|
|
|
|
|
|
|
=item * Intended Audience |
1821
|
|
|
|
|
|
|
|
1822
|
|
|
|
|
|
|
Value: ["Developers"]. |
1823
|
|
|
|
|
|
|
|
1824
|
|
|
|
|
|
|
=item * License |
1825
|
|
|
|
|
|
|
|
1826
|
|
|
|
|
|
|
Value: "OSI Approved :: Artistic License". |
1827
|
|
|
|
|
|
|
|
1828
|
|
|
|
|
|
|
=item * Programming Language |
1829
|
|
|
|
|
|
|
|
1830
|
|
|
|
|
|
|
Value: "Perl". |
1831
|
|
|
|
|
|
|
|
1832
|
|
|
|
|
|
|
=item * Topic |
1833
|
|
|
|
|
|
|
|
1834
|
|
|
|
|
|
|
Value: ["Software Development :: Libraries :: Perl Modules","Utilities"]. |
1835
|
|
|
|
|
|
|
|
1836
|
|
|
|
|
|
|
=back |
1837
|
|
|
|
|
|
|
|
1838
|
|
|
|
|
|
|
=head2 From feature set TextTable |
1839
|
|
|
|
|
|
|
|
1840
|
|
|
|
|
|
|
Features from feature set L<TextTable|Module::Features::TextTable> declared by this module: |
1841
|
|
|
|
|
|
|
|
1842
|
|
|
|
|
|
|
=over |
1843
|
|
|
|
|
|
|
|
1844
|
|
|
|
|
|
|
=item * can_align_cell_containing_color_code |
1845
|
|
|
|
|
|
|
|
1846
|
|
|
|
|
|
|
Value: yes. |
1847
|
|
|
|
|
|
|
|
1848
|
|
|
|
|
|
|
=item * can_align_cell_containing_newline |
1849
|
|
|
|
|
|
|
|
1850
|
|
|
|
|
|
|
Value: yes. |
1851
|
|
|
|
|
|
|
|
1852
|
|
|
|
|
|
|
=item * can_align_cell_containing_wide_character |
1853
|
|
|
|
|
|
|
|
1854
|
|
|
|
|
|
|
Value: yes. |
1855
|
|
|
|
|
|
|
|
1856
|
|
|
|
|
|
|
=item * can_color |
1857
|
|
|
|
|
|
|
|
1858
|
|
|
|
|
|
|
Can produce colored table. |
1859
|
|
|
|
|
|
|
|
1860
|
|
|
|
|
|
|
Value: yes. |
1861
|
|
|
|
|
|
|
|
1862
|
|
|
|
|
|
|
=item * can_color_theme |
1863
|
|
|
|
|
|
|
|
1864
|
|
|
|
|
|
|
Allow choosing colors from a named set of palettes. |
1865
|
|
|
|
|
|
|
|
1866
|
|
|
|
|
|
|
Value: yes. |
1867
|
|
|
|
|
|
|
|
1868
|
|
|
|
|
|
|
=item * can_colspan |
1869
|
|
|
|
|
|
|
|
1870
|
|
|
|
|
|
|
Value: no. |
1871
|
|
|
|
|
|
|
|
1872
|
|
|
|
|
|
|
=item * can_customize_border |
1873
|
|
|
|
|
|
|
|
1874
|
|
|
|
|
|
|
Let user customize border character in some way, e.g. selecting from several available borders, disable border. |
1875
|
|
|
|
|
|
|
|
1876
|
|
|
|
|
|
|
Value: yes. |
1877
|
|
|
|
|
|
|
|
1878
|
|
|
|
|
|
|
=item * can_halign |
1879
|
|
|
|
|
|
|
|
1880
|
|
|
|
|
|
|
Provide a way for user to specify horizontal alignment (leftE<sol>middleE<sol>right) of cells. |
1881
|
|
|
|
|
|
|
|
1882
|
|
|
|
|
|
|
Value: yes. |
1883
|
|
|
|
|
|
|
|
1884
|
|
|
|
|
|
|
=item * can_halign_individual_cell |
1885
|
|
|
|
|
|
|
|
1886
|
|
|
|
|
|
|
Provide a way for user to specify different horizontal alignment (leftE<sol>middleE<sol>right) for individual cells. |
1887
|
|
|
|
|
|
|
|
1888
|
|
|
|
|
|
|
Value: yes. |
1889
|
|
|
|
|
|
|
|
1890
|
|
|
|
|
|
|
=item * can_halign_individual_column |
1891
|
|
|
|
|
|
|
|
1892
|
|
|
|
|
|
|
Provide a way for user to specify different horizontal alignment (leftE<sol>middleE<sol>right) for individual columns. |
1893
|
|
|
|
|
|
|
|
1894
|
|
|
|
|
|
|
Value: yes. |
1895
|
|
|
|
|
|
|
|
1896
|
|
|
|
|
|
|
=item * can_halign_individual_row |
1897
|
|
|
|
|
|
|
|
1898
|
|
|
|
|
|
|
Provide a way for user to specify different horizontal alignment (leftE<sol>middleE<sol>right) for individual rows. |
1899
|
|
|
|
|
|
|
|
1900
|
|
|
|
|
|
|
Value: yes. |
1901
|
|
|
|
|
|
|
|
1902
|
|
|
|
|
|
|
=item * can_hpad |
1903
|
|
|
|
|
|
|
|
1904
|
|
|
|
|
|
|
Provide a way for user to specify horizontal padding of cells. |
1905
|
|
|
|
|
|
|
|
1906
|
|
|
|
|
|
|
Value: yes. |
1907
|
|
|
|
|
|
|
|
1908
|
|
|
|
|
|
|
=item * can_hpad_individual_cell |
1909
|
|
|
|
|
|
|
|
1910
|
|
|
|
|
|
|
Provide a way for user to specify different horizontal padding of individual cells. |
1911
|
|
|
|
|
|
|
|
1912
|
|
|
|
|
|
|
Value: yes. |
1913
|
|
|
|
|
|
|
|
1914
|
|
|
|
|
|
|
=item * can_hpad_individual_column |
1915
|
|
|
|
|
|
|
|
1916
|
|
|
|
|
|
|
Provide a way for user to specify different horizontal padding of individual columns. |
1917
|
|
|
|
|
|
|
|
1918
|
|
|
|
|
|
|
Value: yes. |
1919
|
|
|
|
|
|
|
|
1920
|
|
|
|
|
|
|
=item * can_hpad_individual_row |
1921
|
|
|
|
|
|
|
|
1922
|
|
|
|
|
|
|
Provide a way for user to specify different horizontal padding of individual rows. |
1923
|
|
|
|
|
|
|
|
1924
|
|
|
|
|
|
|
Value: yes. |
1925
|
|
|
|
|
|
|
|
1926
|
|
|
|
|
|
|
=item * can_rowspan |
1927
|
|
|
|
|
|
|
|
1928
|
|
|
|
|
|
|
Value: no. |
1929
|
|
|
|
|
|
|
|
1930
|
|
|
|
|
|
|
=item * can_set_cell_height |
1931
|
|
|
|
|
|
|
|
1932
|
|
|
|
|
|
|
Allow setting height of rows. |
1933
|
|
|
|
|
|
|
|
1934
|
|
|
|
|
|
|
Value: yes. |
1935
|
|
|
|
|
|
|
|
1936
|
|
|
|
|
|
|
=item * can_set_cell_height_of_individual_row |
1937
|
|
|
|
|
|
|
|
1938
|
|
|
|
|
|
|
Allow setting height of individual rows. |
1939
|
|
|
|
|
|
|
|
1940
|
|
|
|
|
|
|
Value: yes. |
1941
|
|
|
|
|
|
|
|
1942
|
|
|
|
|
|
|
=item * can_set_cell_width |
1943
|
|
|
|
|
|
|
|
1944
|
|
|
|
|
|
|
Allow setting height of rows. |
1945
|
|
|
|
|
|
|
|
1946
|
|
|
|
|
|
|
Value: yes. |
1947
|
|
|
|
|
|
|
|
1948
|
|
|
|
|
|
|
=item * can_set_cell_width_of_individual_column |
1949
|
|
|
|
|
|
|
|
1950
|
|
|
|
|
|
|
Allow setting height of individual rows. |
1951
|
|
|
|
|
|
|
|
1952
|
|
|
|
|
|
|
Value: yes. |
1953
|
|
|
|
|
|
|
|
1954
|
|
|
|
|
|
|
=item * can_use_box_character |
1955
|
|
|
|
|
|
|
|
1956
|
|
|
|
|
|
|
Can use terminal box-drawing character when drawing border. |
1957
|
|
|
|
|
|
|
|
1958
|
|
|
|
|
|
|
Value: yes. |
1959
|
|
|
|
|
|
|
|
1960
|
|
|
|
|
|
|
=item * can_valign |
1961
|
|
|
|
|
|
|
|
1962
|
|
|
|
|
|
|
Provide a way for user to specify vertical alignment (topE<sol>middleE<sol>bottom) of cells. |
1963
|
|
|
|
|
|
|
|
1964
|
|
|
|
|
|
|
Value: yes. |
1965
|
|
|
|
|
|
|
|
1966
|
|
|
|
|
|
|
=item * can_valign_individual_cell |
1967
|
|
|
|
|
|
|
|
1968
|
|
|
|
|
|
|
Provide a way for user to specify different vertical alignment (topE<sol>middleE<sol>bottom) for individual cells. |
1969
|
|
|
|
|
|
|
|
1970
|
|
|
|
|
|
|
Value: yes. |
1971
|
|
|
|
|
|
|
|
1972
|
|
|
|
|
|
|
=item * can_valign_individual_column |
1973
|
|
|
|
|
|
|
|
1974
|
|
|
|
|
|
|
Provide a way for user to specify different vertical alignment (topE<sol>middleE<sol>bottom) for individual columns. |
1975
|
|
|
|
|
|
|
|
1976
|
|
|
|
|
|
|
Value: yes. |
1977
|
|
|
|
|
|
|
|
1978
|
|
|
|
|
|
|
=item * can_valign_individual_row |
1979
|
|
|
|
|
|
|
|
1980
|
|
|
|
|
|
|
Provide a way for user to specify different vertical alignment (topE<sol>middleE<sol>bottom) for individual rows. |
1981
|
|
|
|
|
|
|
|
1982
|
|
|
|
|
|
|
Value: yes. |
1983
|
|
|
|
|
|
|
|
1984
|
|
|
|
|
|
|
=item * can_vpad |
1985
|
|
|
|
|
|
|
|
1986
|
|
|
|
|
|
|
Provide a way for user to specify vertical padding of cells. |
1987
|
|
|
|
|
|
|
|
1988
|
|
|
|
|
|
|
Value: yes. |
1989
|
|
|
|
|
|
|
|
1990
|
|
|
|
|
|
|
=item * can_vpad_individual_cell |
1991
|
|
|
|
|
|
|
|
1992
|
|
|
|
|
|
|
Provide a way for user to specify different vertical padding of individual cells. |
1993
|
|
|
|
|
|
|
|
1994
|
|
|
|
|
|
|
Value: yes. |
1995
|
|
|
|
|
|
|
|
1996
|
|
|
|
|
|
|
=item * can_vpad_individual_column |
1997
|
|
|
|
|
|
|
|
1998
|
|
|
|
|
|
|
Provide a way for user to specify different vertical padding of individual columns. |
1999
|
|
|
|
|
|
|
|
2000
|
|
|
|
|
|
|
Value: yes. |
2001
|
|
|
|
|
|
|
|
2002
|
|
|
|
|
|
|
=item * can_vpad_individual_row |
2003
|
|
|
|
|
|
|
|
2004
|
|
|
|
|
|
|
Provide a way for user to specify different vertical padding of individual rows. |
2005
|
|
|
|
|
|
|
|
2006
|
|
|
|
|
|
|
Value: yes. |
2007
|
|
|
|
|
|
|
|
2008
|
|
|
|
|
|
|
=item * speed |
2009
|
|
|
|
|
|
|
|
2010
|
|
|
|
|
|
|
Subjective speed rating, relative to other text table modules. |
2011
|
|
|
|
|
|
|
|
2012
|
|
|
|
|
|
|
Value: "slow". |
2013
|
|
|
|
|
|
|
|
2014
|
|
|
|
|
|
|
=back |
2015
|
|
|
|
|
|
|
|
2016
|
|
|
|
|
|
|
For more details on module features, see L<Module::Features>. |
2017
|
|
|
|
|
|
|
|
2018
|
|
|
|
|
|
|
=head1 REFERRING TO COLUMNS |
2019
|
|
|
|
|
|
|
|
2020
|
|
|
|
|
|
|
Columns can be referred to be integer number (0-based) or name (string). You |
2021
|
|
|
|
|
|
|
should not have integer numbers as column names because that will be confusing. |
2022
|
|
|
|
|
|
|
Example: |
2023
|
|
|
|
|
|
|
|
2024
|
|
|
|
|
|
|
$t->columns(["col1", "col2", "col3"]); # col1=0, col2=1, col3=2 |
2025
|
|
|
|
|
|
|
$t->add_row([...]); |
2026
|
|
|
|
|
|
|
... |
2027
|
|
|
|
|
|
|
|
2028
|
|
|
|
|
|
|
# set visible columns |
2029
|
|
|
|
|
|
|
$t->column_filter([1,2,1]); # col2, col3, col2 |
2030
|
|
|
|
|
|
|
$t->column_filter(["col2","col3","col2"]); # same thing |
2031
|
|
|
|
|
|
|
|
2032
|
|
|
|
|
|
|
See also: L</REFERRING TO ROWS>. |
2033
|
|
|
|
|
|
|
|
2034
|
|
|
|
|
|
|
=head1 REFERRING TO ROWS |
2035
|
|
|
|
|
|
|
|
2036
|
|
|
|
|
|
|
Rows are referred to by integer number (0-based). |
2037
|
|
|
|
|
|
|
|
2038
|
|
|
|
|
|
|
$t->columns(["name", "age", "gender"]); |
2039
|
|
|
|
|
|
|
$t->add_row(["marty", ...]); # first row (0) |
2040
|
|
|
|
|
|
|
$t->add_row(["wendy", ...]); # second row (1) |
2041
|
|
|
|
|
|
|
$t->add_row(["charlotte", ...]); # third row (2) |
2042
|
|
|
|
|
|
|
|
2043
|
|
|
|
|
|
|
# set visible rows |
2044
|
|
|
|
|
|
|
$t->row_filter([0,2]); # marty & charlotte |
2045
|
|
|
|
|
|
|
|
2046
|
|
|
|
|
|
|
See also: L</REFERRING TO COLUMNS>. |
2047
|
|
|
|
|
|
|
|
2048
|
|
|
|
|
|
|
=head1 BORDER STYLES |
2049
|
|
|
|
|
|
|
|
2050
|
|
|
|
|
|
|
To list available border styles, just list the C<BorderStyle::*> modules. You |
2051
|
|
|
|
|
|
|
can use the provided method: |
2052
|
|
|
|
|
|
|
|
2053
|
|
|
|
|
|
|
say $_ for $t->list_border_styles; |
2054
|
|
|
|
|
|
|
|
2055
|
|
|
|
|
|
|
Or you can also try out borders using the provided |
2056
|
|
|
|
|
|
|
L<ansitable-list-border-styles> script. |
2057
|
|
|
|
|
|
|
|
2058
|
|
|
|
|
|
|
To choose border style, set the C<border_style> attribute to an available border |
2059
|
|
|
|
|
|
|
style name (which is the BorderStyle::* module name without the prefix) with |
2060
|
|
|
|
|
|
|
optional arguments. |
2061
|
|
|
|
|
|
|
|
2062
|
|
|
|
|
|
|
# during construction |
2063
|
|
|
|
|
|
|
my $t = Text::ANSITable->new( |
2064
|
|
|
|
|
|
|
... |
2065
|
|
|
|
|
|
|
border_style => "UTF8::SingleLineBold", |
2066
|
|
|
|
|
|
|
... |
2067
|
|
|
|
|
|
|
); |
2068
|
|
|
|
|
|
|
|
2069
|
|
|
|
|
|
|
# after the object is constructed |
2070
|
|
|
|
|
|
|
$t->border_style("UTF8::SingleLineBold"); |
2071
|
|
|
|
|
|
|
$t->border_style("Test::CustomChar=character,x"); |
2072
|
|
|
|
|
|
|
$t->border_style(["Test::CustomChar", {character=>"x"}]); |
2073
|
|
|
|
|
|
|
|
2074
|
|
|
|
|
|
|
If no border style is selected explicitly, a nice default will be chosen. You |
2075
|
|
|
|
|
|
|
can also set the C<ANSITABLE_BORDER_STYLE> or C<BORDER_STYLE> environment |
2076
|
|
|
|
|
|
|
variable to set the default. |
2077
|
|
|
|
|
|
|
|
2078
|
|
|
|
|
|
|
To create a new border style, see L<BorderStyle>. |
2079
|
|
|
|
|
|
|
|
2080
|
|
|
|
|
|
|
=head1 COLOR THEMES |
2081
|
|
|
|
|
|
|
|
2082
|
|
|
|
|
|
|
To list available color themes, just list the C<ColorTheme::*> modules (usually |
2083
|
|
|
|
|
|
|
you want to use color themes specifically created for Text::ANSITable in |
2084
|
|
|
|
|
|
|
C<ColorTheme::Text::ANSITable::*> namespace). You can use the provided method: |
2085
|
|
|
|
|
|
|
|
2086
|
|
|
|
|
|
|
say $_ for $t->list_color_themes; |
2087
|
|
|
|
|
|
|
|
2088
|
|
|
|
|
|
|
Or you can also run the provided L<ansitable-list-color-themes> script. |
2089
|
|
|
|
|
|
|
|
2090
|
|
|
|
|
|
|
To choose a color theme, set the C<color_theme> attribute to an available color |
2091
|
|
|
|
|
|
|
theme (which is the ColorTheme::* module name without the prefix) with optional |
2092
|
|
|
|
|
|
|
arguments: |
2093
|
|
|
|
|
|
|
|
2094
|
|
|
|
|
|
|
# during construction |
2095
|
|
|
|
|
|
|
my $t = Text::ANSITable->new( |
2096
|
|
|
|
|
|
|
... |
2097
|
|
|
|
|
|
|
color_theme => "Standard::NoGradation", |
2098
|
|
|
|
|
|
|
... |
2099
|
|
|
|
|
|
|
); |
2100
|
|
|
|
|
|
|
|
2101
|
|
|
|
|
|
|
# after the object is constructed |
2102
|
|
|
|
|
|
|
$t->color_theme("Standard::NoGradation"); |
2103
|
|
|
|
|
|
|
$t->color_theme(["Lens::Darken", {theme=>"Standard::NoGradation"}]); |
2104
|
|
|
|
|
|
|
|
2105
|
|
|
|
|
|
|
If no color theme is selected explicitly, a nice default will be chosen. You can |
2106
|
|
|
|
|
|
|
also set the C<ANSITABLE_COLOR_THEME> environment variable to set the default. |
2107
|
|
|
|
|
|
|
|
2108
|
|
|
|
|
|
|
To create a new color theme, see L<ColorTheme> and an existing |
2109
|
|
|
|
|
|
|
C<ColorTheme::Text::ANSITable::*> module. |
2110
|
|
|
|
|
|
|
|
2111
|
|
|
|
|
|
|
=head1 COLUMN WIDTHS |
2112
|
|
|
|
|
|
|
|
2113
|
|
|
|
|
|
|
By default column width is set just so it is enough to show the widest data. |
2114
|
|
|
|
|
|
|
This can be customized in the following ways (in order of precedence, from |
2115
|
|
|
|
|
|
|
lowest): |
2116
|
|
|
|
|
|
|
|
2117
|
|
|
|
|
|
|
=over |
2118
|
|
|
|
|
|
|
|
2119
|
|
|
|
|
|
|
=item * table-level C<cell_width> attribute |
2120
|
|
|
|
|
|
|
|
2121
|
|
|
|
|
|
|
This sets width for all columns. |
2122
|
|
|
|
|
|
|
|
2123
|
|
|
|
|
|
|
=item * conditional column styles |
2124
|
|
|
|
|
|
|
|
2125
|
|
|
|
|
|
|
The example below sets column width to 10 for columns whose names matching |
2126
|
|
|
|
|
|
|
C</[acm]time/>, else sets the column width to 20. |
2127
|
|
|
|
|
|
|
|
2128
|
|
|
|
|
|
|
$t->add_cond_column_style(sub { /[acm]time/ }, width => 10); |
2129
|
|
|
|
|
|
|
$t->add_cond_column_style(sub { !/[acm]time/ }, width => 20); |
2130
|
|
|
|
|
|
|
|
2131
|
|
|
|
|
|
|
=item * per-column C<width> style |
2132
|
|
|
|
|
|
|
|
2133
|
|
|
|
|
|
|
$t->set_column_style('colname', width => 20); |
2134
|
|
|
|
|
|
|
|
2135
|
|
|
|
|
|
|
=back |
2136
|
|
|
|
|
|
|
|
2137
|
|
|
|
|
|
|
You can use negative number to mean I<minimum> width. |
2138
|
|
|
|
|
|
|
|
2139
|
|
|
|
|
|
|
=head1 ROW HEIGHTS |
2140
|
|
|
|
|
|
|
|
2141
|
|
|
|
|
|
|
This can be customized in the following ways (in order of precedence, from |
2142
|
|
|
|
|
|
|
lowest): |
2143
|
|
|
|
|
|
|
|
2144
|
|
|
|
|
|
|
=over |
2145
|
|
|
|
|
|
|
|
2146
|
|
|
|
|
|
|
=item * table-level C<cell_height> attribute |
2147
|
|
|
|
|
|
|
|
2148
|
|
|
|
|
|
|
This sets height for all rows. |
2149
|
|
|
|
|
|
|
|
2150
|
|
|
|
|
|
|
=item * conditional row styles |
2151
|
|
|
|
|
|
|
|
2152
|
|
|
|
|
|
|
The example below sets row height to 2 for every odd rows, and 1 for even rows. |
2153
|
|
|
|
|
|
|
|
2154
|
|
|
|
|
|
|
$t->add_cond_row_style(sub { $_ % 2 == 0 }, height => 2); |
2155
|
|
|
|
|
|
|
$t->add_cond_row_style(sub { $_ % 2 }, height => 1); |
2156
|
|
|
|
|
|
|
|
2157
|
|
|
|
|
|
|
=item * per-row C<height> style |
2158
|
|
|
|
|
|
|
|
2159
|
|
|
|
|
|
|
$t->set_row_style(1, height => 2); |
2160
|
|
|
|
|
|
|
|
2161
|
|
|
|
|
|
|
=back |
2162
|
|
|
|
|
|
|
|
2163
|
|
|
|
|
|
|
You can use negative number to mean I<minimum> height. |
2164
|
|
|
|
|
|
|
|
2165
|
|
|
|
|
|
|
=head1 CELL (HORIZONTAL) PADDING |
2166
|
|
|
|
|
|
|
|
2167
|
|
|
|
|
|
|
By default cell (horizontal) padding is 1. This can be customized in the |
2168
|
|
|
|
|
|
|
following ways (in order of precedence, from lowest): |
2169
|
|
|
|
|
|
|
|
2170
|
|
|
|
|
|
|
=over |
2171
|
|
|
|
|
|
|
|
2172
|
|
|
|
|
|
|
=item * table-level C<cell_pad> attribute |
2173
|
|
|
|
|
|
|
|
2174
|
|
|
|
|
|
|
This sets left and right padding for all columns. |
2175
|
|
|
|
|
|
|
|
2176
|
|
|
|
|
|
|
=item * table-level C<cell_lpad> and C<cell_rpad> attributes |
2177
|
|
|
|
|
|
|
|
2178
|
|
|
|
|
|
|
They set left and right padding for all columns, respectively. |
2179
|
|
|
|
|
|
|
|
2180
|
|
|
|
|
|
|
=item * conditional column C<pad> style |
2181
|
|
|
|
|
|
|
|
2182
|
|
|
|
|
|
|
$t->add_cond_column_style($cond, pad => 0); |
2183
|
|
|
|
|
|
|
|
2184
|
|
|
|
|
|
|
=item * conditional column C<lpad>/C<rpad> style |
2185
|
|
|
|
|
|
|
|
2186
|
|
|
|
|
|
|
$t->add_cond_column_style($cond, lpad => 1, rpad => 2); |
2187
|
|
|
|
|
|
|
|
2188
|
|
|
|
|
|
|
=item * per-column C<pad> style |
2189
|
|
|
|
|
|
|
|
2190
|
|
|
|
|
|
|
$t->set_column_style($colname, pad => 0); |
2191
|
|
|
|
|
|
|
|
2192
|
|
|
|
|
|
|
=item * per-column C<lpad>/C<rpad> style |
2193
|
|
|
|
|
|
|
|
2194
|
|
|
|
|
|
|
$t->set_column_style($colname, lpad => 1); |
2195
|
|
|
|
|
|
|
$t->set_column_style($colname, rpad => 2); |
2196
|
|
|
|
|
|
|
|
2197
|
|
|
|
|
|
|
=back |
2198
|
|
|
|
|
|
|
|
2199
|
|
|
|
|
|
|
=head1 ROW VERTICAL PADDING |
2200
|
|
|
|
|
|
|
|
2201
|
|
|
|
|
|
|
Default vertical padding is 0. This can be changed in the following ways (in |
2202
|
|
|
|
|
|
|
order of precedence, from lowest): |
2203
|
|
|
|
|
|
|
|
2204
|
|
|
|
|
|
|
=over |
2205
|
|
|
|
|
|
|
|
2206
|
|
|
|
|
|
|
=item * table-level C<cell_vpad> attribute |
2207
|
|
|
|
|
|
|
|
2208
|
|
|
|
|
|
|
This sets top and bottom padding for all rows. |
2209
|
|
|
|
|
|
|
|
2210
|
|
|
|
|
|
|
=item * table-level C<cell_tpad>/C<cell_bpad> attributes |
2211
|
|
|
|
|
|
|
|
2212
|
|
|
|
|
|
|
They set top/bottom padding separately for all rows. |
2213
|
|
|
|
|
|
|
|
2214
|
|
|
|
|
|
|
=item * conditional row C<vpad> style |
2215
|
|
|
|
|
|
|
|
2216
|
|
|
|
|
|
|
Example: |
2217
|
|
|
|
|
|
|
|
2218
|
|
|
|
|
|
|
$t->add_cond_row_style($cond, vpad => 1); |
2219
|
|
|
|
|
|
|
|
2220
|
|
|
|
|
|
|
=item * per-row C<vpad> style |
2221
|
|
|
|
|
|
|
|
2222
|
|
|
|
|
|
|
Example: |
2223
|
|
|
|
|
|
|
|
2224
|
|
|
|
|
|
|
$t->set_row_style($rownum, vpad => 1); |
2225
|
|
|
|
|
|
|
|
2226
|
|
|
|
|
|
|
When adding row: |
2227
|
|
|
|
|
|
|
|
2228
|
|
|
|
|
|
|
$t->add_row($rownum, {vpad=>1}); |
2229
|
|
|
|
|
|
|
|
2230
|
|
|
|
|
|
|
=item * per-row C<tpad>/C<bpad> style |
2231
|
|
|
|
|
|
|
|
2232
|
|
|
|
|
|
|
Example: |
2233
|
|
|
|
|
|
|
|
2234
|
|
|
|
|
|
|
$t->set_row_style($rownum, tpad => 1); |
2235
|
|
|
|
|
|
|
$t->set_row_style($rownum, bpad => 2); |
2236
|
|
|
|
|
|
|
|
2237
|
|
|
|
|
|
|
When adding row: |
2238
|
|
|
|
|
|
|
|
2239
|
|
|
|
|
|
|
$t->add_row($row, {tpad=>1, bpad=>2}); |
2240
|
|
|
|
|
|
|
|
2241
|
|
|
|
|
|
|
=back |
2242
|
|
|
|
|
|
|
|
2243
|
|
|
|
|
|
|
=head1 CELL COLORS |
2244
|
|
|
|
|
|
|
|
2245
|
|
|
|
|
|
|
By default data format colors are used, e.g. cyan/green for text (using the |
2246
|
|
|
|
|
|
|
default color scheme, items C<num_data>, C<bool_data>, etc). In absense of that, |
2247
|
|
|
|
|
|
|
C<cell_fgcolor> and C<cell_bgcolor> from the color scheme are used. You can |
2248
|
|
|
|
|
|
|
customize colors in the following ways (ordered by precedence, from lowest): |
2249
|
|
|
|
|
|
|
|
2250
|
|
|
|
|
|
|
=over |
2251
|
|
|
|
|
|
|
|
2252
|
|
|
|
|
|
|
=item * table-level C<cell_fgcolor> and C<cell_bgcolor> attributes |
2253
|
|
|
|
|
|
|
|
2254
|
|
|
|
|
|
|
Sets all cells' colors. Color should be specified using 6-hexdigit RGB which |
2255
|
|
|
|
|
|
|
will be converted to the appropriate terminal color. |
2256
|
|
|
|
|
|
|
|
2257
|
|
|
|
|
|
|
Can also be set to a coderef which will receive ($rownum, $colname) and should |
2258
|
|
|
|
|
|
|
return an RGB color. |
2259
|
|
|
|
|
|
|
|
2260
|
|
|
|
|
|
|
=item * conditional column C<fgcolor> and C<bgcolor> style |
2261
|
|
|
|
|
|
|
|
2262
|
|
|
|
|
|
|
Example: |
2263
|
|
|
|
|
|
|
|
2264
|
|
|
|
|
|
|
$t->add_cond_column_style($cond, fgcolor => 'fa8888', bgcolor => '202020'); |
2265
|
|
|
|
|
|
|
|
2266
|
|
|
|
|
|
|
=item * per-column C<fgcolor> and C<bgcolor> styles |
2267
|
|
|
|
|
|
|
|
2268
|
|
|
|
|
|
|
Example: |
2269
|
|
|
|
|
|
|
|
2270
|
|
|
|
|
|
|
$t->set_column_style('colname', fgcolor => 'fa8888'); |
2271
|
|
|
|
|
|
|
$t->set_column_style('colname', bgcolor => '202020'); |
2272
|
|
|
|
|
|
|
|
2273
|
|
|
|
|
|
|
=item * conditional row C<fgcolor> and C<bgcolor> style |
2274
|
|
|
|
|
|
|
|
2275
|
|
|
|
|
|
|
Example: |
2276
|
|
|
|
|
|
|
|
2277
|
|
|
|
|
|
|
$t->add_cond_row_style($cond, fgcolor => 'fa8888', bgcolor => '202020'); |
2278
|
|
|
|
|
|
|
|
2279
|
|
|
|
|
|
|
=item * per-row C<fgcolor> and C<bgcolor> styles |
2280
|
|
|
|
|
|
|
|
2281
|
|
|
|
|
|
|
Example: |
2282
|
|
|
|
|
|
|
|
2283
|
|
|
|
|
|
|
$t->set_row_style($rownum, {fgcolor => 'fa8888', bgcolor => '202020'}); |
2284
|
|
|
|
|
|
|
|
2285
|
|
|
|
|
|
|
When adding row/rows: |
2286
|
|
|
|
|
|
|
|
2287
|
|
|
|
|
|
|
$t->add_row($row, {fgcolor=>..., bgcolor=>...}); |
2288
|
|
|
|
|
|
|
$t->add_rows($rows, {bgcolor=>...}); |
2289
|
|
|
|
|
|
|
|
2290
|
|
|
|
|
|
|
=item * conditional cell C<fgcolor> and C<bgcolor> style |
2291
|
|
|
|
|
|
|
|
2292
|
|
|
|
|
|
|
$t->add_cond_cell_style($cond, fgcolor=>..., bgcolor=>...); |
2293
|
|
|
|
|
|
|
|
2294
|
|
|
|
|
|
|
=item * per-cell C<fgcolor> and C<bgcolor> styles |
2295
|
|
|
|
|
|
|
|
2296
|
|
|
|
|
|
|
Example: |
2297
|
|
|
|
|
|
|
|
2298
|
|
|
|
|
|
|
$t->set_cell_style($rownum, $colname, fgcolor => 'fa8888'); |
2299
|
|
|
|
|
|
|
$t->set_cell_style($rownum, $colname, bgcolor => '202020'); |
2300
|
|
|
|
|
|
|
|
2301
|
|
|
|
|
|
|
=back |
2302
|
|
|
|
|
|
|
|
2303
|
|
|
|
|
|
|
For flexibility, all colors can be specified as coderef. See L</"COLOR THEMES"> |
2304
|
|
|
|
|
|
|
for more details. |
2305
|
|
|
|
|
|
|
|
2306
|
|
|
|
|
|
|
=head1 CELL (HORIZONTAL AND VERTICAL) ALIGNMENT |
2307
|
|
|
|
|
|
|
|
2308
|
|
|
|
|
|
|
By default, numbers are right-aligned, dates and bools are centered, and the |
2309
|
|
|
|
|
|
|
other data types (text including) are left-aligned. All data are top-valigned. |
2310
|
|
|
|
|
|
|
This can be customized in the following ways (in order of precedence, from |
2311
|
|
|
|
|
|
|
lowest): |
2312
|
|
|
|
|
|
|
|
2313
|
|
|
|
|
|
|
=over |
2314
|
|
|
|
|
|
|
|
2315
|
|
|
|
|
|
|
=item * table-level C<cell_align> and C<cell_valign> attribute |
2316
|
|
|
|
|
|
|
|
2317
|
|
|
|
|
|
|
=item * conditional column C<align> and <valign> styles |
2318
|
|
|
|
|
|
|
|
2319
|
|
|
|
|
|
|
$t->add_cond_column_style($cond, align=>..., valign=>...); |
2320
|
|
|
|
|
|
|
|
2321
|
|
|
|
|
|
|
=item * per-column C<align> and C<valign> styles |
2322
|
|
|
|
|
|
|
|
2323
|
|
|
|
|
|
|
Example: |
2324
|
|
|
|
|
|
|
|
2325
|
|
|
|
|
|
|
$t->set_column_style($colname, align => 'middle'); # or left, or right |
2326
|
|
|
|
|
|
|
$t->set_column_style($colname, valign => 'top'); # or bottom, or middle |
2327
|
|
|
|
|
|
|
|
2328
|
|
|
|
|
|
|
=item * conditional row C<align> and <valign> styles |
2329
|
|
|
|
|
|
|
|
2330
|
|
|
|
|
|
|
$t->add_cond_row_style($cond, align=>..., valign=>...); |
2331
|
|
|
|
|
|
|
|
2332
|
|
|
|
|
|
|
=item * per-row C<align> and C<valign> styles |
2333
|
|
|
|
|
|
|
|
2334
|
|
|
|
|
|
|
=item * conditional cell C<align> and <valign> styles |
2335
|
|
|
|
|
|
|
|
2336
|
|
|
|
|
|
|
$t->add_cond_cell_style($cond, align=>..., valign=>...); |
2337
|
|
|
|
|
|
|
|
2338
|
|
|
|
|
|
|
=item * per-cell C<align> and C<valign> styles |
2339
|
|
|
|
|
|
|
|
2340
|
|
|
|
|
|
|
$t->set_cell_style($rownum, $colname, align => 'middle'); |
2341
|
|
|
|
|
|
|
$t->set_cell_style($rownum, $colname, valign => 'top'); |
2342
|
|
|
|
|
|
|
|
2343
|
|
|
|
|
|
|
=back |
2344
|
|
|
|
|
|
|
|
2345
|
|
|
|
|
|
|
=head1 CELL FORMATS |
2346
|
|
|
|
|
|
|
|
2347
|
|
|
|
|
|
|
The per-column- and per-cell- C<formats> style regulates how to format data. The |
2348
|
|
|
|
|
|
|
value for this style setting will be passed to L<Data::Unixish::Apply>'s |
2349
|
|
|
|
|
|
|
C<apply()>, as the C<functions> argument. So it should be a single string (like |
2350
|
|
|
|
|
|
|
C<date>) or an array (like C<< ['date', ['centerpad', {width=>20}]] >>). |
2351
|
|
|
|
|
|
|
|
2352
|
|
|
|
|
|
|
L<Data::Unixish::Apply> is an optional prerequisite, so you will need to install |
2353
|
|
|
|
|
|
|
it separately if you need this feature. |
2354
|
|
|
|
|
|
|
|
2355
|
|
|
|
|
|
|
To see what functions are available, install L<App::dux> and then run C<dux -l>. |
2356
|
|
|
|
|
|
|
Functions of interest to formatting data include: C<bool>, C<num>, C<sprintf>, |
2357
|
|
|
|
|
|
|
C<sprintfn>, C<wrap>, C<ANSI::*> (in L<Data::Unixish::ANSI> distribution), |
2358
|
|
|
|
|
|
|
(among others). |
2359
|
|
|
|
|
|
|
|
2360
|
|
|
|
|
|
|
=head1 CONDITIONAL STYLES |
2361
|
|
|
|
|
|
|
|
2362
|
|
|
|
|
|
|
As an alternative to setting styles for specific {column,row,cell}, you can also |
2363
|
|
|
|
|
|
|
create conditional styles. You specify a Perl code for the condition, then if |
2364
|
|
|
|
|
|
|
the condition evaluates to true, the corresponding styles are applied to the |
2365
|
|
|
|
|
|
|
corresponding {column,row,cell}. |
2366
|
|
|
|
|
|
|
|
2367
|
|
|
|
|
|
|
To add a conditional style, use the C<add_cond_{column,row,cell}_style> methods. |
2368
|
|
|
|
|
|
|
These methods accept condition code as its first argument and one or more styles |
2369
|
|
|
|
|
|
|
in the subsequent argument(s). For example: |
2370
|
|
|
|
|
|
|
|
2371
|
|
|
|
|
|
|
$t->add_cond_row_style(sub { $_ % 2 }, bgcolor=>'202020'); |
2372
|
|
|
|
|
|
|
|
2373
|
|
|
|
|
|
|
The above example will set row bgcolor for odd rows. You can add more |
2374
|
|
|
|
|
|
|
conditional styles: |
2375
|
|
|
|
|
|
|
|
2376
|
|
|
|
|
|
|
$t->add_cond_row_style(sub { $_ % 2 == 0 }, bgcolor=>'404040'); |
2377
|
|
|
|
|
|
|
|
2378
|
|
|
|
|
|
|
All the conditions will be evaluated and the applicable styles will be merged |
2379
|
|
|
|
|
|
|
together. For example, if we add a third conditional row style: |
2380
|
|
|
|
|
|
|
|
2381
|
|
|
|
|
|
|
$t->add_cond_row_style(sub { $_ % 10 == 0 }, height=>2, fgcolor=>'ffff00'); |
2382
|
|
|
|
|
|
|
|
2383
|
|
|
|
|
|
|
then every tenth row will have its height set to 2, fgcolor set to ffff00, and |
2384
|
|
|
|
|
|
|
bgcolor set to 404040 (from the second conditional). |
2385
|
|
|
|
|
|
|
|
2386
|
|
|
|
|
|
|
Condition coderef will be called with these arguments: |
2387
|
|
|
|
|
|
|
|
2388
|
|
|
|
|
|
|
($self, %args) |
2389
|
|
|
|
|
|
|
|
2390
|
|
|
|
|
|
|
Available keys in C<%args> for conditional column styles: C<col> (int, column |
2391
|
|
|
|
|
|
|
index), C<colname> (str, column name). Additionally, C<$_> will be set locally |
2392
|
|
|
|
|
|
|
to the column index. |
2393
|
|
|
|
|
|
|
|
2394
|
|
|
|
|
|
|
Available keys in C<%args> for conditional row styles: C<row> (int, row index), |
2395
|
|
|
|
|
|
|
C<row_data> (array). Additionally, C<$_> will be set locally to the row index. |
2396
|
|
|
|
|
|
|
|
2397
|
|
|
|
|
|
|
Available keys in C<%args> for conditional cell styles: C<content> (str), C<col> |
2398
|
|
|
|
|
|
|
(int, column index), C<row> (int, row index). Additionally, C<$_> will be set |
2399
|
|
|
|
|
|
|
locally to the cell content. |
2400
|
|
|
|
|
|
|
|
2401
|
|
|
|
|
|
|
Coderef should return boolean indicating whether style should be applied to a |
2402
|
|
|
|
|
|
|
particular column/row/cell. When returning a true value, coderef can also return |
2403
|
|
|
|
|
|
|
a hashref to return additional styles that will be merged/applied too. |
2404
|
|
|
|
|
|
|
|
2405
|
|
|
|
|
|
|
=head1 STYLE SETS |
2406
|
|
|
|
|
|
|
|
2407
|
|
|
|
|
|
|
A style set is just a collection of style settings that can be applied. |
2408
|
|
|
|
|
|
|
Organizing styles into style sets makes applying the styles simpler and more |
2409
|
|
|
|
|
|
|
reusable. |
2410
|
|
|
|
|
|
|
|
2411
|
|
|
|
|
|
|
More than one style sets can be applied. |
2412
|
|
|
|
|
|
|
|
2413
|
|
|
|
|
|
|
Style set module accepts arguments. |
2414
|
|
|
|
|
|
|
|
2415
|
|
|
|
|
|
|
For example, the L<Text::ANSITable::StyleSet::AltRow> style set defines this: |
2416
|
|
|
|
|
|
|
|
2417
|
|
|
|
|
|
|
has odd_bgcolor => (is => 'rw'); |
2418
|
|
|
|
|
|
|
has even_bgcolor => (is => 'rw'); |
2419
|
|
|
|
|
|
|
has odd_fgcolor => (is => 'rw'); |
2420
|
|
|
|
|
|
|
has even_fgcolor => (is => 'rw'); |
2421
|
|
|
|
|
|
|
|
2422
|
|
|
|
|
|
|
sub apply { |
2423
|
|
|
|
|
|
|
my ($self, $table) = @_; |
2424
|
|
|
|
|
|
|
|
2425
|
|
|
|
|
|
|
$table->add_cond_row_style(sub { |
2426
|
|
|
|
|
|
|
my ($t, %args) = @_; |
2427
|
|
|
|
|
|
|
my %styles; |
2428
|
|
|
|
|
|
|
if ($_ % 2) { |
2429
|
|
|
|
|
|
|
$styles{bgcolor} = $self->odd_bgcolor |
2430
|
|
|
|
|
|
|
if defined $self->odd_bgcolor; |
2431
|
|
|
|
|
|
|
$styles{fgcolor} = $self->odd_fgcolor |
2432
|
|
|
|
|
|
|
if defined $self->odd_bgcolor; |
2433
|
|
|
|
|
|
|
} else { |
2434
|
|
|
|
|
|
|
$styles{bgcolor} = $self->even_bgcolor |
2435
|
|
|
|
|
|
|
if defined $self->even_bgcolor; |
2436
|
|
|
|
|
|
|
$styles{fgcolor} = $self->even_fgcolor |
2437
|
|
|
|
|
|
|
if defined $self->even_bgcolor; |
2438
|
|
|
|
|
|
|
} |
2439
|
|
|
|
|
|
|
\%styles; |
2440
|
|
|
|
|
|
|
}); |
2441
|
|
|
|
|
|
|
} |
2442
|
|
|
|
|
|
|
|
2443
|
|
|
|
|
|
|
To apply this style set: |
2444
|
|
|
|
|
|
|
|
2445
|
|
|
|
|
|
|
$t->apply_style_set("AltRow", odd_bgcolor=>"003300", even_bgcolor=>"000000"); |
2446
|
|
|
|
|
|
|
|
2447
|
|
|
|
|
|
|
To create a new style set, create a module under C<Text::ANSITable::StyleSet::> |
2448
|
|
|
|
|
|
|
like the above example. Please see the other existing style set modules for more |
2449
|
|
|
|
|
|
|
examples. |
2450
|
|
|
|
|
|
|
|
2451
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
2452
|
|
|
|
|
|
|
|
2453
|
|
|
|
|
|
|
=head2 columns |
2454
|
|
|
|
|
|
|
|
2455
|
|
|
|
|
|
|
Array of str. Must be unique. |
2456
|
|
|
|
|
|
|
|
2457
|
|
|
|
|
|
|
Store column names. Note that when drawing, you can omit some columns, reorder |
2458
|
|
|
|
|
|
|
them, or display some more than once (see C<column_filter> attribute). |
2459
|
|
|
|
|
|
|
|
2460
|
|
|
|
|
|
|
Caveat: Since, for convenience, a column can be referred to using its name or |
2461
|
|
|
|
|
|
|
position, weird/unecxpected thing can happen if you name a column with a number |
2462
|
|
|
|
|
|
|
(e.g. 0, 1, 2, ...). So don't do that. |
2463
|
|
|
|
|
|
|
|
2464
|
|
|
|
|
|
|
=head2 rows => ARRAY OF ARRAY OF STR |
2465
|
|
|
|
|
|
|
|
2466
|
|
|
|
|
|
|
Store row data. You can set this attribute directly, or add rows incrementally |
2467
|
|
|
|
|
|
|
using C<add_row()> and C<add_rows()> methods. |
2468
|
|
|
|
|
|
|
|
2469
|
|
|
|
|
|
|
=head2 row_filter => CODE|ARRAY OF INT |
2470
|
|
|
|
|
|
|
|
2471
|
|
|
|
|
|
|
When drawing, only show rows that match this. Can be an array containing indices |
2472
|
|
|
|
|
|
|
of rows which should be shown, or a coderef which will be called for each row |
2473
|
|
|
|
|
|
|
with arguments C<< ($row, $rownum) >> and should return a bool value indicating |
2474
|
|
|
|
|
|
|
whether that row should be displayed. |
2475
|
|
|
|
|
|
|
|
2476
|
|
|
|
|
|
|
Internal note: During drawing, rows will be filtered and put into C<< |
2477
|
|
|
|
|
|
|
$t->{_draw}{frows} >>. |
2478
|
|
|
|
|
|
|
|
2479
|
|
|
|
|
|
|
=head2 column_filter => CODE|ARRAY OF STR |
2480
|
|
|
|
|
|
|
|
2481
|
|
|
|
|
|
|
When drawing, only show columns that match this. Can be an array containing |
2482
|
|
|
|
|
|
|
names of columns that should be displayed (column names can be in different |
2483
|
|
|
|
|
|
|
order or duplicate, column can also be referred to with its numeric index). Can |
2484
|
|
|
|
|
|
|
also be a coderef which will be called with C<< ($colname, $colnum) >> for |
2485
|
|
|
|
|
|
|
every column and should return a bool value indicating whether that column |
2486
|
|
|
|
|
|
|
should be displayed. The coderef version is more limited in that it cannot |
2487
|
|
|
|
|
|
|
reorder the columns or instruct for the same column to be displayed more than |
2488
|
|
|
|
|
|
|
once. |
2489
|
|
|
|
|
|
|
|
2490
|
|
|
|
|
|
|
Internal note: During drawing, column names will be filtered and put into C<< |
2491
|
|
|
|
|
|
|
$t->{_draw}{fcols} >>. |
2492
|
|
|
|
|
|
|
|
2493
|
|
|
|
|
|
|
=head2 column_wrap => BOOL |
2494
|
|
|
|
|
|
|
|
2495
|
|
|
|
|
|
|
Set column wrapping for all columns. Can be overriden by per-column C<wrap> |
2496
|
|
|
|
|
|
|
style. By default column wrapping will only be done for text columns and when |
2497
|
|
|
|
|
|
|
width is explicitly set to a positive value. |
2498
|
|
|
|
|
|
|
|
2499
|
|
|
|
|
|
|
=head2 use_color => BOOL |
2500
|
|
|
|
|
|
|
|
2501
|
|
|
|
|
|
|
Whether to output color. Default is taken from C<NO_COLOR> environment variable, |
2502
|
|
|
|
|
|
|
C<COLOR> environment variable, or detected via C<(-t STDOUT)>. If C<use_color> |
2503
|
|
|
|
|
|
|
is set to 0, an attempt to use a colored color theme (i.e. anything that is not |
2504
|
|
|
|
|
|
|
the C<no_color> theme) will result in an exception. |
2505
|
|
|
|
|
|
|
|
2506
|
|
|
|
|
|
|
(In the future, setting C<use_color> to 0 might opt the module to use |
2507
|
|
|
|
|
|
|
normal/plain string routines instead of the slower ta_* functions from |
2508
|
|
|
|
|
|
|
L<Text::ANSI::Util>; this also means that the module won't handle ANSI escape |
2509
|
|
|
|
|
|
|
codes in the content text.) |
2510
|
|
|
|
|
|
|
|
2511
|
|
|
|
|
|
|
=head2 color_depth => INT |
2512
|
|
|
|
|
|
|
|
2513
|
|
|
|
|
|
|
Terminal's color depth. Either 16, 256, or 2**24 (16777216). Default will be |
2514
|
|
|
|
|
|
|
retrieved from C<COLOR_DEPTH> environment or detected using L<Term::Detect>. |
2515
|
|
|
|
|
|
|
|
2516
|
|
|
|
|
|
|
=head2 use_box_chars => BOOL |
2517
|
|
|
|
|
|
|
|
2518
|
|
|
|
|
|
|
Whether to use box drawing characters. Drawing box drawing characters can be |
2519
|
|
|
|
|
|
|
problematic in some places because it uses ANSI escape codes to switch to (and |
2520
|
|
|
|
|
|
|
back from) line drawing mode (C<"\e(0"> and C<"\e(B">, respectively). |
2521
|
|
|
|
|
|
|
|
2522
|
|
|
|
|
|
|
Default is taken from C<BOX_CHARS> environment variable, or 1. If |
2523
|
|
|
|
|
|
|
C<use_box_chars> is set to 0, an attempt to use a border style that uses box |
2524
|
|
|
|
|
|
|
drawing chararacters will result in an exception. |
2525
|
|
|
|
|
|
|
|
2526
|
|
|
|
|
|
|
=head2 use_utf8 => BOOL |
2527
|
|
|
|
|
|
|
|
2528
|
|
|
|
|
|
|
Whether to use Unicode (UTF8) characters. Default is taken from C<UTF8> |
2529
|
|
|
|
|
|
|
environment variable, or detected using L<Term::Detect>, or guessed via L<LANG> |
2530
|
|
|
|
|
|
|
environment variable. If C<use_utf8> is set to 0, an attempt to select a border |
2531
|
|
|
|
|
|
|
style that uses Unicode characters will result in an exception. |
2532
|
|
|
|
|
|
|
|
2533
|
|
|
|
|
|
|
(In the future, setting C<use_utf8> to 0 might opt the module to use the |
2534
|
|
|
|
|
|
|
non-"mb_*" version of functions from L<Text::ANSI::Util>, e.g. C<ta_wrap()> |
2535
|
|
|
|
|
|
|
instead of C<ta_mbwrap()>, and so on). |
2536
|
|
|
|
|
|
|
|
2537
|
|
|
|
|
|
|
=head2 wide => BOOL |
2538
|
|
|
|
|
|
|
|
2539
|
|
|
|
|
|
|
Whether to support wide characters. The default is to check for the existence of |
2540
|
|
|
|
|
|
|
L<Text::ANSI::WideUtil> (an optional prereq). You can explicitly enable or |
2541
|
|
|
|
|
|
|
disable wide-character support here. |
2542
|
|
|
|
|
|
|
|
2543
|
|
|
|
|
|
|
=head2 border_style => STR |
2544
|
|
|
|
|
|
|
|
2545
|
|
|
|
|
|
|
Border style name to use. This is a module name in the |
2546
|
|
|
|
|
|
|
C<BorderStyle::Text::ANSITable::*>, C<BorderStyle::*>, or |
2547
|
|
|
|
|
|
|
C<BorderStyle::Text::ANSITable::OldCompat::*> namespace, without the prefix. |
2548
|
|
|
|
|
|
|
See the L<BorderStyle> specification on how to create a new border style. |
2549
|
|
|
|
|
|
|
|
2550
|
|
|
|
|
|
|
=head2 color_theme => STR |
2551
|
|
|
|
|
|
|
|
2552
|
|
|
|
|
|
|
Color theme name to use. This is a module name in the |
2553
|
|
|
|
|
|
|
C<ColorTheme::Text::ANSITable::*>, C<ColorTheme::*>, or |
2554
|
|
|
|
|
|
|
C<ColorTheme::Text::ANSITable::OldCompat::*> namespace, without the prefix. See |
2555
|
|
|
|
|
|
|
the L<ColorTheme> and an example existing color theme module like |
2556
|
|
|
|
|
|
|
L<ColorTheme::Text::ANSITable::Standard::Gradation> specification on how to |
2557
|
|
|
|
|
|
|
create a new border style. |
2558
|
|
|
|
|
|
|
|
2559
|
|
|
|
|
|
|
=head2 show_header => BOOL (default: 1) |
2560
|
|
|
|
|
|
|
|
2561
|
|
|
|
|
|
|
When drawing, whether to show header. |
2562
|
|
|
|
|
|
|
|
2563
|
|
|
|
|
|
|
=head2 show_row_separator => INT (default: 2) |
2564
|
|
|
|
|
|
|
|
2565
|
|
|
|
|
|
|
When drawing, whether to show separator lines between rows. The default (2) is |
2566
|
|
|
|
|
|
|
to only show separators drawn using C<add_row_separator()>. If you set this to |
2567
|
|
|
|
|
|
|
1, lines will be drawn after every data row. If you set this attribute to 0, no |
2568
|
|
|
|
|
|
|
lines will be drawn whatsoever. |
2569
|
|
|
|
|
|
|
|
2570
|
|
|
|
|
|
|
=head2 cell_width => INT |
2571
|
|
|
|
|
|
|
|
2572
|
|
|
|
|
|
|
Set width for all cells. Can be overriden by per-column C<width> style. |
2573
|
|
|
|
|
|
|
|
2574
|
|
|
|
|
|
|
=head2 cell_height => INT |
2575
|
|
|
|
|
|
|
|
2576
|
|
|
|
|
|
|
Set height for all cell. Can be overriden by per-row C<height> style. |
2577
|
|
|
|
|
|
|
|
2578
|
|
|
|
|
|
|
=head2 cell_align => STR |
2579
|
|
|
|
|
|
|
|
2580
|
|
|
|
|
|
|
Set (horizontal) alignment for all cells. Either C<left>, C<middle>, or |
2581
|
|
|
|
|
|
|
C<right>. Can be overriden by per-column/per-row/per-cell C<align> style. |
2582
|
|
|
|
|
|
|
|
2583
|
|
|
|
|
|
|
=head2 cell_valign => STR |
2584
|
|
|
|
|
|
|
|
2585
|
|
|
|
|
|
|
Set (horizontal) alignment for all cells. Either C<top>, C<middle>, or |
2586
|
|
|
|
|
|
|
C<bottom>. Can be overriden by per-column/per-row/per-cell C<align> style. |
2587
|
|
|
|
|
|
|
|
2588
|
|
|
|
|
|
|
=head2 cell_pad => INT |
2589
|
|
|
|
|
|
|
|
2590
|
|
|
|
|
|
|
Set (horizontal) padding for all cells. Can be overriden by per-column C<pad> |
2591
|
|
|
|
|
|
|
style. |
2592
|
|
|
|
|
|
|
|
2593
|
|
|
|
|
|
|
=head2 cell_lpad => INT |
2594
|
|
|
|
|
|
|
|
2595
|
|
|
|
|
|
|
Set left padding for all cells. Overrides the C<cell_pad> attribute. Can be |
2596
|
|
|
|
|
|
|
overriden by per-column C<lpad> style. |
2597
|
|
|
|
|
|
|
|
2598
|
|
|
|
|
|
|
=head2 cell_rpad => INT |
2599
|
|
|
|
|
|
|
|
2600
|
|
|
|
|
|
|
Set right padding for all cells. Overrides the C<cell_pad> attribute. Can be |
2601
|
|
|
|
|
|
|
overriden by per-column C<rpad> style. |
2602
|
|
|
|
|
|
|
|
2603
|
|
|
|
|
|
|
=head2 cell_vpad => INT |
2604
|
|
|
|
|
|
|
|
2605
|
|
|
|
|
|
|
Set vertical padding for all cells. Can be overriden by per-row C<vpad> style. |
2606
|
|
|
|
|
|
|
|
2607
|
|
|
|
|
|
|
=head2 cell_tpad => INT |
2608
|
|
|
|
|
|
|
|
2609
|
|
|
|
|
|
|
Set top padding for all cells. Overrides the C<cell_vpad> attribute. Can be |
2610
|
|
|
|
|
|
|
overriden by per-row C<tpad> style. |
2611
|
|
|
|
|
|
|
|
2612
|
|
|
|
|
|
|
=head2 cell_bpad => INT |
2613
|
|
|
|
|
|
|
|
2614
|
|
|
|
|
|
|
Set bottom padding for all cells. Overrides the C<cell_vpad> attribute. Can be |
2615
|
|
|
|
|
|
|
overriden by per-row C<bpad> style. |
2616
|
|
|
|
|
|
|
|
2617
|
|
|
|
|
|
|
=head2 cell_fgcolor => RGB|CODE |
2618
|
|
|
|
|
|
|
|
2619
|
|
|
|
|
|
|
Set foreground color for all cells. Value should be 6-hexdigit RGB. Can also be |
2620
|
|
|
|
|
|
|
a coderef that will receive %args (e.g. rownum, col_name, colnum) and should |
2621
|
|
|
|
|
|
|
return an RGB color. Can be overriden by per-cell C<fgcolor> style. |
2622
|
|
|
|
|
|
|
|
2623
|
|
|
|
|
|
|
=head2 cell_bgcolor => RGB|CODE |
2624
|
|
|
|
|
|
|
|
2625
|
|
|
|
|
|
|
Like C<cell_fgcolor> but for background color. |
2626
|
|
|
|
|
|
|
|
2627
|
|
|
|
|
|
|
=head2 header_fgcolor => RGB|CODE |
2628
|
|
|
|
|
|
|
|
2629
|
|
|
|
|
|
|
Set foreground color for all headers. Overrides C<cell_fgcolor> for headers. |
2630
|
|
|
|
|
|
|
Value should be a 6-hexdigit RGB. Can also be a coderef that will receive %args |
2631
|
|
|
|
|
|
|
(e.g. col_name, colnum) and should return an RGB color. |
2632
|
|
|
|
|
|
|
|
2633
|
|
|
|
|
|
|
=head2 header_bgcolor => RGB|CODE |
2634
|
|
|
|
|
|
|
|
2635
|
|
|
|
|
|
|
Like C<header_fgcolor> but for background color. |
2636
|
|
|
|
|
|
|
|
2637
|
|
|
|
|
|
|
=head2 header_align => STR |
2638
|
|
|
|
|
|
|
|
2639
|
|
|
|
|
|
|
=head2 header_valign => STR |
2640
|
|
|
|
|
|
|
|
2641
|
|
|
|
|
|
|
=head2 header_vpad => INT |
2642
|
|
|
|
|
|
|
|
2643
|
|
|
|
|
|
|
=head2 header_tpad => INT |
2644
|
|
|
|
|
|
|
|
2645
|
|
|
|
|
|
|
=head2 header_bpad => INT |
2646
|
|
|
|
|
|
|
|
2647
|
|
|
|
|
|
|
=head1 METHODS |
2648
|
|
|
|
|
|
|
|
2649
|
|
|
|
|
|
|
=head2 $t = Text::ANSITable->new(%attrs) => OBJ |
2650
|
|
|
|
|
|
|
|
2651
|
|
|
|
|
|
|
Constructor. |
2652
|
|
|
|
|
|
|
|
2653
|
|
|
|
|
|
|
=head2 $t->list_border_styles => LIST |
2654
|
|
|
|
|
|
|
|
2655
|
|
|
|
|
|
|
Return the names of available border styles. Border styles will be searched in |
2656
|
|
|
|
|
|
|
C<BorderStyle::*> modules. |
2657
|
|
|
|
|
|
|
|
2658
|
|
|
|
|
|
|
=head2 $t->list_color_themes => LIST |
2659
|
|
|
|
|
|
|
|
2660
|
|
|
|
|
|
|
Return the names of available color themes. Color themes will be searched in |
2661
|
|
|
|
|
|
|
C<ColorTheme::*> modules. |
2662
|
|
|
|
|
|
|
|
2663
|
|
|
|
|
|
|
=head2 $t->list_style_sets => LIST |
2664
|
|
|
|
|
|
|
|
2665
|
|
|
|
|
|
|
Return the names of available style sets. Style set names are retrieved by |
2666
|
|
|
|
|
|
|
listing modules under C<Text::ANSITable::StyleSet::*> namespace. |
2667
|
|
|
|
|
|
|
|
2668
|
|
|
|
|
|
|
=head2 $t->get_border_style($name) => HASH |
2669
|
|
|
|
|
|
|
|
2670
|
|
|
|
|
|
|
Can also be called as a static method: C<< |
2671
|
|
|
|
|
|
|
Text::ANSITable->get_border_style($name) >>. |
2672
|
|
|
|
|
|
|
|
2673
|
|
|
|
|
|
|
=head2 $t->get_color_theme($name) => HASH |
2674
|
|
|
|
|
|
|
|
2675
|
|
|
|
|
|
|
Can also be called as a static method: C<< |
2676
|
|
|
|
|
|
|
Text::ANSITable->get_color_theme($name) >>. |
2677
|
|
|
|
|
|
|
|
2678
|
|
|
|
|
|
|
=head2 $t->add_row(\@row[, \%styles]) => OBJ |
2679
|
|
|
|
|
|
|
|
2680
|
|
|
|
|
|
|
Add a row. Note that row data is not copied, only referenced. |
2681
|
|
|
|
|
|
|
|
2682
|
|
|
|
|
|
|
Can also add per-row styles (which can also be done using C<row_style()>). |
2683
|
|
|
|
|
|
|
|
2684
|
|
|
|
|
|
|
=head2 $t->add_rows(\@rows[, \%styles]) => OBJ |
2685
|
|
|
|
|
|
|
|
2686
|
|
|
|
|
|
|
Add multiple rows. Note that row data is not copied, only referenced. |
2687
|
|
|
|
|
|
|
|
2688
|
|
|
|
|
|
|
Can also add per-row styles (which can also be done using C<row_style()>). |
2689
|
|
|
|
|
|
|
|
2690
|
|
|
|
|
|
|
=head2 $t->add_row_separator() => OBJ |
2691
|
|
|
|
|
|
|
|
2692
|
|
|
|
|
|
|
Add a row separator line. |
2693
|
|
|
|
|
|
|
|
2694
|
|
|
|
|
|
|
=head2 $t->get_cell($rownum, $col) => VAL |
2695
|
|
|
|
|
|
|
|
2696
|
|
|
|
|
|
|
Get cell value at row #C<$rownum> (starts from zero) and column named/numbered |
2697
|
|
|
|
|
|
|
C<$col>. |
2698
|
|
|
|
|
|
|
|
2699
|
|
|
|
|
|
|
=head2 $t->set_cell($rownum, $col, $newval) => VAL |
2700
|
|
|
|
|
|
|
|
2701
|
|
|
|
|
|
|
Set cell value at row #C<$rownum> (starts from zero) and column named/numbered |
2702
|
|
|
|
|
|
|
C<$col>. Return old value. |
2703
|
|
|
|
|
|
|
|
2704
|
|
|
|
|
|
|
=head2 $t->get_column_style($col, $style) => VAL |
2705
|
|
|
|
|
|
|
|
2706
|
|
|
|
|
|
|
Get per-column style for column named/numbered C<$col>. |
2707
|
|
|
|
|
|
|
|
2708
|
|
|
|
|
|
|
=head2 $t->set_column_style($col, $style=>$val[, $style2=>$val2, ...]) |
2709
|
|
|
|
|
|
|
|
2710
|
|
|
|
|
|
|
Set per-column style(s) for column named/numbered C<$col>. Available values for |
2711
|
|
|
|
|
|
|
C<$style>: C<align>, C<valign>, C<pad>, C<lpad>, C<rpad>, C<width>, C<formats>, |
2712
|
|
|
|
|
|
|
C<fgcolor>, C<bgcolor>, C<type>, C<wrap>. |
2713
|
|
|
|
|
|
|
|
2714
|
|
|
|
|
|
|
=head2 $t->get_cond_column_styles => ARRAY |
2715
|
|
|
|
|
|
|
|
2716
|
|
|
|
|
|
|
Get all the conditional column styles set so far. |
2717
|
|
|
|
|
|
|
|
2718
|
|
|
|
|
|
|
=head2 $t->add_cond_column_style($cond, $style=>$val[, $style2=>$val2 ...]) |
2719
|
|
|
|
|
|
|
|
2720
|
|
|
|
|
|
|
Add a new conditional column style. See L</"CONDITIONAL STYLES"> for more |
2721
|
|
|
|
|
|
|
details on conditional style. |
2722
|
|
|
|
|
|
|
|
2723
|
|
|
|
|
|
|
=for comment | =head2 $t->clear_cond_column_styles | Clear all the conditional column styles. |
2724
|
|
|
|
|
|
|
|
2725
|
|
|
|
|
|
|
=head2 $t->get_eff_column_style($col, $style) => VAL |
2726
|
|
|
|
|
|
|
|
2727
|
|
|
|
|
|
|
Get "effective" column style named C<$style> for a particular column. Effective |
2728
|
|
|
|
|
|
|
column style is calculated from all the conditional column styles and the |
2729
|
|
|
|
|
|
|
per-column styles then merged together. This is the per-column style actually |
2730
|
|
|
|
|
|
|
applied. |
2731
|
|
|
|
|
|
|
|
2732
|
|
|
|
|
|
|
=head2 $t->get_row_style($rownum) => VAL |
2733
|
|
|
|
|
|
|
|
2734
|
|
|
|
|
|
|
Get per-row style for row numbered C<$rownum>. |
2735
|
|
|
|
|
|
|
|
2736
|
|
|
|
|
|
|
=head2 $t->set_row_style($rownum, $style=>$newval[, $style2=>$newval2, ...]) |
2737
|
|
|
|
|
|
|
|
2738
|
|
|
|
|
|
|
Set per-row style(s) for row numbered C<$rownum>. Available values for |
2739
|
|
|
|
|
|
|
C<$style>: C<align>, C<valign>, C<height>, C<vpad>, C<tpad>, C<bpad>, |
2740
|
|
|
|
|
|
|
C<fgcolor>, C<bgcolor>. |
2741
|
|
|
|
|
|
|
|
2742
|
|
|
|
|
|
|
=head2 $t->get_cond_row_styles => ARRAY |
2743
|
|
|
|
|
|
|
|
2744
|
|
|
|
|
|
|
Get all the conditional row styles set so far. |
2745
|
|
|
|
|
|
|
|
2746
|
|
|
|
|
|
|
=head2 $t->add_cond_row_style($cond, $style=>$val[, $style2=>$val2 ...]) |
2747
|
|
|
|
|
|
|
|
2748
|
|
|
|
|
|
|
Add a new conditional row style. See L</"CONDITIONAL STYLES"> for more details |
2749
|
|
|
|
|
|
|
on conditional style. |
2750
|
|
|
|
|
|
|
|
2751
|
|
|
|
|
|
|
=for comment | =head2 $t->clear_cond_row_styles | Clear all the conditional row styles. |
2752
|
|
|
|
|
|
|
|
2753
|
|
|
|
|
|
|
=head2 $t->get_eff_row_style($rownum, $style) => VAL |
2754
|
|
|
|
|
|
|
|
2755
|
|
|
|
|
|
|
Get "effective" row style named C<$style> for a particular row. Effective row |
2756
|
|
|
|
|
|
|
style is calculated from all the conditional row styles and the per-row styles |
2757
|
|
|
|
|
|
|
then merged together. This is the per-row style actually applied. |
2758
|
|
|
|
|
|
|
|
2759
|
|
|
|
|
|
|
=head2 $t->get_cell_style($rownum, $col, $style) => VAL |
2760
|
|
|
|
|
|
|
|
2761
|
|
|
|
|
|
|
Get per-cell style named C<$style> for a particular cell. Return undef if there |
2762
|
|
|
|
|
|
|
is no per-cell style with that name. |
2763
|
|
|
|
|
|
|
|
2764
|
|
|
|
|
|
|
=head2 $t->set_cell_style($rownum, $col, $style=>$newval[, $style2=>$newval2, ...]) |
2765
|
|
|
|
|
|
|
|
2766
|
|
|
|
|
|
|
Set per-cell style(s). Available values for C<$style>: C<align>, C<valign>, |
2767
|
|
|
|
|
|
|
C<formats>, C<fgcolor>, C<bgcolor>. |
2768
|
|
|
|
|
|
|
|
2769
|
|
|
|
|
|
|
=head2 $t->get_cond_cell_styles => ARRAY |
2770
|
|
|
|
|
|
|
|
2771
|
|
|
|
|
|
|
Get all the conditional cell styles set so far. |
2772
|
|
|
|
|
|
|
|
2773
|
|
|
|
|
|
|
=head2 $t->add_cond_cell_style($cond, $style=>$val[, $style2=>$val2 ...]) |
2774
|
|
|
|
|
|
|
|
2775
|
|
|
|
|
|
|
Add a new conditional cell style. See L</"CONDITIONAL STYLES"> for more details |
2776
|
|
|
|
|
|
|
on conditional style. |
2777
|
|
|
|
|
|
|
|
2778
|
|
|
|
|
|
|
=for comment | =head2 $t->clear_cond_cell_styles | Clear all the conditional cell styles. |
2779
|
|
|
|
|
|
|
|
2780
|
|
|
|
|
|
|
=head2 $t->get_eff_cell_style($rownum, $col, $style) => VAL |
2781
|
|
|
|
|
|
|
|
2782
|
|
|
|
|
|
|
Get "effective" cell style named C<$style> for a particular cell. Effective cell |
2783
|
|
|
|
|
|
|
style is calculated from all the conditional cell styles and the per-cell styles |
2784
|
|
|
|
|
|
|
then merged together. This is the per-cell style actually applied. |
2785
|
|
|
|
|
|
|
|
2786
|
|
|
|
|
|
|
=head2 $t->apply_style_set($name, %args) |
2787
|
|
|
|
|
|
|
|
2788
|
|
|
|
|
|
|
Apply a style set. See L</"STYLE SETS"> for more details. |
2789
|
|
|
|
|
|
|
|
2790
|
|
|
|
|
|
|
=head2 $t->draw => STR |
2791
|
|
|
|
|
|
|
|
2792
|
|
|
|
|
|
|
Render table. |
2793
|
|
|
|
|
|
|
|
2794
|
|
|
|
|
|
|
=head1 FAQ |
2795
|
|
|
|
|
|
|
|
2796
|
|
|
|
|
|
|
=head2 General |
2797
|
|
|
|
|
|
|
|
2798
|
|
|
|
|
|
|
=head3 I don't see my data! |
2799
|
|
|
|
|
|
|
|
2800
|
|
|
|
|
|
|
This might be caused by you not defining columns first, e.g.: |
2801
|
|
|
|
|
|
|
|
2802
|
|
|
|
|
|
|
my $t = Text::ANSITable->new; |
2803
|
|
|
|
|
|
|
$t->add_row([1,2,3]); |
2804
|
|
|
|
|
|
|
print $t->draw; |
2805
|
|
|
|
|
|
|
|
2806
|
|
|
|
|
|
|
You need to do this first before adding rows: |
2807
|
|
|
|
|
|
|
|
2808
|
|
|
|
|
|
|
$t->columns(["col1", "col2", "col3"]); |
2809
|
|
|
|
|
|
|
|
2810
|
|
|
|
|
|
|
=head3 All the rows are the same! |
2811
|
|
|
|
|
|
|
|
2812
|
|
|
|
|
|
|
my $t = Text::ANSITable->new; |
2813
|
|
|
|
|
|
|
$t->columns(["col"]); |
2814
|
|
|
|
|
|
|
my @row; |
2815
|
|
|
|
|
|
|
for (1..3) { |
2816
|
|
|
|
|
|
|
@row = ($_); |
2817
|
|
|
|
|
|
|
$t->add_row(\@row); |
2818
|
|
|
|
|
|
|
} |
2819
|
|
|
|
|
|
|
print $t->draw; |
2820
|
|
|
|
|
|
|
|
2821
|
|
|
|
|
|
|
will print: |
2822
|
|
|
|
|
|
|
|
2823
|
|
|
|
|
|
|
col |
2824
|
|
|
|
|
|
|
3 |
2825
|
|
|
|
|
|
|
3 |
2826
|
|
|
|
|
|
|
3 |
2827
|
|
|
|
|
|
|
|
2828
|
|
|
|
|
|
|
You need to add row in this way instead of adding the same reference everytime: |
2829
|
|
|
|
|
|
|
|
2830
|
|
|
|
|
|
|
$t->add_row([@row]); |
2831
|
|
|
|
|
|
|
|
2832
|
|
|
|
|
|
|
=head3 Output is too fancy! I just want to generate some plain (Text::ASCIITable-like) output to be copy-pasted to my document. |
2833
|
|
|
|
|
|
|
|
2834
|
|
|
|
|
|
|
$t->use_utf8(0); |
2835
|
|
|
|
|
|
|
$t->use_box_chars(0); |
2836
|
|
|
|
|
|
|
$t->use_color(0); |
2837
|
|
|
|
|
|
|
$t->border_style('ASCII::SingleLine'); |
2838
|
|
|
|
|
|
|
|
2839
|
|
|
|
|
|
|
and you're good to go. Alternatively you can set environment UTF8=0, |
2840
|
|
|
|
|
|
|
BOX_CHARS=0, COLOR=0, and ANSITABLE_BORDER_STYLE=ASCII::SingleLine. |
2841
|
|
|
|
|
|
|
|
2842
|
|
|
|
|
|
|
=head3 Why am I getting 'Wide character in print' warning? |
2843
|
|
|
|
|
|
|
|
2844
|
|
|
|
|
|
|
You are probably using a utf8 border style, and you haven't done something like |
2845
|
|
|
|
|
|
|
this to your output: |
2846
|
|
|
|
|
|
|
|
2847
|
|
|
|
|
|
|
binmode(STDOUT, ":utf8"); |
2848
|
|
|
|
|
|
|
|
2849
|
|
|
|
|
|
|
=head3 My table looks garbled when viewed through pager like B<less>! |
2850
|
|
|
|
|
|
|
|
2851
|
|
|
|
|
|
|
That's because B<less> by default escapes ANSI color and box_char codes. Try |
2852
|
|
|
|
|
|
|
using C<-R> option of B<less> to display ANSI color codes raw. |
2853
|
|
|
|
|
|
|
|
2854
|
|
|
|
|
|
|
Or, try not using colors and box_char border styles: |
2855
|
|
|
|
|
|
|
|
2856
|
|
|
|
|
|
|
$t->use_color(0); |
2857
|
|
|
|
|
|
|
$t->use_box_chars(0); |
2858
|
|
|
|
|
|
|
|
2859
|
|
|
|
|
|
|
Note that as of this writing, B<less -R> does not interpret box_char codes so |
2860
|
|
|
|
|
|
|
you'll need to avoid using box_char border styles if you want your output to |
2861
|
|
|
|
|
|
|
display properly under B<less>. |
2862
|
|
|
|
|
|
|
|
2863
|
|
|
|
|
|
|
=head3 How do I hide some columns/rows when drawing? |
2864
|
|
|
|
|
|
|
|
2865
|
|
|
|
|
|
|
Use the C<column_filter> and C<row_filter> attributes. For example, given this |
2866
|
|
|
|
|
|
|
table: |
2867
|
|
|
|
|
|
|
|
2868
|
|
|
|
|
|
|
my $t = Text::ANSITable->new; |
2869
|
|
|
|
|
|
|
$t->columns([qw/one two three/]); |
2870
|
|
|
|
|
|
|
$t->add_row([$_, $_, $_]) for 1..10; |
2871
|
|
|
|
|
|
|
|
2872
|
|
|
|
|
|
|
Doing this: |
2873
|
|
|
|
|
|
|
|
2874
|
|
|
|
|
|
|
$t->row_filter([0, 1, 4]); |
2875
|
|
|
|
|
|
|
print $t->draw; |
2876
|
|
|
|
|
|
|
|
2877
|
|
|
|
|
|
|
will show: |
2878
|
|
|
|
|
|
|
|
2879
|
|
|
|
|
|
|
one | two | three |
2880
|
|
|
|
|
|
|
-----+-----+------- |
2881
|
|
|
|
|
|
|
1 | 1 | 1 |
2882
|
|
|
|
|
|
|
2 | 2 | 2 |
2883
|
|
|
|
|
|
|
5 | 5 | 5 |
2884
|
|
|
|
|
|
|
|
2885
|
|
|
|
|
|
|
Doing this: |
2886
|
|
|
|
|
|
|
|
2887
|
|
|
|
|
|
|
$t->row_filter(sub { my ($row, $idx) = @_; $row->[0] % 2 } |
2888
|
|
|
|
|
|
|
|
2889
|
|
|
|
|
|
|
will display: |
2890
|
|
|
|
|
|
|
|
2891
|
|
|
|
|
|
|
one | two | three |
2892
|
|
|
|
|
|
|
-----+-----+------- |
2893
|
|
|
|
|
|
|
1 | 1 | 1 |
2894
|
|
|
|
|
|
|
3 | 3 | 3 |
2895
|
|
|
|
|
|
|
5 | 5 | 5 |
2896
|
|
|
|
|
|
|
7 | 7 | 7 |
2897
|
|
|
|
|
|
|
9 | 9 | 9 |
2898
|
|
|
|
|
|
|
|
2899
|
|
|
|
|
|
|
Doing this: |
2900
|
|
|
|
|
|
|
|
2901
|
|
|
|
|
|
|
$t->column_filter([qw/two one 0/]); |
2902
|
|
|
|
|
|
|
|
2903
|
|
|
|
|
|
|
will display: |
2904
|
|
|
|
|
|
|
|
2905
|
|
|
|
|
|
|
two | one | one |
2906
|
|
|
|
|
|
|
-----+-----+----- |
2907
|
|
|
|
|
|
|
1 | 1 | 1 |
2908
|
|
|
|
|
|
|
2 | 2 | 2 |
2909
|
|
|
|
|
|
|
3 | 3 | 3 |
2910
|
|
|
|
|
|
|
4 | 4 | 4 |
2911
|
|
|
|
|
|
|
5 | 5 | 5 |
2912
|
|
|
|
|
|
|
6 | 6 | 6 |
2913
|
|
|
|
|
|
|
7 | 7 | 7 |
2914
|
|
|
|
|
|
|
8 | 8 | 8 |
2915
|
|
|
|
|
|
|
9 | 9 | 9 |
2916
|
|
|
|
|
|
|
10 | 10 | 10 |
2917
|
|
|
|
|
|
|
|
2918
|
|
|
|
|
|
|
Doing this: |
2919
|
|
|
|
|
|
|
|
2920
|
|
|
|
|
|
|
$t->column_filter(sub { my ($colname, $idx) = @_; $colname =~ /t/ }); |
2921
|
|
|
|
|
|
|
|
2922
|
|
|
|
|
|
|
will display: |
2923
|
|
|
|
|
|
|
|
2924
|
|
|
|
|
|
|
two | three |
2925
|
|
|
|
|
|
|
-----+------- |
2926
|
|
|
|
|
|
|
1 | 1 |
2927
|
|
|
|
|
|
|
2 | 2 |
2928
|
|
|
|
|
|
|
3 | 3 |
2929
|
|
|
|
|
|
|
4 | 4 |
2930
|
|
|
|
|
|
|
5 | 5 |
2931
|
|
|
|
|
|
|
6 | 6 |
2932
|
|
|
|
|
|
|
7 | 7 |
2933
|
|
|
|
|
|
|
8 | 8 |
2934
|
|
|
|
|
|
|
9 | 9 |
2935
|
|
|
|
|
|
|
10 | 10 |
2936
|
|
|
|
|
|
|
|
2937
|
|
|
|
|
|
|
=head2 Formatting data |
2938
|
|
|
|
|
|
|
|
2939
|
|
|
|
|
|
|
=head3 How do I format data? |
2940
|
|
|
|
|
|
|
|
2941
|
|
|
|
|
|
|
Use the C<formats> per-column style or per-cell style. For example: |
2942
|
|
|
|
|
|
|
|
2943
|
|
|
|
|
|
|
$t->set_column_style('available', formats => [[bool=>{style=>'check_cross'}], |
2944
|
|
|
|
|
|
|
[centerpad=>{width=>10}]]); |
2945
|
|
|
|
|
|
|
$t->set_column_style('amount' , formats => [[num=>{decimal_digits=>2}]]); |
2946
|
|
|
|
|
|
|
$t->set_column_style('size' , formats => [[num=>{style=>'kilo'}]]); |
2947
|
|
|
|
|
|
|
|
2948
|
|
|
|
|
|
|
See L<Data::Unixish::Apply> and L<Data::Unixish> for more details on the |
2949
|
|
|
|
|
|
|
available formatting functions. |
2950
|
|
|
|
|
|
|
|
2951
|
|
|
|
|
|
|
=head3 How does the module determine column data type? |
2952
|
|
|
|
|
|
|
|
2953
|
|
|
|
|
|
|
Currently: if column name has the word C<date> or C<time> in it, the column is |
2954
|
|
|
|
|
|
|
assumed to contain B<date> data. If column name has C<?> in it, the column is |
2955
|
|
|
|
|
|
|
assumed to be B<bool>. If a column contains only numbers (or undefs), it is |
2956
|
|
|
|
|
|
|
B<num>. Otherwise, it is B<str>. |
2957
|
|
|
|
|
|
|
|
2958
|
|
|
|
|
|
|
=head3 How does the module format data types? |
2959
|
|
|
|
|
|
|
|
2960
|
|
|
|
|
|
|
Currently: B<num> will be right aligned and applied C<num_data> color (cyan in |
2961
|
|
|
|
|
|
|
the default theme). B<date> will be centered and applied C<date_data> color |
2962
|
|
|
|
|
|
|
(gold in the default theme). B<bool> will be centered and formatted as |
2963
|
|
|
|
|
|
|
check/cross symbol and applied C<bool_data> color (red/green depending on |
2964
|
|
|
|
|
|
|
whether the data is false/true). B<str> will be applied C<str_data> color (no |
2965
|
|
|
|
|
|
|
color in the default theme). |
2966
|
|
|
|
|
|
|
|
2967
|
|
|
|
|
|
|
Other color themes might use different colors. |
2968
|
|
|
|
|
|
|
|
2969
|
|
|
|
|
|
|
=head3 How do I force column to be of a certain data type? |
2970
|
|
|
|
|
|
|
|
2971
|
|
|
|
|
|
|
For example, you have a column named C<deleted> but want to display it as |
2972
|
|
|
|
|
|
|
B<bool>. You can do: |
2973
|
|
|
|
|
|
|
|
2974
|
|
|
|
|
|
|
$t->set_column_style(deleted => type => 'bool'); |
2975
|
|
|
|
|
|
|
|
2976
|
|
|
|
|
|
|
=head3 How do I wrap long text? |
2977
|
|
|
|
|
|
|
|
2978
|
|
|
|
|
|
|
The C<wrap> dux function can be used to wrap text (see: L<Data::Unixish::wrap>). |
2979
|
|
|
|
|
|
|
You'll want to set C<ansi> and C<mb> both to 1 to handle ANSI escape codes and |
2980
|
|
|
|
|
|
|
wide characters in your text (unless you are sure that your text does not |
2981
|
|
|
|
|
|
|
contain those): |
2982
|
|
|
|
|
|
|
|
2983
|
|
|
|
|
|
|
$t->set_column_style('description', formats=>[[wrap => {width=>60, ansi=>1, mb=>1}]]); |
2984
|
|
|
|
|
|
|
|
2985
|
|
|
|
|
|
|
=head3 How do I highlight text with color? |
2986
|
|
|
|
|
|
|
|
2987
|
|
|
|
|
|
|
The C<ansi::highlight> dux function can be used to highlight text (see: |
2988
|
|
|
|
|
|
|
L<Data::Unixish::ANSI::highlight>). |
2989
|
|
|
|
|
|
|
|
2990
|
|
|
|
|
|
|
$t->set_column_style(2, formats => [[highlight => {pattern=>$pat}]]); |
2991
|
|
|
|
|
|
|
|
2992
|
|
|
|
|
|
|
=head3 I want to change the default bool cross/check sign representation! |
2993
|
|
|
|
|
|
|
|
2994
|
|
|
|
|
|
|
By default, bool columns are shown as cross/check sign. This can be changed, |
2995
|
|
|
|
|
|
|
e.g.: |
2996
|
|
|
|
|
|
|
|
2997
|
|
|
|
|
|
|
$t->set_column_style($colname, type => 'bool', |
2998
|
|
|
|
|
|
|
formats => [[bool => {style=>"Y_N"}]]); |
2999
|
|
|
|
|
|
|
|
3000
|
|
|
|
|
|
|
See L<Data::Unixish::bool> for more details. |
3001
|
|
|
|
|
|
|
|
3002
|
|
|
|
|
|
|
=head3 How do I do conditional cell formatting? |
3003
|
|
|
|
|
|
|
|
3004
|
|
|
|
|
|
|
There are several ways. |
3005
|
|
|
|
|
|
|
|
3006
|
|
|
|
|
|
|
First, you can use the C<cond> dux function through C<formats> style. For |
3007
|
|
|
|
|
|
|
example, if the cell contains the string "Cuti", you want to color the cell |
3008
|
|
|
|
|
|
|
yellow. Otherwise, you want to color the cell red: |
3009
|
|
|
|
|
|
|
|
3010
|
|
|
|
|
|
|
$t->set_column_style($colname, formats => [ |
3011
|
|
|
|
|
|
|
[cond => { |
3012
|
|
|
|
|
|
|
if => sub { $_ =~ /Cuti/ }, |
3013
|
|
|
|
|
|
|
then => ["ansi::color", {color=>"yellow"}], |
3014
|
|
|
|
|
|
|
else => ["ansi::color", {color=>"red"}], |
3015
|
|
|
|
|
|
|
}] |
3016
|
|
|
|
|
|
|
]); |
3017
|
|
|
|
|
|
|
|
3018
|
|
|
|
|
|
|
Another way is to use the C<add_cond_{cell,row,column}> methods. See |
3019
|
|
|
|
|
|
|
L</"CONDITIONAL STYLES"> for more details. An example: |
3020
|
|
|
|
|
|
|
|
3021
|
|
|
|
|
|
|
$t->add_cond_row_style(sub { |
3022
|
|
|
|
|
|
|
my %args = @_; |
3023
|
|
|
|
|
|
|
$args{colname} =~ /Cuti/ ? {bgcolor=>"ffff00"} : {bgcolor=>"ff0000"}; |
3024
|
|
|
|
|
|
|
}); |
3025
|
|
|
|
|
|
|
|
3026
|
|
|
|
|
|
|
And another way is to use (or create) style set, which is basically a packaging |
3027
|
|
|
|
|
|
|
of the above ways. An advantage of using style set is, because you do not |
3028
|
|
|
|
|
|
|
specify coderef directly, you can specify it from the environment variable. See |
3029
|
|
|
|
|
|
|
L</"STYLE SETS"> for more details. |
3030
|
|
|
|
|
|
|
|
3031
|
|
|
|
|
|
|
=head2 Border |
3032
|
|
|
|
|
|
|
|
3033
|
|
|
|
|
|
|
=head3 How to hide borders? |
3034
|
|
|
|
|
|
|
|
3035
|
|
|
|
|
|
|
There is currently no C<show_border> attribute. Choose border styles like |
3036
|
|
|
|
|
|
|
C<ASCII::Space>, C<ASCII::None>, C<UTF8::None>: |
3037
|
|
|
|
|
|
|
|
3038
|
|
|
|
|
|
|
$t->border_style("UTF8::None"); |
3039
|
|
|
|
|
|
|
|
3040
|
|
|
|
|
|
|
=head3 Why are there 'ASCII::None' as well 'UTF8::None' and 'BoxChar::None' border styles? |
3041
|
|
|
|
|
|
|
|
3042
|
|
|
|
|
|
|
Because of the row separator, that can still be drawn if C<add_row_separator()> |
3043
|
|
|
|
|
|
|
is used. See next question. |
3044
|
|
|
|
|
|
|
|
3045
|
|
|
|
|
|
|
=head3 I want to hide borders, and I do not want row separators to be shown! |
3046
|
|
|
|
|
|
|
|
3047
|
|
|
|
|
|
|
The default is for separator lines to be drawn if drawn using |
3048
|
|
|
|
|
|
|
C<add_row_separator()>, e.g.: |
3049
|
|
|
|
|
|
|
|
3050
|
|
|
|
|
|
|
$t->add_row(['row1']); |
3051
|
|
|
|
|
|
|
$t->add_row(['row2']); |
3052
|
|
|
|
|
|
|
$t->add_row_separator; |
3053
|
|
|
|
|
|
|
$t->add_row(['row3']); |
3054
|
|
|
|
|
|
|
|
3055
|
|
|
|
|
|
|
The result will be: |
3056
|
|
|
|
|
|
|
|
3057
|
|
|
|
|
|
|
row1 |
3058
|
|
|
|
|
|
|
row2 |
3059
|
|
|
|
|
|
|
-------- |
3060
|
|
|
|
|
|
|
row3 |
3061
|
|
|
|
|
|
|
|
3062
|
|
|
|
|
|
|
However, if you set C<show_row_separator> to 0, no separator lines will be drawn |
3063
|
|
|
|
|
|
|
whatsoever: |
3064
|
|
|
|
|
|
|
|
3065
|
|
|
|
|
|
|
row1 |
3066
|
|
|
|
|
|
|
row2 |
3067
|
|
|
|
|
|
|
row3 |
3068
|
|
|
|
|
|
|
|
3069
|
|
|
|
|
|
|
=head3 I want to separate each row with a line! |
3070
|
|
|
|
|
|
|
|
3071
|
|
|
|
|
|
|
Set C<show_row_separator> to 1, or alternatively, set |
3072
|
|
|
|
|
|
|
C<ANSITABLE_STYLE='{"show_row_separator":1}>. |
3073
|
|
|
|
|
|
|
|
3074
|
|
|
|
|
|
|
=head2 Color |
3075
|
|
|
|
|
|
|
|
3076
|
|
|
|
|
|
|
=head3 How to disable colors? |
3077
|
|
|
|
|
|
|
|
3078
|
|
|
|
|
|
|
Set C<use_color> attribute or C<COLOR> environment to 0. |
3079
|
|
|
|
|
|
|
|
3080
|
|
|
|
|
|
|
=head3 How to specify colors using names (e.g. red, 'navy blue') instead of RGB? |
3081
|
|
|
|
|
|
|
|
3082
|
|
|
|
|
|
|
Use modules like L<Graphics::ColorNames>. |
3083
|
|
|
|
|
|
|
|
3084
|
|
|
|
|
|
|
=head3 I'm not seeing colors when output is piped (e.g. to a pager)! |
3085
|
|
|
|
|
|
|
|
3086
|
|
|
|
|
|
|
The default is to disable colors when (-t STDOUT) is false. You can force-enable |
3087
|
|
|
|
|
|
|
colors by setting C<use_color> attribute or C<COLOR> environment to 1. |
3088
|
|
|
|
|
|
|
|
3089
|
|
|
|
|
|
|
=head3 How to enable 256 colors? I'm seeing only 16 colors. |
3090
|
|
|
|
|
|
|
|
3091
|
|
|
|
|
|
|
Use terminal emulators that support 256 colors, e.g. Konsole, xterm, |
3092
|
|
|
|
|
|
|
gnome-terminal, PuTTY/pterm (but the last one has minimal Unicode support). |
3093
|
|
|
|
|
|
|
Better yet, use Konsole or Konsole-based emulators which supports 24bit colors. |
3094
|
|
|
|
|
|
|
|
3095
|
|
|
|
|
|
|
=head3 How to enable 24bit colors (true color)? |
3096
|
|
|
|
|
|
|
|
3097
|
|
|
|
|
|
|
Currently only B<Konsole> and the Konsole-based B<Yakuake> terminal emulator |
3098
|
|
|
|
|
|
|
software support 24bit colors. |
3099
|
|
|
|
|
|
|
|
3100
|
|
|
|
|
|
|
=head3 How to force lower color depth? (e.g. I use Konsole but want 16 colors) |
3101
|
|
|
|
|
|
|
|
3102
|
|
|
|
|
|
|
Set C<COLOR_DEPTH> to 16. |
3103
|
|
|
|
|
|
|
|
3104
|
|
|
|
|
|
|
=head3 How to change border gradation color? |
3105
|
|
|
|
|
|
|
|
3106
|
|
|
|
|
|
|
The default color theme applies vertical color gradation to borders from white |
3107
|
|
|
|
|
|
|
(ffffff) to gray (444444). To change this, set C<border1> and C<border2> theme |
3108
|
|
|
|
|
|
|
arguments: |
3109
|
|
|
|
|
|
|
|
3110
|
|
|
|
|
|
|
$t->color_theme_args({border1=>'ff0000', border2=>'00ff00'}); # red to green |
3111
|
|
|
|
|
|
|
|
3112
|
|
|
|
|
|
|
=head3 I'm using terminal emulator with white background, the texts are not very visible! |
3113
|
|
|
|
|
|
|
|
3114
|
|
|
|
|
|
|
Try using the "*_whitebg" themes, as the other themes are geared towards |
3115
|
|
|
|
|
|
|
terminal emulators with black background. |
3116
|
|
|
|
|
|
|
|
3117
|
|
|
|
|
|
|
=head3 How to set different background colors for odd/even rows? |
3118
|
|
|
|
|
|
|
|
3119
|
|
|
|
|
|
|
Aside from doing C<< $t->set_row_style($rownum, bgcolor=>...) >> for each row, |
3120
|
|
|
|
|
|
|
you can also do this: |
3121
|
|
|
|
|
|
|
|
3122
|
|
|
|
|
|
|
$t->cell_bgcolor(sub { my ($self, %args) = @_; $args{rownum} % 2 ? '202020' : undef }); |
3123
|
|
|
|
|
|
|
|
3124
|
|
|
|
|
|
|
Or, you can use conditional row styles: |
3125
|
|
|
|
|
|
|
|
3126
|
|
|
|
|
|
|
$t->add_cond_row_style(sub { $_ % 2 }, {bgcolor=>'202020'}); |
3127
|
|
|
|
|
|
|
|
3128
|
|
|
|
|
|
|
Or, you can use the L<Text::ANSITable::StyleSet::AltRow> style set: |
3129
|
|
|
|
|
|
|
|
3130
|
|
|
|
|
|
|
$t->apply_style_set(AltRow => {even_bgcolor=>'202020'}); |
3131
|
|
|
|
|
|
|
|
3132
|
|
|
|
|
|
|
=head1 ENVIRONMENT |
3133
|
|
|
|
|
|
|
|
3134
|
|
|
|
|
|
|
=head2 COLOR => BOOL |
3135
|
|
|
|
|
|
|
|
3136
|
|
|
|
|
|
|
Can be used to set default value for the C<color> attribute. |
3137
|
|
|
|
|
|
|
|
3138
|
|
|
|
|
|
|
=head2 COLOR_DEPTH => INT |
3139
|
|
|
|
|
|
|
|
3140
|
|
|
|
|
|
|
Can be used to set default value for the C<color_depth> attribute. |
3141
|
|
|
|
|
|
|
|
3142
|
|
|
|
|
|
|
=head2 BOX_CHARS => BOOL |
3143
|
|
|
|
|
|
|
|
3144
|
|
|
|
|
|
|
Can be used to set default value for the C<box_chars> attribute. |
3145
|
|
|
|
|
|
|
|
3146
|
|
|
|
|
|
|
=head2 UTF8 => BOOL |
3147
|
|
|
|
|
|
|
|
3148
|
|
|
|
|
|
|
Can be used to set default value for the C<utf8> attribute. |
3149
|
|
|
|
|
|
|
|
3150
|
|
|
|
|
|
|
=head2 COLUMNS => INT |
3151
|
|
|
|
|
|
|
|
3152
|
|
|
|
|
|
|
Can be used to override terminal width detection. |
3153
|
|
|
|
|
|
|
|
3154
|
|
|
|
|
|
|
=head2 ANSITABLE_BORDER_STYLE => STR |
3155
|
|
|
|
|
|
|
|
3156
|
|
|
|
|
|
|
Can be used to set default value for C<border_style> attribute. Takes precedence |
3157
|
|
|
|
|
|
|
over L<BORDER_STYLE>. |
3158
|
|
|
|
|
|
|
|
3159
|
|
|
|
|
|
|
=head2 BORDER_STYLE => STR |
3160
|
|
|
|
|
|
|
|
3161
|
|
|
|
|
|
|
Can be used to set default value for C<border_style> attribute. See also |
3162
|
|
|
|
|
|
|
C<ANSITABLE_BORDER_STYLE>. |
3163
|
|
|
|
|
|
|
|
3164
|
|
|
|
|
|
|
=head2 ANSITABLE_COLOR_THEME => STR |
3165
|
|
|
|
|
|
|
|
3166
|
|
|
|
|
|
|
Can be used to set default value for C<border_style> attribute. |
3167
|
|
|
|
|
|
|
|
3168
|
|
|
|
|
|
|
=head2 ANSITABLE_STYLE => str(json) |
3169
|
|
|
|
|
|
|
|
3170
|
|
|
|
|
|
|
Can be used to set table's most attributes. Value should be a JSON-encoded hash |
3171
|
|
|
|
|
|
|
of C<< attr => val >> pairs. Example: |
3172
|
|
|
|
|
|
|
|
3173
|
|
|
|
|
|
|
% ANSITABLE_STYLE='{"show_row_separator":1}' ansitable-list-border-styles |
3174
|
|
|
|
|
|
|
|
3175
|
|
|
|
|
|
|
will display table with row separator lines after every row. |
3176
|
|
|
|
|
|
|
|
3177
|
|
|
|
|
|
|
=head2 WRAP => BOOL |
3178
|
|
|
|
|
|
|
|
3179
|
|
|
|
|
|
|
Can be used to set default value for the C<wrap> column style. |
3180
|
|
|
|
|
|
|
|
3181
|
|
|
|
|
|
|
=head2 ANSITABLE_COLUMN_STYLES => str(json) |
3182
|
|
|
|
|
|
|
|
3183
|
|
|
|
|
|
|
Can be used to set per-column styles. Interpreted right before draw(). Value |
3184
|
|
|
|
|
|
|
should be a JSON-encoded hash of C<< col => {style => val, ...} >> pairs. |
3185
|
|
|
|
|
|
|
Example: |
3186
|
|
|
|
|
|
|
|
3187
|
|
|
|
|
|
|
% ANSITABLE_COLUMN_STYLES='{"2":{"type":"num"},"3":{"type":"str"}}' ansitable-list-border-styles |
3188
|
|
|
|
|
|
|
|
3189
|
|
|
|
|
|
|
will display the bool columns as num and str instead. |
3190
|
|
|
|
|
|
|
|
3191
|
|
|
|
|
|
|
=head2 ANSITABLE_ROW_STYLES => str(json) |
3192
|
|
|
|
|
|
|
|
3193
|
|
|
|
|
|
|
Can be used to set per-row styles. Interpreted right before draw(). Value should |
3194
|
|
|
|
|
|
|
be a JSON-encoded a hash of C<< rownum => {style => val, ...} >> pairs. |
3195
|
|
|
|
|
|
|
Example: |
3196
|
|
|
|
|
|
|
|
3197
|
|
|
|
|
|
|
% ANSITABLE_ROW_STYLES='{"0":{"bgcolor":"000080","vpad":1}}' ansitable-list-border-styles |
3198
|
|
|
|
|
|
|
|
3199
|
|
|
|
|
|
|
will display the first row with blue background color and taller height. |
3200
|
|
|
|
|
|
|
|
3201
|
|
|
|
|
|
|
=head2 ANSITABLE_CELL_STYLES => str(json) |
3202
|
|
|
|
|
|
|
|
3203
|
|
|
|
|
|
|
Can be used to set per-cell styles. Interpreted right before draw(). Value |
3204
|
|
|
|
|
|
|
should be a JSON-encoded a hash of C<< "rownum,col" => {style => val, ...} >> |
3205
|
|
|
|
|
|
|
pairs. Example: |
3206
|
|
|
|
|
|
|
|
3207
|
|
|
|
|
|
|
% ANSITABLE_CELL_STYLES='{"1,1":{"bgcolor":"008000"}}' ansitable-list-border-styles |
3208
|
|
|
|
|
|
|
|
3209
|
|
|
|
|
|
|
will display the second-on-the-left, second-on-the-top cell with green |
3210
|
|
|
|
|
|
|
background color. |
3211
|
|
|
|
|
|
|
|
3212
|
|
|
|
|
|
|
=head2 ANSITABLE_STYLE_SETS => str(json) |
3213
|
|
|
|
|
|
|
|
3214
|
|
|
|
|
|
|
Can be used to apply style sets. Value should be a JSON-encoded array. Each |
3215
|
|
|
|
|
|
|
element must be a style set name or a 2-element array containing style set name |
3216
|
|
|
|
|
|
|
and its arguments (C<< [$name, \%args] >>). Example: |
3217
|
|
|
|
|
|
|
|
3218
|
|
|
|
|
|
|
% ANSITABLE_STYLE_SETS='[["AltRow",{"odd_bgcolor":"003300"}]]' |
3219
|
|
|
|
|
|
|
|
3220
|
|
|
|
|
|
|
will display table with row separator lines after every row. |
3221
|
|
|
|
|
|
|
|
3222
|
|
|
|
|
|
|
=head1 HOMEPAGE |
3223
|
|
|
|
|
|
|
|
3224
|
|
|
|
|
|
|
Please visit the project's homepage at L<https://metacpan.org/release/Text-ANSITable>. |
3225
|
|
|
|
|
|
|
|
3226
|
|
|
|
|
|
|
=head1 SOURCE |
3227
|
|
|
|
|
|
|
|
3228
|
|
|
|
|
|
|
Source repository is at L<https://github.com/perlancar/perl-Text-ANSITable>. |
3229
|
|
|
|
|
|
|
|
3230
|
|
|
|
|
|
|
=head1 SEE ALSO |
3231
|
|
|
|
|
|
|
|
3232
|
|
|
|
|
|
|
=head2 Border styles |
3233
|
|
|
|
|
|
|
|
3234
|
|
|
|
|
|
|
For collections of border styles, search for C<BorderStyle::*> modules. |
3235
|
|
|
|
|
|
|
|
3236
|
|
|
|
|
|
|
=head2 Color themes |
3237
|
|
|
|
|
|
|
|
3238
|
|
|
|
|
|
|
For collections of color themes, search for C<ColorTheme::*> modules. |
3239
|
|
|
|
|
|
|
|
3240
|
|
|
|
|
|
|
=head2 Other table-formatting CPAN modules |
3241
|
|
|
|
|
|
|
|
3242
|
|
|
|
|
|
|
L<Text::ASCIITable> is one of the most popular table-formatting modules on CPAN. |
3243
|
|
|
|
|
|
|
There are a couple of "extensions" for Text::ASCIITable: |
3244
|
|
|
|
|
|
|
L<Text::ASCIITable::TW>, L<Text::ASCIITable::Wrap>; Text::ANSITable can be an |
3245
|
|
|
|
|
|
|
alternative for all those modules since it can already handle wide-characters as |
3246
|
|
|
|
|
|
|
well as multiline text in cells. |
3247
|
|
|
|
|
|
|
|
3248
|
|
|
|
|
|
|
L<Text::TabularDisplay> |
3249
|
|
|
|
|
|
|
|
3250
|
|
|
|
|
|
|
L<Text::Table> |
3251
|
|
|
|
|
|
|
|
3252
|
|
|
|
|
|
|
L<Text::SimpleTable> |
3253
|
|
|
|
|
|
|
|
3254
|
|
|
|
|
|
|
L<Text::UnicodeTable::Simple> |
3255
|
|
|
|
|
|
|
|
3256
|
|
|
|
|
|
|
L<Table::Simple> |
3257
|
|
|
|
|
|
|
|
3258
|
|
|
|
|
|
|
L<Acme::CPANModules::TextTable> catalogs text table modules. |
3259
|
|
|
|
|
|
|
|
3260
|
|
|
|
|
|
|
=head2 Front-ends |
3261
|
|
|
|
|
|
|
|
3262
|
|
|
|
|
|
|
L<Text::Table::Any> and its CLI L<texttable> can use Text::ANSITable as one of |
3263
|
|
|
|
|
|
|
the backends. |
3264
|
|
|
|
|
|
|
|
3265
|
|
|
|
|
|
|
=head2 Other related modules |
3266
|
|
|
|
|
|
|
|
3267
|
|
|
|
|
|
|
L<App::TextTableUtils> includes utilities like L<csv2ansitable> or |
3268
|
|
|
|
|
|
|
L<json2ansitable> which can convert a CSV or array-of-array structure to a table |
3269
|
|
|
|
|
|
|
rendered using Text::ANSITable. |
3270
|
|
|
|
|
|
|
|
3271
|
|
|
|
|
|
|
=head2 Other |
3272
|
|
|
|
|
|
|
|
3273
|
|
|
|
|
|
|
Unix command B<column> (e.g. C<column -t>). |
3274
|
|
|
|
|
|
|
|
3275
|
|
|
|
|
|
|
=head1 AUTHOR |
3276
|
|
|
|
|
|
|
|
3277
|
|
|
|
|
|
|
perlancar <perlancar@cpan.org> |
3278
|
|
|
|
|
|
|
|
3279
|
|
|
|
|
|
|
=head1 CONTRIBUTORS |
3280
|
|
|
|
|
|
|
|
3281
|
|
|
|
|
|
|
=for stopwords Mario Zieschang Steven Haryanto |
3282
|
|
|
|
|
|
|
|
3283
|
|
|
|
|
|
|
=over 4 |
3284
|
|
|
|
|
|
|
|
3285
|
|
|
|
|
|
|
=item * |
3286
|
|
|
|
|
|
|
|
3287
|
|
|
|
|
|
|
Mario Zieschang <mario@zieschang.info> |
3288
|
|
|
|
|
|
|
|
3289
|
|
|
|
|
|
|
=item * |
3290
|
|
|
|
|
|
|
|
3291
|
|
|
|
|
|
|
Steven Haryanto <stevenharyanto@gmail.com> |
3292
|
|
|
|
|
|
|
|
3293
|
|
|
|
|
|
|
=back |
3294
|
|
|
|
|
|
|
|
3295
|
|
|
|
|
|
|
=head1 CONTRIBUTING |
3296
|
|
|
|
|
|
|
|
3297
|
|
|
|
|
|
|
|
3298
|
|
|
|
|
|
|
To contribute, you can send patches by email/via RT, or send pull requests on |
3299
|
|
|
|
|
|
|
GitHub. |
3300
|
|
|
|
|
|
|
|
3301
|
|
|
|
|
|
|
Most of the time, you don't need to build the distribution yourself. You can |
3302
|
|
|
|
|
|
|
simply modify the code, then test via: |
3303
|
|
|
|
|
|
|
|
3304
|
|
|
|
|
|
|
% prove -l |
3305
|
|
|
|
|
|
|
|
3306
|
|
|
|
|
|
|
If you want to build the distribution (e.g. to try to install it locally on your |
3307
|
|
|
|
|
|
|
system), you can install L<Dist::Zilla>, |
3308
|
|
|
|
|
|
|
L<Dist::Zilla::PluginBundle::Author::PERLANCAR>, and sometimes one or two other |
3309
|
|
|
|
|
|
|
Dist::Zilla plugin and/or Pod::Weaver::Plugin. Any additional steps required |
3310
|
|
|
|
|
|
|
beyond that are considered a bug and can be reported to me. |
3311
|
|
|
|
|
|
|
|
3312
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
3313
|
|
|
|
|
|
|
|
3314
|
|
|
|
|
|
|
This software is copyright (c) 2022, 2021, 2020, 2018, 2017, 2016, 2015, 2014, 2013 by perlancar <perlancar@cpan.org>. |
3315
|
|
|
|
|
|
|
|
3316
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
3317
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
3318
|
|
|
|
|
|
|
|
3319
|
|
|
|
|
|
|
=head1 BUGS |
3320
|
|
|
|
|
|
|
|
3321
|
|
|
|
|
|
|
Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Text-ANSITable> |
3322
|
|
|
|
|
|
|
|
3323
|
|
|
|
|
|
|
When submitting a bug or request, please include a test-file or a |
3324
|
|
|
|
|
|
|
patch to an existing test-file that illustrates the bug or desired |
3325
|
|
|
|
|
|
|
feature. |
3326
|
|
|
|
|
|
|
|
3327
|
|
|
|
|
|
|
=cut |