| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Text::ANSI::Fold; |
|
2
|
|
|
|
|
|
|
|
|
3
|
14
|
|
|
14
|
|
2297542
|
use v5.14; |
|
|
14
|
|
|
|
|
62
|
|
|
4
|
14
|
|
|
14
|
|
86
|
use warnings; |
|
|
14
|
|
|
|
|
88
|
|
|
|
14
|
|
|
|
|
903
|
|
|
5
|
14
|
|
|
14
|
|
2167
|
use utf8; |
|
|
14
|
|
|
|
|
1080
|
|
|
|
14
|
|
|
|
|
86
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = "2.3305"; |
|
8
|
|
|
|
|
|
|
|
|
9
|
14
|
|
|
14
|
|
7789
|
use Data::Dumper; |
|
|
14
|
|
|
|
|
127249
|
|
|
|
14
|
|
|
|
|
1605
|
|
|
10
|
|
|
|
|
|
|
{ |
|
11
|
14
|
|
|
14
|
|
132
|
no warnings 'redefine'; |
|
|
14
|
|
|
|
|
29
|
|
|
|
14
|
|
|
|
|
2107
|
|
|
12
|
0
|
|
|
0
|
|
0
|
*Data::Dumper::qquote = sub { qq["${\(shift)}"] }; |
|
|
0
|
|
|
|
|
0
|
|
|
13
|
|
|
|
|
|
|
$Data::Dumper::Useperl = 1; |
|
14
|
|
|
|
|
|
|
$Data::Dumper::Sortkeys = 1; |
|
15
|
|
|
|
|
|
|
} |
|
16
|
14
|
|
|
14
|
|
117
|
use Carp; |
|
|
14
|
|
|
|
|
27
|
|
|
|
14
|
|
|
|
|
1253
|
|
|
17
|
14
|
|
|
14
|
|
93
|
use List::Util qw(pairmap pairgrep); |
|
|
14
|
|
|
|
|
26
|
|
|
|
14
|
|
|
|
|
1131
|
|
|
18
|
14
|
|
|
14
|
|
140
|
use Scalar::Util qw(looks_like_number); |
|
|
14
|
|
|
|
|
49
|
|
|
|
14
|
|
|
|
|
907
|
|
|
19
|
14
|
|
|
14
|
|
7997
|
use Text::VisualWidth::PP 'vwidth'; |
|
|
14
|
|
|
|
|
81513
|
|
|
|
14
|
|
|
|
|
1450
|
|
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
###################################################################### |
|
22
|
14
|
|
|
14
|
|
147
|
use Exporter 'import'; |
|
|
14
|
|
|
|
|
30
|
|
|
|
14
|
|
|
|
|
10443
|
|
|
23
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( |
|
24
|
|
|
|
|
|
|
constants => [ qw( |
|
25
|
|
|
|
|
|
|
&LINEBREAK_NONE |
|
26
|
|
|
|
|
|
|
&LINEBREAK_ALL |
|
27
|
|
|
|
|
|
|
&LINEBREAK_RUNIN |
|
28
|
|
|
|
|
|
|
&LINEBREAK_RUNOUT |
|
29
|
|
|
|
|
|
|
) ], |
|
30
|
|
|
|
|
|
|
regex => [ qw( |
|
31
|
|
|
|
|
|
|
$reset_re |
|
32
|
|
|
|
|
|
|
$color_re |
|
33
|
|
|
|
|
|
|
$erase_re |
|
34
|
|
|
|
|
|
|
$csi_re |
|
35
|
|
|
|
|
|
|
$osc_re |
|
36
|
|
|
|
|
|
|
) ], |
|
37
|
|
|
|
|
|
|
); |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
our @EXPORT_OK = ( qw(&ansi_fold), |
|
40
|
|
|
|
|
|
|
@{$EXPORT_TAGS{constants}}, |
|
41
|
|
|
|
|
|
|
@{$EXPORT_TAGS{regex}}, |
|
42
|
|
|
|
|
|
|
); |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub ansi_fold { |
|
45
|
437
|
|
|
437
|
1
|
1058133
|
my($text, $width, @option) = @_; |
|
46
|
437
|
|
|
|
|
1838
|
__PACKAGE__->fold($text, width => $width, @option); |
|
47
|
|
|
|
|
|
|
} |
|
48
|
|
|
|
|
|
|
###################################################################### |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
our $alphanum_re = qr{ [_\d\p{Latin}\p{Greek}\p{Cyrillic}\p{Hangul}] }x; |
|
51
|
|
|
|
|
|
|
our $nonspace_re = qr{ \p{IsPrintableLatin} }x; |
|
52
|
|
|
|
|
|
|
our $reset_re = qr{ \e \[ [0;]* m }x; |
|
53
|
|
|
|
|
|
|
our $color_re = qr{ \e \[ [\d;]* m }x; |
|
54
|
|
|
|
|
|
|
our $erase_re = qr{ \e \[ [\d;]* K }x; |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# see ECMA-48 5.4 Control sequences |
|
57
|
|
|
|
|
|
|
my $csi_start = qr{ (?: \e\[ | \x9b ) }x; |
|
58
|
|
|
|
|
|
|
my $csi_parameter = qr/[\x30-\x3f]*+/; |
|
59
|
|
|
|
|
|
|
my $csi_itermidiate = qr/[\x20-\x2f]*+/; |
|
60
|
|
|
|
|
|
|
my $csi_final = qr/[\x40-\x7e]/; |
|
61
|
|
|
|
|
|
|
our $csi_body_re = qr/${csi_start}${csi_parameter}${csi_itermidiate}/; |
|
62
|
|
|
|
|
|
|
our $csi_re = qr/${csi_start}${csi_parameter}${csi_itermidiate}${csi_final}/; |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
our $osc_re = qr{ |
|
65
|
|
|
|
|
|
|
# see ECMA-48 8.3.89 OSC - OPERATING SYSTEM COMMAND |
|
66
|
|
|
|
|
|
|
# Extended to accept non-ASCII (undefined but tolerated) |
|
67
|
|
|
|
|
|
|
(?: \e\] | \x9d ) # osc |
|
68
|
|
|
|
|
|
|
[^\x00-\x07\x0e-\x1f\x7f-\x9f]*+ # command (excludes C1 controls) |
|
69
|
|
|
|
|
|
|
(?: \e\\ | \x9c | \a ) # st: string terminator |
|
70
|
|
|
|
|
|
|
}x; |
|
71
|
|
|
|
|
|
|
|
|
72
|
14
|
|
|
14
|
|
161
|
use constant SGR_RESET => "\e[m"; |
|
|
14
|
|
|
|
|
32
|
|
|
|
14
|
|
|
|
|
1443
|
|
|
73
|
14
|
|
|
14
|
|
102
|
use constant OSC8_RESET => "\e]8;;\e\\"; |
|
|
14
|
|
|
|
|
30
|
|
|
|
14
|
|
|
|
|
3749
|
|
|
74
|
|
|
|
|
|
|
|
|
75
|
161
|
|
|
161
|
0
|
6278
|
sub pwidth { vwidth $_[0] =~ s/\X\cH{1,2}//gr =~ s/${osc_re}//gr } |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub IsPrintableLatin { |
|
78
|
1
|
|
|
1
|
0
|
208
|
return <<"END"; |
|
79
|
|
|
|
|
|
|
+utf8::ASCII |
|
80
|
|
|
|
|
|
|
+utf8::Latin |
|
81
|
|
|
|
|
|
|
-utf8::White_Space |
|
82
|
|
|
|
|
|
|
END |
|
83
|
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
sub IsWideSpacing { |
|
86
|
14
|
|
|
14
|
0
|
1598
|
return <<"END"; |
|
87
|
|
|
|
|
|
|
+utf8::East_Asian_Width=Wide |
|
88
|
|
|
|
|
|
|
+utf8::East_Asian_Width=FullWidth |
|
89
|
|
|
|
|
|
|
-utf8::Nonspacing_Mark |
|
90
|
|
|
|
|
|
|
-utf8::Default_Ignorable_Code_Point |
|
91
|
|
|
|
|
|
|
END |
|
92
|
|
|
|
|
|
|
} |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub IsWideAmbiguousSpacing { |
|
95
|
14
|
|
|
14
|
0
|
1985
|
return <<"END"; |
|
96
|
|
|
|
|
|
|
+utf8::East_Asian_Width=Wide |
|
97
|
|
|
|
|
|
|
+utf8::East_Asian_Width=FullWidth |
|
98
|
|
|
|
|
|
|
+utf8::East_Asian_Width=Ambiguous |
|
99
|
|
|
|
|
|
|
-utf8::Nonspacing_Mark |
|
100
|
|
|
|
|
|
|
-utf8::Default_Ignorable_Code_Point |
|
101
|
|
|
|
|
|
|
END |
|
102
|
|
|
|
|
|
|
} |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
sub _startWideSpacing { |
|
105
|
|
|
|
|
|
|
# look at $_ |
|
106
|
62
|
100
|
|
62
|
|
163
|
if ($Text::VisualWidth::PP::EastAsian) { |
|
107
|
2
|
|
|
|
|
9
|
/^\p{IsWideAmbiguousSpacing}/; |
|
108
|
|
|
|
|
|
|
} else { |
|
109
|
60
|
|
|
|
|
335
|
/^\p{IsWideSpacing}/; |
|
110
|
|
|
|
|
|
|
} |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
use constant { |
|
114
|
14
|
|
|
|
|
2945
|
LINEBREAK_NONE => 0, |
|
115
|
|
|
|
|
|
|
LINEBREAK_RUNIN => 1, |
|
116
|
|
|
|
|
|
|
LINEBREAK_RUNOUT => 2, |
|
117
|
|
|
|
|
|
|
LINEBREAK_ALL => 3, |
|
118
|
14
|
|
|
14
|
|
178
|
}; |
|
|
14
|
|
|
|
|
33
|
|
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
our $DEFAULT_LINEBREAK = LINEBREAK_NONE; |
|
121
|
|
|
|
|
|
|
our $DEFAULT_RUNIN_WIDTH = 2; |
|
122
|
|
|
|
|
|
|
our $DEFAULT_RUNOUT_WIDTH = 2; |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
BEGIN { |
|
125
|
14
|
50
|
|
14
|
|
1790
|
if ($] < 5.016) { |
|
126
|
0
|
|
|
|
|
0
|
require charnames; |
|
127
|
0
|
|
|
|
|
0
|
charnames->import(':full'); |
|
128
|
|
|
|
|
|
|
} |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
our %TABSTYLE = ( |
|
132
|
|
|
|
|
|
|
pairmap { |
|
133
|
|
|
|
|
|
|
( $a =~ s/_/-/gr => ref $b ? $b : [ $b, $b ] ); |
|
134
|
|
|
|
|
|
|
} |
|
135
|
14
|
|
|
14
|
|
10528
|
symbol => [ "\N{SYMBOL FOR HORIZONTAL TABULATION}", # ␉ |
|
|
14
|
|
|
|
|
145786
|
|
|
|
14
|
|
|
|
|
108
|
|
|
136
|
|
|
|
|
|
|
"\N{SYMBOL FOR SPACE}" ], # ␠ |
|
137
|
|
|
|
|
|
|
shade => [ "\N{MEDIUM SHADE}", # ▒ |
|
138
|
|
|
|
|
|
|
"\N{LIGHT SHADE}" ], # ░ |
|
139
|
|
|
|
|
|
|
block => [ "\N{LOWER ONE QUARTER BLOCK}", # ▂ |
|
140
|
|
|
|
|
|
|
"\N{LOWER ONE EIGHTH BLOCK}" ], # ▁ |
|
141
|
|
|
|
|
|
|
needle => [ "\N{BOX DRAWINGS HEAVY RIGHT}", # ╺ |
|
142
|
|
|
|
|
|
|
"\N{BOX DRAWINGS LIGHT HORIZONTAL}" ], # ─ |
|
143
|
|
|
|
|
|
|
dash => [ "\N{BOX DRAWINGS HEAVY RIGHT}", # ╺ |
|
144
|
|
|
|
|
|
|
"\N{BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL}" ], # ╌ |
|
145
|
|
|
|
|
|
|
triangle => [ "\N{BLACK RIGHT-POINTING SMALL TRIANGLE}", # ▸ |
|
146
|
|
|
|
|
|
|
"\N{WHITE RIGHT-POINTING SMALL TRIANGLE}" ], # ▹ |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
dot => '.', |
|
149
|
|
|
|
|
|
|
space => ' ', |
|
150
|
|
|
|
|
|
|
emspace => "\N{EM SPACE}", # |
|
151
|
|
|
|
|
|
|
blank => "\N{OPEN BOX}", # ␣ |
|
152
|
|
|
|
|
|
|
middle_dot => "\N{MIDDLE DOT}", # · |
|
153
|
|
|
|
|
|
|
arrow => "\N{RIGHTWARDS ARROW}", # → |
|
154
|
|
|
|
|
|
|
double_arrow => "\N{RIGHTWARDS DOUBLE ARROW}", # ⇒ |
|
155
|
|
|
|
|
|
|
triple_arrow => "\N{RIGHTWARDS TRIPLE ARROW}", # ⇛ |
|
156
|
|
|
|
|
|
|
white_arrow => "\N{RIGHTWARDS WHITE ARROW}", # ⇨ |
|
157
|
|
|
|
|
|
|
wave_arrow => "\N{RIGHTWARDS WAVE ARROW}", # ↝ |
|
158
|
|
|
|
|
|
|
circle_arrow => "\N{CIRCLED HEAVY WHITE RIGHTWARDS ARROW}", # ➲ |
|
159
|
|
|
|
|
|
|
curved_arrow => "\N{HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW}",# ➥ |
|
160
|
|
|
|
|
|
|
shadow_arrow => "\N{HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW}",# ➮ |
|
161
|
|
|
|
|
|
|
squat_arrow => "\N{SQUAT BLACK RIGHTWARDS ARROW}", # ➧ |
|
162
|
|
|
|
|
|
|
squiggle => "\N{RIGHTWARDS SQUIGGLE ARROW}", # ⇝ |
|
163
|
|
|
|
|
|
|
harpoon => "\N{RIGHTWARDS HARPOON WITH BARB UPWARDS}", # ⇀ |
|
164
|
|
|
|
|
|
|
cuneiform => "\N{CUNEIFORM SIGN TAB}", # 𒋰 |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
); |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
for my $alias ( |
|
169
|
|
|
|
|
|
|
[ bar => 'needle'], |
|
170
|
|
|
|
|
|
|
[ pin => 'needle'] |
|
171
|
|
|
|
|
|
|
) { |
|
172
|
|
|
|
|
|
|
$TABSTYLE{$alias->[0]} = $TABSTYLE{$alias->[1]}; |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
my @default = ( |
|
176
|
|
|
|
|
|
|
text => '', |
|
177
|
|
|
|
|
|
|
width => undef, |
|
178
|
|
|
|
|
|
|
padding => 0, |
|
179
|
|
|
|
|
|
|
boundary => '', |
|
180
|
|
|
|
|
|
|
padchar => ' ', |
|
181
|
|
|
|
|
|
|
prefix => '', |
|
182
|
|
|
|
|
|
|
ambiguous => 'narrow', |
|
183
|
|
|
|
|
|
|
margin => 0, |
|
184
|
|
|
|
|
|
|
linebreak => $DEFAULT_LINEBREAK, |
|
185
|
|
|
|
|
|
|
runin => $DEFAULT_RUNIN_WIDTH, |
|
186
|
|
|
|
|
|
|
runout => $DEFAULT_RUNOUT_WIDTH, |
|
187
|
|
|
|
|
|
|
expand => 0, |
|
188
|
|
|
|
|
|
|
tabstop => 8, |
|
189
|
|
|
|
|
|
|
tabhead => ' ', |
|
190
|
|
|
|
|
|
|
tabspace => ' ', |
|
191
|
|
|
|
|
|
|
discard => {}, |
|
192
|
|
|
|
|
|
|
splitwide => 0, |
|
193
|
|
|
|
|
|
|
lefthalf => "\N{NO-BREAK SPACE}", |
|
194
|
|
|
|
|
|
|
righthalf => "\N{NO-BREAK SPACE}", |
|
195
|
|
|
|
|
|
|
); |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
sub new { |
|
198
|
16
|
|
|
16
|
1
|
2218528
|
my $class = shift; |
|
199
|
16
|
|
|
|
|
422
|
my $obj = bless { @default }, $class; |
|
200
|
16
|
100
|
|
|
|
253
|
$obj->configure(@_) if @_; |
|
201
|
16
|
|
|
|
|
85
|
$obj; |
|
202
|
|
|
|
|
|
|
} |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
INTERNAL_METHODS: { |
|
205
|
|
|
|
|
|
|
sub spawn { |
|
206
|
715
|
|
|
715
|
0
|
1157
|
my $obj = shift; |
|
207
|
715
|
|
|
|
|
1370
|
my $class = ref $obj; |
|
208
|
715
|
|
|
762
|
|
8569
|
my %new = ( %$obj, pairgrep { defined $b } @_ ); |
|
|
762
|
|
|
|
|
7733
|
|
|
209
|
715
|
|
|
|
|
4604
|
bless \%new, $class; |
|
210
|
|
|
|
|
|
|
} |
|
211
|
715
|
100
|
|
715
|
0
|
2516
|
sub do_runin { $_[0]->{linebreak} & LINEBREAK_RUNIN && $_[0]->{runin} > 0 } |
|
212
|
596
|
100
|
|
596
|
0
|
4010
|
sub do_runout { $_[0]->{linebreak} & LINEBREAK_RUNOUT && $_[0]->{runout} > 0 } |
|
213
|
|
|
|
|
|
|
} |
|
214
|
|
|
|
|
|
|
|
|
215
|
14
|
|
|
14
|
|
541668
|
use Text::ANSI::Fold::Japanese::W3C qw(%prohibition); |
|
|
14
|
|
|
|
|
78
|
|
|
|
14
|
|
|
|
|
18585
|
|
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
sub chars_to_regex { |
|
218
|
28
|
|
|
28
|
0
|
175
|
my $chars = join '', @_; |
|
219
|
28
|
|
|
|
|
59
|
my($c, @s); |
|
220
|
28
|
|
|
|
|
1556
|
for ($chars =~ /\X/g) { |
|
221
|
2170
|
100
|
|
|
|
4085
|
if (length == 1) { |
|
222
|
2156
|
|
|
|
|
3150
|
$c .= $_; |
|
223
|
|
|
|
|
|
|
} else { |
|
224
|
14
|
|
|
|
|
58
|
push @s, $_; |
|
225
|
|
|
|
|
|
|
} |
|
226
|
|
|
|
|
|
|
} |
|
227
|
28
|
100
|
|
|
|
419
|
if (@s) { |
|
228
|
14
|
|
|
|
|
41
|
local $" = '|'; |
|
229
|
14
|
|
|
|
|
1472
|
qr/(?:[\Q$c\E]|@s)/; |
|
230
|
|
|
|
|
|
|
} else { |
|
231
|
14
|
|
|
|
|
675
|
qr/[\Q$c\E]/; |
|
232
|
|
|
|
|
|
|
} |
|
233
|
|
|
|
|
|
|
} |
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
my %prohibition_re = do { |
|
236
|
|
|
|
|
|
|
head => do { |
|
237
|
|
|
|
|
|
|
my $re = chars_to_regex @prohibition{qw(head postfix)}; |
|
238
|
|
|
|
|
|
|
qr/(?: $re | \p{Space_Separator} )/x; |
|
239
|
|
|
|
|
|
|
}, |
|
240
|
|
|
|
|
|
|
end => chars_to_regex @prohibition{qw(end prefix)}, |
|
241
|
|
|
|
|
|
|
}; |
|
242
|
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
sub configure { |
|
244
|
63
|
|
|
63
|
1
|
279852
|
my $obj = shift; |
|
245
|
63
|
100
|
|
|
|
253
|
if (not ref $obj) { |
|
246
|
12
|
|
|
|
|
42
|
$obj = state $private = __PACKAGE__->new; |
|
247
|
|
|
|
|
|
|
} |
|
248
|
63
|
50
|
|
|
|
265
|
croak "invalid parameter" if @_ % 2; |
|
249
|
63
|
|
|
|
|
223
|
while (@_ >= 2) { |
|
250
|
103
|
|
|
|
|
324
|
my($a, $b) = splice @_, 0, 2; |
|
251
|
|
|
|
|
|
|
|
|
252
|
103
|
100
|
|
|
|
260
|
if ($a eq 'tabstyle') { |
|
253
|
1
|
|
50
|
|
|
25
|
$b // next; |
|
254
|
1
|
50
|
|
|
|
10
|
my($h, $s) = $b =~ /([-\w]+)/g or croak "$b: invalid tabstyle"; |
|
255
|
1
|
|
33
|
|
|
11
|
$s ||= $h; |
|
256
|
|
|
|
|
|
|
my %style = ( |
|
257
|
|
|
|
|
|
|
h => ($TABSTYLE{$h} or croak "$h: invalid tabstyle"), |
|
258
|
1
|
|
33
|
|
|
12
|
s => ($TABSTYLE{$s} or croak "$s: invalid tabstyle"), |
|
|
|
|
33
|
|
|
|
|
|
259
|
|
|
|
|
|
|
); |
|
260
|
|
|
|
|
|
|
unshift @_, |
|
261
|
|
|
|
|
|
|
tabhead => $style{h}->[0], |
|
262
|
1
|
|
|
|
|
8
|
tabspace => $style{s}->[1]; |
|
263
|
1
|
|
|
|
|
5
|
next; |
|
264
|
|
|
|
|
|
|
} |
|
265
|
|
|
|
|
|
|
|
|
266
|
102
|
50
|
|
|
|
286
|
croak "$a: invalid parameter" if not exists $obj->{$a}; |
|
267
|
102
|
|
|
|
|
335
|
$obj->{$a} = $b; |
|
268
|
|
|
|
|
|
|
} |
|
269
|
63
|
50
|
|
|
|
266
|
if (ref $obj->{discard} eq 'ARRAY') { |
|
270
|
0
|
|
|
|
|
0
|
$obj->{discard} = { map { uc $_ => 1 } @{$obj->{discard}} }; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
271
|
|
|
|
|
|
|
} |
|
272
|
63
|
|
|
|
|
201
|
$obj; |
|
273
|
|
|
|
|
|
|
} |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
my @color_stack; |
|
276
|
|
|
|
|
|
|
my @bg_stack; |
|
277
|
|
|
|
|
|
|
my @reset; |
|
278
|
|
|
|
|
|
|
my $osc8_link; |
|
279
|
159
|
|
|
159
|
0
|
655
|
sub put_reset { @reset = shift }; |
|
280
|
|
|
|
|
|
|
sub pop_reset { |
|
281
|
193
|
100
|
|
193
|
0
|
515
|
@reset ? do { @color_stack = (); pop @reset } : ''; |
|
|
159
|
|
|
|
|
400
|
|
|
|
159
|
|
|
|
|
410
|
|
|
282
|
|
|
|
|
|
|
} |
|
283
|
|
|
|
|
|
|
|
|
284
|
14
|
|
|
14
|
|
126
|
use constant MAX_INT => ~0 >> 1; |
|
|
14
|
|
|
|
|
26
|
|
|
|
14
|
|
|
|
|
6584
|
|
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
sub IsEOL { |
|
287
|
14
|
|
|
14
|
0
|
48557
|
<<"END"; |
|
288
|
|
|
|
|
|
|
0000\t0000 |
|
289
|
|
|
|
|
|
|
000A\t000D |
|
290
|
|
|
|
|
|
|
2028\t2029 |
|
291
|
|
|
|
|
|
|
END |
|
292
|
|
|
|
|
|
|
} |
|
293
|
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
sub fold { |
|
295
|
715
|
|
|
715
|
1
|
134626
|
my $obj = shift; |
|
296
|
715
|
|
50
|
|
|
2379
|
local $_ = shift // ''; |
|
297
|
|
|
|
|
|
|
|
|
298
|
715
|
100
|
|
|
|
1891
|
if (not ref $obj) { |
|
299
|
437
|
|
|
|
|
869
|
$obj = state $private = configure(); |
|
300
|
|
|
|
|
|
|
} |
|
301
|
715
|
|
|
|
|
2449
|
my $opt = $obj->spawn(splice @_); |
|
302
|
|
|
|
|
|
|
|
|
303
|
715
|
|
|
|
|
1611
|
my $width = $opt->{width}; |
|
304
|
715
|
50
|
33
|
|
|
4183
|
looks_like_number $width and $width == int($width) |
|
305
|
|
|
|
|
|
|
or croak "$width: invalid width"; |
|
306
|
715
|
100
|
|
|
|
1902
|
$opt->{padding} = 0 if $width <= 0; |
|
307
|
715
|
100
|
|
|
|
1518
|
$width = MAX_INT if $width < 0; |
|
308
|
715
|
50
|
|
|
|
2103
|
($width -= $opt->{margin}) > 0 or croak "margin too big"; |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
my $word_char_re = |
|
311
|
|
|
|
|
|
|
{ word => $alphanum_re, space => $nonspace_re } |
|
312
|
715
|
|
50
|
|
|
3345
|
->{$opt->{boundary} // ''}; |
|
313
|
|
|
|
|
|
|
|
|
314
|
715
|
|
|
|
|
2537
|
local $Text::VisualWidth::PP::EastAsian = $opt->{ambiguous} eq 'wide'; |
|
315
|
|
|
|
|
|
|
|
|
316
|
715
|
|
|
|
|
1148
|
my $folded = ''; |
|
317
|
715
|
|
|
|
|
1095
|
my $eol = ''; |
|
318
|
715
|
|
|
|
|
1117
|
my $room = $width; |
|
319
|
715
|
|
|
|
|
1511
|
@bg_stack = @color_stack = @reset = (); |
|
320
|
715
|
|
|
|
|
1247
|
$osc8_link = undef; |
|
321
|
|
|
|
|
|
|
my $unremarkable_re = |
|
322
|
715
|
100
|
|
|
|
4473
|
$opt->{expand} ? qr/[^\p{IsEOL}\e\t]/ |
|
323
|
|
|
|
|
|
|
: qr/[^\p{IsEOL}\e]/; |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
FOLD: |
|
326
|
715
|
|
|
|
|
1883
|
while (length) { |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
# newline, null, vt |
|
329
|
|
|
|
|
|
|
# U+2028: Line Separator |
|
330
|
|
|
|
|
|
|
# U+2029: Paragraph Separator |
|
331
|
2067
|
100
|
|
|
|
10626
|
if (s/\A(\r*\n|[\0\x0b\N{U+2028}\N{U+2029}])//) { |
|
332
|
20
|
|
|
|
|
29
|
$eol = $1; |
|
333
|
20
|
|
|
|
|
22
|
last; |
|
334
|
|
|
|
|
|
|
} |
|
335
|
|
|
|
|
|
|
# form feed |
|
336
|
2047
|
100
|
|
|
|
5303
|
if (m/\A(\f+)/p) { |
|
337
|
3
|
100
|
|
|
|
10
|
last if length $folded; |
|
338
|
2
|
|
|
|
|
11
|
($folded, $_) = ($1, ${^POSTMATCH}); |
|
339
|
2
|
|
|
|
|
5
|
next; |
|
340
|
|
|
|
|
|
|
} |
|
341
|
|
|
|
|
|
|
# carriage return |
|
342
|
2044
|
100
|
|
|
|
4428
|
if (s/\A(\r+)//) { |
|
343
|
2
|
50
|
|
|
|
6
|
if (length == 0) { |
|
344
|
|
|
|
|
|
|
# this must be the part of CRNL |
|
345
|
0
|
|
|
|
|
0
|
$eol = $1; |
|
346
|
0
|
|
|
|
|
0
|
last; |
|
347
|
|
|
|
|
|
|
} else { |
|
348
|
2
|
|
|
|
|
4
|
$folded .= $1; |
|
349
|
2
|
|
|
|
|
3
|
$room = $width; |
|
350
|
2
|
|
|
|
|
4
|
next; |
|
351
|
|
|
|
|
|
|
} |
|
352
|
|
|
|
|
|
|
} |
|
353
|
|
|
|
|
|
|
# ECMA-48 OPERATING SYSTEM COMMAND |
|
354
|
2042
|
100
|
|
|
|
12773
|
if (s/\A($osc_re)//) { |
|
355
|
50
|
|
|
|
|
93
|
my $osc = $1; |
|
356
|
50
|
100
|
|
|
|
96
|
unless ($obj->{discard}->{OSC}) { |
|
357
|
46
|
|
|
|
|
74
|
$folded .= $osc; |
|
358
|
46
|
50
|
|
|
|
194
|
if ($osc =~ /^(?:\e\]|\x9d)8;[^;]*;(.*?)(?:\e\\|\x9c|\a)$/) { |
|
359
|
46
|
100
|
|
|
|
106
|
$osc8_link = $1 ne '' ? $osc : undef; |
|
360
|
|
|
|
|
|
|
} |
|
361
|
|
|
|
|
|
|
} |
|
362
|
50
|
|
|
|
|
97
|
next; |
|
363
|
|
|
|
|
|
|
} |
|
364
|
|
|
|
|
|
|
# erase line (assume 0) |
|
365
|
1992
|
100
|
|
|
|
8878
|
if (s/\A($erase_re)//) { |
|
366
|
1
|
50
|
|
|
|
8
|
$folded .= $1 unless $obj->{discard}->{EL}; |
|
367
|
1
|
|
|
|
|
4
|
@bg_stack = grep { !/$erase_re/ } @color_stack; |
|
|
1
|
|
|
|
|
9
|
|
|
368
|
1
|
|
|
|
|
4
|
push @color_stack, $1; |
|
369
|
1
|
|
|
|
|
2
|
next; |
|
370
|
|
|
|
|
|
|
} |
|
371
|
|
|
|
|
|
|
# reset |
|
372
|
1991
|
100
|
|
|
|
9619
|
if (s/\A($reset_re+($erase_re*))//) { |
|
373
|
159
|
|
|
|
|
649
|
put_reset($1); |
|
374
|
159
|
50
|
|
|
|
499
|
@bg_stack = () if $2; |
|
375
|
159
|
|
|
|
|
431
|
next; |
|
376
|
|
|
|
|
|
|
} |
|
377
|
|
|
|
|
|
|
|
|
378
|
1832
|
100
|
|
|
|
4129
|
last if $room < 1; |
|
379
|
1278
|
100
|
66
|
|
|
3490
|
if ($room < 2 and !$opt->{splitwide}) { |
|
380
|
124
|
100
|
100
|
|
|
393
|
last if $room != $width and &_startWideSpacing; |
|
381
|
|
|
|
|
|
|
} |
|
382
|
|
|
|
|
|
|
|
|
383
|
1262
|
100
|
|
|
|
2843
|
if (@reset) { |
|
384
|
111
|
|
|
|
|
327
|
$folded .= pop_reset(); |
|
385
|
|
|
|
|
|
|
} |
|
386
|
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
# ANSI color sequence |
|
388
|
1262
|
100
|
|
|
|
5810
|
if (s/\A($color_re)//) { |
|
389
|
215
|
|
|
|
|
719
|
$folded .= $1; |
|
390
|
215
|
|
|
|
|
573
|
push @color_stack, $1; |
|
391
|
215
|
|
|
|
|
665
|
next; |
|
392
|
|
|
|
|
|
|
} |
|
393
|
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
# imcomplete CSI |
|
395
|
1047
|
100
|
|
|
|
6449
|
if (s/\A(\e+|$csi_body_re)\z//) { |
|
396
|
3
|
|
|
|
|
11
|
$folded .= $1; |
|
397
|
3
|
|
|
|
|
7
|
last; |
|
398
|
|
|
|
|
|
|
} |
|
399
|
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
# tab |
|
401
|
1044
|
100
|
100
|
|
|
3977
|
if ($opt->{expand} and s/\A\t//) { |
|
402
|
112
|
|
|
|
|
329
|
my $space = $opt->{tabstop} - ($width - $room) % $opt->{tabstop}; |
|
403
|
112
|
|
|
|
|
533
|
$_ = $opt->{tabhead} . $opt->{tabspace} x ($space - 1) . $_; |
|
404
|
112
|
|
|
|
|
314
|
next; |
|
405
|
|
|
|
|
|
|
} |
|
406
|
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
# backspace |
|
408
|
932
|
|
|
|
|
1510
|
my $bs = 0; |
|
409
|
932
|
|
|
|
|
2798
|
while (m/\A(?:\X\cH+)++(?\X|\z)/p) { |
|
410
|
850
|
|
|
|
|
6637
|
my $w = vwidth($+{c}); |
|
411
|
850
|
100
|
100
|
|
|
126066
|
last FOLD if $w > $room and $room != $width; |
|
412
|
846
|
|
|
|
|
2609
|
$folded .= ${^MATCH}; |
|
413
|
846
|
|
|
|
|
7283
|
$_ = ${^POSTMATCH}; |
|
414
|
846
|
|
|
|
|
1394
|
$room -= $w; |
|
415
|
846
|
|
|
|
|
1352
|
$bs++; |
|
416
|
846
|
100
|
|
|
|
1738
|
last FOLD if $room < 0; |
|
417
|
840
|
100
|
|
|
|
6276
|
last if $room < 1; |
|
418
|
|
|
|
|
|
|
} |
|
419
|
922
|
100
|
|
|
|
2061
|
next if $bs; |
|
420
|
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
# consume unremarkable characters |
|
422
|
860
|
50
|
|
|
|
7734
|
if (s/\A(\e+|(?:${unremarkable_re}(?!\cH))+)//) { |
|
423
|
860
|
|
|
|
|
2518
|
my $s = $1; |
|
424
|
860
|
100
|
|
|
|
2962
|
if ((my $w = vwidth($s)) <= $room) { |
|
425
|
387
|
|
|
|
|
66496
|
$folded .= $s; |
|
426
|
387
|
|
|
|
|
694
|
$room -= $w; |
|
427
|
387
|
|
|
|
|
1416
|
next; |
|
428
|
|
|
|
|
|
|
} |
|
429
|
473
|
|
|
|
|
176061
|
my($a, $b, $w) = simple_fold($s, $room); |
|
430
|
473
|
50
|
|
|
|
1418
|
if ($opt->{splitwide}) { |
|
431
|
0
|
0
|
0
|
|
|
0
|
if ($w == $room - 1 && $b =~ /\A\p{IsWideSpacing}/p) { |
|
|
|
0
|
|
|
|
|
|
|
432
|
0
|
|
|
|
|
0
|
$a .= $opt->{lefthalf}; |
|
433
|
0
|
|
|
|
|
0
|
$b = $opt->{righthalf} . ${^POSTMATCH}; |
|
434
|
0
|
|
|
|
|
0
|
$w++; |
|
435
|
|
|
|
|
|
|
} |
|
436
|
|
|
|
|
|
|
elsif ($w > $room) { |
|
437
|
0
|
|
|
|
|
0
|
$a = $opt->{lefthalf}; |
|
438
|
0
|
|
|
|
|
0
|
$b = $opt->{righthalf} . $b; |
|
439
|
0
|
|
|
|
|
0
|
$w--; |
|
440
|
|
|
|
|
|
|
} |
|
441
|
|
|
|
|
|
|
} |
|
442
|
473
|
50
|
66
|
|
|
1570
|
if ($w > $room && $room != $width) { |
|
443
|
0
|
|
|
|
|
0
|
$_ = $s . $_; |
|
444
|
0
|
|
|
|
|
0
|
last; |
|
445
|
|
|
|
|
|
|
} |
|
446
|
473
|
|
|
|
|
1383
|
($folded, $_) = ($folded . $a, $b . $_); |
|
447
|
473
|
|
|
|
|
1546
|
$room -= $w; |
|
448
|
|
|
|
|
|
|
} else { |
|
449
|
0
|
|
|
|
|
0
|
die "panic ($_)"; |
|
450
|
|
|
|
|
|
|
} |
|
451
|
|
|
|
|
|
|
} |
|
452
|
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
## |
|
454
|
|
|
|
|
|
|
## --boundary=word |
|
455
|
|
|
|
|
|
|
## |
|
456
|
715
|
100
|
100
|
|
|
4187
|
if ($word_char_re |
|
|
|
|
100
|
|
|
|
|
|
457
|
|
|
|
|
|
|
and my($w2) = /\A( (?: ${word_char_re} \cH ? ) + )/x |
|
458
|
|
|
|
|
|
|
and my($lead, $w1) = $folded =~ m{ |
|
459
|
|
|
|
|
|
|
\A ## avoid CSI/OSC final char making a word |
|
460
|
|
|
|
|
|
|
( (?: [^\e\x9b\x9d]* (?:${csi_re}|${osc_re})++ ) *+ .*? ) |
|
461
|
|
|
|
|
|
|
( (?: ${word_char_re} \cH ? ) + ) |
|
462
|
|
|
|
|
|
|
\z }x |
|
463
|
|
|
|
|
|
|
) { |
|
464
|
|
|
|
|
|
|
## Break line before word only when enough space will be |
|
465
|
|
|
|
|
|
|
## provided for the word in the next turn. |
|
466
|
39
|
|
|
|
|
797
|
my $l = pwidth($w1); |
|
467
|
|
|
|
|
|
|
## prefix length |
|
468
|
39
|
100
|
|
|
|
2963
|
my $p = $opt->{prefix} eq '' ? 0 : vwidth($opt->{prefix}); |
|
469
|
39
|
100
|
66
|
|
|
873
|
if ($room + $l < $width - $p and $l + pwidth($w2) <= $width - $p |
|
|
|
|
66
|
|
|
|
|
|
470
|
|
|
|
|
|
|
and pwidth($lead) > 0) { |
|
471
|
34
|
|
|
|
|
2289
|
$folded = $lead; |
|
472
|
34
|
|
|
|
|
90
|
$_ = $w1 . pop_reset() . $_; |
|
473
|
34
|
|
|
|
|
70
|
$room += $l; |
|
474
|
|
|
|
|
|
|
} |
|
475
|
|
|
|
|
|
|
} |
|
476
|
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
## |
|
478
|
|
|
|
|
|
|
## RUN-OUT |
|
479
|
|
|
|
|
|
|
## |
|
480
|
715
|
100
|
100
|
|
|
3436
|
if ($_ ne '' and $opt->do_runout) { |
|
481
|
96
|
100
|
66
|
|
|
3135
|
if ($folded =~ m{ (? (?! ${reset_re}) ${color_re}*+ ) |
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
482
|
|
|
|
|
|
|
(? |
|
483
|
|
|
|
|
|
|
(?: ($prohibition_re{end}) (?: \cH{1,2} \g{-1})* )+ |
|
484
|
|
|
|
|
|
|
) \z |
|
485
|
|
|
|
|
|
|
}xp |
|
486
|
|
|
|
|
|
|
and ${^PREMATCH} ne '' and pwidth(${^PREMATCH}) > 0 |
|
487
|
|
|
|
|
|
|
and (my $w = pwidth $+{runout}) <= $opt->{runout}) { |
|
488
|
|
|
|
|
|
|
|
|
489
|
19
|
|
|
|
|
1479
|
$folded = ${^PREMATCH}; |
|
490
|
19
|
|
|
|
|
95
|
$_ = join '', ${^MATCH}, @reset, $_; |
|
491
|
19
|
100
|
|
|
|
523
|
pop_reset() if $+{color}; |
|
492
|
19
|
|
|
|
|
493
|
$room += $w; |
|
493
|
|
|
|
|
|
|
} |
|
494
|
|
|
|
|
|
|
} |
|
495
|
|
|
|
|
|
|
|
|
496
|
715
|
100
|
|
|
|
2091
|
$folded .= pop_reset() if @reset; |
|
497
|
|
|
|
|
|
|
|
|
498
|
715
|
|
|
|
|
1439
|
$room += $opt->{margin}; |
|
499
|
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
## |
|
501
|
|
|
|
|
|
|
## RUN-IN |
|
502
|
|
|
|
|
|
|
## |
|
503
|
715
|
100
|
|
|
|
1707
|
if ($opt->do_runin) { |
|
504
|
101
|
|
|
|
|
263
|
my @runin; |
|
505
|
101
|
|
|
|
|
184
|
my $m = $opt->{runin}; |
|
506
|
101
|
|
100
|
|
|
2318
|
while ($m > 0 and |
|
507
|
|
|
|
|
|
|
m{\A (? ${color_re}*+) |
|
508
|
|
|
|
|
|
|
(? $prohibition_re{head} ) |
|
509
|
|
|
|
|
|
|
( \cH{1,2} \g{runin} )* # multiple strike |
|
510
|
|
|
|
|
|
|
(? (?: $erase_re* $reset_re+ $erase_re* )? ) |
|
511
|
|
|
|
|
|
|
}xp) { |
|
512
|
30
|
|
|
|
|
214
|
my $w = vwidth $+{runin}; |
|
513
|
30
|
50
|
|
|
|
2790
|
last if ($m -= $w) < 0; |
|
514
|
30
|
100
|
|
|
|
179
|
$+{color} and do { push @color_stack, $+{color} }; |
|
|
2
|
|
|
|
|
13
|
|
|
515
|
30
|
100
|
|
|
|
132
|
$+{reset} and do { @color_stack = () }; |
|
|
2
|
|
|
|
|
7
|
|
|
516
|
30
|
|
|
|
|
81
|
$room -= $w; |
|
517
|
30
|
|
|
|
|
87
|
push @runin, ${^MATCH}; |
|
518
|
30
|
|
|
|
|
198
|
$_ = ${^POSTMATCH}; |
|
519
|
|
|
|
|
|
|
} |
|
520
|
101
|
100
|
|
|
|
332
|
$folded .= join '', @runin if @runin; |
|
521
|
|
|
|
|
|
|
} |
|
522
|
|
|
|
|
|
|
|
|
523
|
715
|
100
|
|
|
|
1470
|
if (@color_stack) { |
|
524
|
56
|
|
|
|
|
135
|
$folded .= SGR_RESET; |
|
525
|
56
|
50
|
|
|
|
324
|
$_ = join '', @color_stack, $_ if $_ ne ''; |
|
526
|
|
|
|
|
|
|
} |
|
527
|
715
|
100
|
|
|
|
1505
|
if (defined $osc8_link) { |
|
528
|
16
|
|
|
|
|
21
|
$folded .= OSC8_RESET; |
|
529
|
16
|
50
|
|
|
|
64
|
$_ = $osc8_link . $_ if $_ ne ''; |
|
530
|
|
|
|
|
|
|
} |
|
531
|
|
|
|
|
|
|
|
|
532
|
715
|
100
|
100
|
|
|
1911
|
if ($opt->{padding} and $room > 0) { |
|
533
|
13
|
|
|
|
|
41
|
my $padding = $opt->{padchar} x $room; |
|
534
|
13
|
100
|
|
|
|
28
|
if (@bg_stack) { |
|
535
|
1
|
|
|
|
|
6
|
$padding = join '', @bg_stack, $padding, SGR_RESET; |
|
536
|
|
|
|
|
|
|
} |
|
537
|
13
|
|
|
|
|
27
|
$folded .= $padding; |
|
538
|
|
|
|
|
|
|
} |
|
539
|
|
|
|
|
|
|
|
|
540
|
715
|
100
|
100
|
|
|
2711
|
if (length and my $p = $opt->{prefix}) { |
|
541
|
19
|
100
|
|
|
|
90
|
my $s = ref $p eq 'CODE' ? &$p : $p; |
|
542
|
19
|
|
|
|
|
84
|
$_ = $s . $_; |
|
543
|
|
|
|
|
|
|
} |
|
544
|
|
|
|
|
|
|
|
|
545
|
715
|
|
|
|
|
10015
|
($folded . $eol, $_, $width - $room); |
|
546
|
|
|
|
|
|
|
} |
|
547
|
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
## |
|
549
|
|
|
|
|
|
|
## Trim off one or more *logical* characters from the beginning of a line |
|
550
|
|
|
|
|
|
|
## |
|
551
|
|
|
|
|
|
|
sub simple_fold { |
|
552
|
473
|
|
|
473
|
0
|
935
|
my $orig = shift; |
|
553
|
473
|
|
|
|
|
675
|
my $width = shift; |
|
554
|
473
|
50
|
|
|
|
1138
|
$width <= 0 and croak "parameter error"; |
|
555
|
|
|
|
|
|
|
|
|
556
|
473
|
50
|
|
|
|
10163
|
my($left, $right) = $orig =~ m/^(\X{0,$width}+)(.*)/ |
|
557
|
|
|
|
|
|
|
or croak "$width: unexpected width"; |
|
558
|
|
|
|
|
|
|
|
|
559
|
473
|
|
|
|
|
1601
|
my $w = vwidth $left; |
|
560
|
473
|
|
|
|
|
42650
|
while ($w > $width) { |
|
561
|
14
|
|
|
14
|
|
198
|
use integer; |
|
|
14
|
|
|
|
|
59
|
|
|
|
14
|
|
|
|
|
130
|
|
|
562
|
87
|
|
|
|
|
424
|
my $trim = ($w - $width + 1) / 2; |
|
563
|
87
|
100
|
|
|
|
2876
|
$left =~ s/\X \K ( \X{$trim} ) \z//x or last; |
|
564
|
83
|
|
|
|
|
348
|
$right = $1 . $right; |
|
565
|
83
|
|
|
|
|
211
|
$w -= vwidth $1; |
|
566
|
|
|
|
|
|
|
} |
|
567
|
|
|
|
|
|
|
|
|
568
|
473
|
|
|
|
|
8860
|
($left, $right, $w); |
|
569
|
|
|
|
|
|
|
} |
|
570
|
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
###################################################################### |
|
572
|
|
|
|
|
|
|
# EXTERNAL METHODS |
|
573
|
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
sub text :lvalue { |
|
575
|
9
|
|
|
9
|
1
|
1545
|
my $obj = shift; |
|
576
|
9
|
100
|
|
|
|
26
|
if (@_ == 0) { |
|
577
|
6
|
|
|
|
|
29
|
$obj->{text}; |
|
578
|
|
|
|
|
|
|
} else { |
|
579
|
3
|
50
|
|
|
|
11
|
croak "Invalid argument" if @_ > 1; |
|
580
|
3
|
|
|
|
|
9
|
$obj->{text} = shift; |
|
581
|
3
|
|
|
|
|
13
|
$obj; |
|
582
|
|
|
|
|
|
|
} |
|
583
|
|
|
|
|
|
|
} |
|
584
|
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
sub retrieve { |
|
586
|
127
|
|
|
127
|
1
|
163
|
my $obj = shift; |
|
587
|
127
|
|
|
|
|
291
|
local *_ = \$obj->{text}; |
|
588
|
127
|
100
|
|
|
|
294
|
return '' if not defined $_; |
|
589
|
106
|
|
|
|
|
224
|
(my $folded, my $rest) = $obj->fold($_, @_); |
|
590
|
106
|
50
|
66
|
|
|
368
|
die "panic: retrieve: no progress in fold" |
|
591
|
|
|
|
|
|
|
if length $rest and $rest eq $_; |
|
592
|
106
|
100
|
|
|
|
202
|
$_ = length $rest ? $rest : undef; |
|
593
|
106
|
|
|
|
|
314
|
$folded; |
|
594
|
|
|
|
|
|
|
} |
|
595
|
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
sub chops { |
|
597
|
28
|
|
|
28
|
1
|
56
|
my $obj = shift; |
|
598
|
28
|
|
|
|
|
55
|
my %opt = @_; |
|
599
|
28
|
|
66
|
|
|
123
|
my $width = $opt{width} // $obj->{width}; |
|
600
|
|
|
|
|
|
|
|
|
601
|
28
|
|
|
|
|
40
|
my @chops; |
|
602
|
|
|
|
|
|
|
|
|
603
|
28
|
100
|
|
|
|
66
|
if (ref $width eq 'ARRAY') { |
|
604
|
10
|
|
|
|
|
12
|
for my $w (@{$width}) { |
|
|
10
|
|
|
|
|
23
|
|
|
605
|
49
|
100
|
|
|
|
149
|
if ($w == 0) { |
|
|
|
100
|
|
|
|
|
|
|
606
|
2
|
|
|
|
|
3
|
push @chops, ''; |
|
607
|
|
|
|
|
|
|
} |
|
608
|
|
|
|
|
|
|
elsif ((my $chop = $obj->retrieve(width => $w)) ne '') { |
|
609
|
43
|
|
|
|
|
128
|
push @chops, $chop; |
|
610
|
|
|
|
|
|
|
} |
|
611
|
|
|
|
|
|
|
else { |
|
612
|
4
|
|
|
|
|
8
|
last; |
|
613
|
|
|
|
|
|
|
} |
|
614
|
|
|
|
|
|
|
} |
|
615
|
|
|
|
|
|
|
} |
|
616
|
|
|
|
|
|
|
else { |
|
617
|
18
|
|
|
|
|
50
|
while ((my $chop = $obj->retrieve(width => $width)) ne '') { |
|
618
|
61
|
|
|
|
|
160
|
push @chops, $chop; |
|
619
|
|
|
|
|
|
|
} |
|
620
|
|
|
|
|
|
|
} |
|
621
|
|
|
|
|
|
|
|
|
622
|
28
|
|
|
|
|
278
|
@chops; |
|
623
|
|
|
|
|
|
|
} |
|
624
|
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
1; |
|
626
|
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
__END__ |