line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Text::Pretty; |
2
|
1
|
|
|
1
|
|
26009
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
38
|
|
3
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
26
|
|
4
|
1
|
|
|
1
|
|
360
|
use Types; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
use Exporter; |
6
|
|
|
|
|
|
|
use base qw/Exporter/; |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
our $VERSION = '0.1.0'; |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( |
11
|
|
|
|
|
|
|
prims => [qw(empty text space endl nest indent hcat onel) ] |
12
|
|
|
|
|
|
|
, simple => [qw(semi comma colon dot equals quote bquote qquote |
13
|
|
|
|
|
|
|
lparen rparen lbrack rbrack lbrace rbrace langle rangle)] |
14
|
|
|
|
|
|
|
, struct => [qw(parents brackets braces quotes qquotes bquotes) ] |
15
|
|
|
|
|
|
|
); |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
$EXPORT_TAGS{combinators} = [ @{$EXPORT_TAGS{prims}} |
18
|
|
|
|
|
|
|
, qw(vcat hsep punctuate surround) |
19
|
|
|
|
|
|
|
]; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
our @EXPORT_OK = ( qw(is_empty words) |
22
|
|
|
|
|
|
|
, @{$EXPORT_TAGS{combinators}} |
23
|
|
|
|
|
|
|
, @{$EXPORT_TAGS{simple}} |
24
|
|
|
|
|
|
|
, @{$EXPORT_TAGS{struct}} |
25
|
|
|
|
|
|
|
); |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
$EXPORT_TAGS{all} = \@EXPORT_OK; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# document types |
30
|
|
|
|
|
|
|
newtype Text::Pretty::Empty; |
31
|
|
|
|
|
|
|
newtype Text::Pretty::Text; |
32
|
|
|
|
|
|
|
newtype Text::Pretty::Space; |
33
|
|
|
|
|
|
|
newtype Text::Pretty::Endl; |
34
|
|
|
|
|
|
|
newtype Text::Pretty::Nest; |
35
|
|
|
|
|
|
|
newtype Text::Pretty::HCat; |
36
|
|
|
|
|
|
|
newtype Text::Pretty::Onel; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
uniontype Text::Pretty::Doc, qw(Text::Pretty::Empty |
39
|
|
|
|
|
|
|
Text::Pretty::Text |
40
|
|
|
|
|
|
|
Text::Pretty::Space |
41
|
|
|
|
|
|
|
Text::Pretty::Endl |
42
|
|
|
|
|
|
|
Text::Pretty::Nest |
43
|
|
|
|
|
|
|
Text::Pretty::HCat |
44
|
|
|
|
|
|
|
Text::Pretty::Onel); |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
typeclass Text::Pretty::Print, |
47
|
|
|
|
|
|
|
pretty => undef; |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# rendering method |
50
|
|
|
|
|
|
|
# returns a string of the rendered document |
51
|
|
|
|
|
|
|
# - document to render |
52
|
|
|
|
|
|
|
# - options: document width and indent |
53
|
|
|
|
|
|
|
instance Text::Pretty::Print, Text::Pretty::Doc, |
54
|
|
|
|
|
|
|
pretty => sub { my( $doc, %opts ) = @_ |
55
|
|
|
|
|
|
|
; my $w = $opts{width} || 80 |
56
|
|
|
|
|
|
|
; my $ls = render_proc($doc,0,$w,['']) |
57
|
|
|
|
|
|
|
; join qq{\n}, @$ls |
58
|
|
|
|
|
|
|
}; |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# primitive documents |
61
|
|
|
|
|
|
|
sub empty () { Empty() } |
62
|
|
|
|
|
|
|
sub text ($) { Text(shift) } |
63
|
|
|
|
|
|
|
sub space () { Space() } |
64
|
|
|
|
|
|
|
sub endl () { Endl() } |
65
|
|
|
|
|
|
|
sub nest ($$) { Nest(shift,shift) } |
66
|
|
|
|
|
|
|
sub hcat ($) { HCat(shift) } |
67
|
|
|
|
|
|
|
sub onel ($) { Onel(shift) } |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
# document predicates |
70
|
|
|
|
|
|
|
sub is_empty ($) { shift->isa('Empty') } |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# simple documents |
73
|
|
|
|
|
|
|
sub semi () { text ';' } |
74
|
|
|
|
|
|
|
sub comma () { text ',' } |
75
|
|
|
|
|
|
|
sub colon () { text ':' } |
76
|
|
|
|
|
|
|
sub dot () { text '.' } |
77
|
|
|
|
|
|
|
sub equals () { text '=' } |
78
|
|
|
|
|
|
|
sub quote () { text q{'} } |
79
|
|
|
|
|
|
|
sub bquote () { text q{`} } |
80
|
|
|
|
|
|
|
sub qquote () { text q{"} } |
81
|
|
|
|
|
|
|
sub lparen () { text '(' } |
82
|
|
|
|
|
|
|
sub rparen () { text ')' } |
83
|
|
|
|
|
|
|
sub lbrack () { text '[' } |
84
|
|
|
|
|
|
|
sub rbrack () { text ']' } |
85
|
|
|
|
|
|
|
sub lbrace () { text '{' } |
86
|
|
|
|
|
|
|
sub rbrace () { text '}' } |
87
|
|
|
|
|
|
|
sub langle () { text '<' } |
88
|
|
|
|
|
|
|
sub rangle () { text '>' } |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
# generic document combinators |
91
|
|
|
|
|
|
|
sub punctuate ($$) { my($p,$l)=@_; |
92
|
|
|
|
|
|
|
hcat [do{ my @r = map {$_,$p} @{$l}; pop @r; @r} ] } |
93
|
|
|
|
|
|
|
sub surround ($$$) { my($a,$v,$b)=@_; my $l = length $a->pretty; |
94
|
|
|
|
|
|
|
hcat [ $a, (nest $l, hcat [$v, $b]) ] } |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# derived document combinators |
97
|
|
|
|
|
|
|
sub vcat ($) { punctuate endl, [grep {not is_empty $_} @{shift()}] } |
98
|
|
|
|
|
|
|
sub hsep ($) { punctuate space, [grep {not is_empty $_} @{shift()}] } |
99
|
|
|
|
|
|
|
sub parents ($) { surround lparen, shift(), rparen } |
100
|
|
|
|
|
|
|
sub brackets ($) { surround lbrack, shift(), rbrack } |
101
|
|
|
|
|
|
|
sub braces ($) { surround lbrace, shift(), rbrace } |
102
|
|
|
|
|
|
|
sub quotes ($) { surround quote, shift(), quote } |
103
|
|
|
|
|
|
|
sub qquotes ($) { surround qquote, shift(), qquote } |
104
|
|
|
|
|
|
|
sub bquotes ($) { surround text q{``}, shift(), text q{''} } |
105
|
|
|
|
|
|
|
sub words ($) { my $s = shift |
106
|
|
|
|
|
|
|
; hcat [ hsep [map {text $_} split qr{\s+}, $s] |
107
|
|
|
|
|
|
|
, $s =~ /\s$/sm |
108
|
|
|
|
|
|
|
? space |
109
|
|
|
|
|
|
|
: () ] } |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sub render_proc |
112
|
|
|
|
|
|
|
{ no strict |
113
|
|
|
|
|
|
|
; my( $doc, $i, $w, $ls ) = @_ |
114
|
|
|
|
|
|
|
; asserttype Text::Pretty::Doc, $doc |
115
|
|
|
|
|
|
|
; match $doc |
116
|
|
|
|
|
|
|
=> Text::Pretty::Text |
117
|
|
|
|
|
|
|
=> sub{ my $s = shift |
118
|
|
|
|
|
|
|
; length($ls->[$#{$ls}])+length($s) >= $w |
119
|
|
|
|
|
|
|
&& length($ls->[$#{$ls}]) != $i |
120
|
|
|
|
|
|
|
? do{ my $l = (q{ }x$i).$s |
121
|
|
|
|
|
|
|
; push @$ls, $l |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
: do{ my $l = pop @$ls |
124
|
|
|
|
|
|
|
; $l .= (q{ }x($i - length $l)) . $s |
125
|
|
|
|
|
|
|
; push @$ls, $l |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
; $ls |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
=> Text::Pretty::Space |
130
|
|
|
|
|
|
|
=> sub{ length($ls->[$#{$ls}]) >= $w |
131
|
|
|
|
|
|
|
? push @$ls, q{ }x$i |
132
|
|
|
|
|
|
|
: do{ my $l = pop @$ls |
133
|
|
|
|
|
|
|
; $l .= q{ } |
134
|
|
|
|
|
|
|
; push @$ls, $l |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
; $ls |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
=> Text::Pretty::Endl |
139
|
|
|
|
|
|
|
=> sub{ push @$ls, q{ }x$i |
140
|
|
|
|
|
|
|
; $ls |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
=> Text::Pretty::HCat |
143
|
|
|
|
|
|
|
=> sub{ $ls = render_proc($_,$i,$w,$ls) for @{shift()} |
144
|
|
|
|
|
|
|
; $ls |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
=> Text::Pretty::Nest |
147
|
|
|
|
|
|
|
=> sub{ render_proc(pop, $i + shift, $w, $ls) } |
148
|
|
|
|
|
|
|
=> Text::Pretty::Onel |
149
|
|
|
|
|
|
|
=> sub{ my $e = text render_proc(shift, 0, 1_000_000, [''])->[0] |
150
|
|
|
|
|
|
|
; render_proc($e, $i, $w, $ls) |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
=> Text::Pretty::Empty |
153
|
|
|
|
|
|
|
=> sub{ $ls } |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
1; |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=head1 NAME |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
Text::Pretty - The great new Text::Pretty! |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=head1 VERSION |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
Version 0.1 |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=head1 SYNOPSIS |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
A generic pretty printing combinators. |
169
|
|
|
|
|
|
|
More documentation is coming soon. |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=head1 EXPORT |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
empty text space endl nest indent hcat onel |
174
|
|
|
|
|
|
|
semi comma colon dot equals quote bquote qquote |
175
|
|
|
|
|
|
|
lparen rparen lbrack rbrack lbrace rbrace langle rangle |
176
|
|
|
|
|
|
|
parents brackets braces quotes qquotes bquotes |
177
|
|
|
|
|
|
|
vcat hsep punctuate surround is_empty words |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head1 AUTHOR |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
Eugene Grigoriev, C<< >> |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=head1 BUGS |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
Please report any bugs or feature requests to C, or through |
186
|
|
|
|
|
|
|
the web interface at L. I will be notified, and then you'll |
187
|
|
|
|
|
|
|
automatically be notified of progress on your bug as I make changes. |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=head1 SUPPORT |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
perldoc Text::Pretty |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
You can also look for information at: |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=over 4 |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
L |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
L |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=item * CPAN Ratings |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
L |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
=item * Search CPAN |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
L |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=back |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
Copyright 2008 Eugene Grigoriev, all rights reserved. |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
230
|
|
|
|
|
|
|
under the same terms as Perl itself. |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
|