line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Text::ANSI::Fold; |
2
|
|
|
|
|
|
|
|
3
|
12
|
|
|
12
|
|
792910
|
use v5.14; |
|
12
|
|
|
|
|
172
|
|
4
|
12
|
|
|
12
|
|
68
|
use warnings; |
|
12
|
|
|
|
|
32
|
|
|
12
|
|
|
|
|
290
|
|
5
|
12
|
|
|
12
|
|
1235
|
use utf8; |
|
12
|
|
|
|
|
45
|
|
|
12
|
|
|
|
|
61
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = "2.2101"; |
8
|
|
|
|
|
|
|
|
9
|
12
|
|
|
12
|
|
5403
|
use Data::Dumper; |
|
12
|
|
|
|
|
57109
|
|
|
12
|
|
|
|
|
807
|
|
10
|
|
|
|
|
|
|
$Data::Dumper::Sortkeys = 1; |
11
|
12
|
|
|
12
|
|
100
|
use Carp; |
|
12
|
|
|
|
|
44
|
|
|
12
|
|
|
|
|
747
|
|
12
|
12
|
|
|
12
|
|
83
|
use List::Util qw(pairmap pairgrep); |
|
12
|
|
|
|
|
21
|
|
|
12
|
|
|
|
|
1241
|
|
13
|
12
|
|
|
12
|
|
85
|
use Scalar::Util qw(looks_like_number); |
|
12
|
|
|
|
|
20
|
|
|
12
|
|
|
|
|
616
|
|
14
|
12
|
|
|
12
|
|
5364
|
use Text::VisualWidth::PP 'vwidth'; |
|
12
|
|
|
|
|
296042
|
|
|
12
|
|
|
|
|
1594
|
|
15
|
23
|
|
|
23
|
0
|
173
|
sub pwidth { vwidth $_[0] =~ s/\X\cH{1,2}//gr } |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
###################################################################### |
18
|
12
|
|
|
12
|
|
117
|
use Exporter 'import'; |
|
12
|
|
|
|
|
25
|
|
|
12
|
|
|
|
|
1964
|
|
19
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( |
20
|
|
|
|
|
|
|
constants => [ qw( |
21
|
|
|
|
|
|
|
&LINEBREAK_NONE |
22
|
|
|
|
|
|
|
&LINEBREAK_ALL |
23
|
|
|
|
|
|
|
&LINEBREAK_RUNIN |
24
|
|
|
|
|
|
|
&LINEBREAK_RUNOUT |
25
|
|
|
|
|
|
|
) ], |
26
|
|
|
|
|
|
|
regex => [ qw( |
27
|
|
|
|
|
|
|
$reset_re |
28
|
|
|
|
|
|
|
$color_re |
29
|
|
|
|
|
|
|
$erase_re |
30
|
|
|
|
|
|
|
$csi_re |
31
|
|
|
|
|
|
|
$osc_re |
32
|
|
|
|
|
|
|
) ], |
33
|
|
|
|
|
|
|
); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
our @EXPORT_OK = ( qw(&ansi_fold), |
36
|
|
|
|
|
|
|
@{$EXPORT_TAGS{constants}}, |
37
|
|
|
|
|
|
|
@{$EXPORT_TAGS{regex}}, |
38
|
|
|
|
|
|
|
); |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub ansi_fold { |
41
|
422
|
|
|
422
|
0
|
140865
|
my($text, $width, @option) = @_; |
42
|
422
|
|
|
|
|
1372
|
__PACKAGE__->fold($text, width => $width, @option); |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
###################################################################### |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
our $alphanum_re = qr{ [_\d\p{Latin}\p{Greek}\p{Cyrillic}\p{Hangul}] }x; |
47
|
|
|
|
|
|
|
our $nonspace_re = qr{ \p{IsPrintableLatin} }x; |
48
|
|
|
|
|
|
|
our $reset_re = qr{ \e \[ [0;]* m }x; |
49
|
|
|
|
|
|
|
our $color_re = qr{ \e \[ [\d;]* m }x; |
50
|
|
|
|
|
|
|
our $erase_re = qr{ \e \[ [\d;]* K }x; |
51
|
|
|
|
|
|
|
our $csi_re = qr{ |
52
|
|
|
|
|
|
|
# see ECMA-48 5.4 Control sequences |
53
|
|
|
|
|
|
|
(?: \e\[ | \x9b ) # csi |
54
|
|
|
|
|
|
|
[\x30-\x3f]* # parameter bytes |
55
|
|
|
|
|
|
|
[\x20-\x2f]* # intermediate bytes |
56
|
|
|
|
|
|
|
[\x40-\x7e] # final byte |
57
|
|
|
|
|
|
|
}x; |
58
|
|
|
|
|
|
|
our $osc_re = qr{ |
59
|
|
|
|
|
|
|
# see ECMA-48 8.3.89 OSC - OPERATING SYSTEM COMMAND |
60
|
|
|
|
|
|
|
(?: \e\] | \x9d ) # osc |
61
|
|
|
|
|
|
|
[\x08-\x13\x20-\x7d]*+ # command |
62
|
|
|
|
|
|
|
(?: \e\\ | \x9c | \a ) # st: string terminator |
63
|
|
|
|
|
|
|
}x; |
64
|
|
|
|
|
|
|
|
65
|
12
|
|
|
12
|
|
28645
|
use constant SGR_RESET => "\e[m"; |
|
12
|
|
|
|
|
29
|
|
|
12
|
|
|
|
|
1943
|
|
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
sub IsPrintableLatin { |
68
|
2
|
|
|
2
|
0
|
1125
|
return <<"END"; |
69
|
|
|
|
|
|
|
+utf8::ASCII |
70
|
|
|
|
|
|
|
+utf8::Latin |
71
|
|
|
|
|
|
|
-utf8::White_Space |
72
|
|
|
|
|
|
|
END |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub IsWideSpacing { |
76
|
5
|
|
|
5
|
0
|
762
|
return <<"END"; |
77
|
|
|
|
|
|
|
+utf8::East_Asian_Width=Wide |
78
|
|
|
|
|
|
|
+utf8::East_Asian_Width=FullWidth |
79
|
|
|
|
|
|
|
-utf8::Nonspacing_Mark |
80
|
|
|
|
|
|
|
END |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
sub IsWideAmbiguousSpacing { |
84
|
1
|
|
|
1
|
0
|
128
|
return <<"END"; |
85
|
|
|
|
|
|
|
+utf8::East_Asian_Width=Wide |
86
|
|
|
|
|
|
|
+utf8::East_Asian_Width=FullWidth |
87
|
|
|
|
|
|
|
+utf8::East_Asian_Width=Ambiguous |
88
|
|
|
|
|
|
|
-utf8::Nonspacing_Mark |
89
|
|
|
|
|
|
|
END |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
sub _startWideSpacing { |
93
|
|
|
|
|
|
|
# look at $_ |
94
|
372
|
100
|
|
372
|
|
736
|
if ($Text::VisualWidth::PP::EastAsian) { |
95
|
2
|
|
|
|
|
17
|
/^\p{IsWideAmbiguousSpacing}/; |
96
|
|
|
|
|
|
|
} else { |
97
|
370
|
|
|
|
|
1643
|
/^\p{IsWideSpacing}/; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
use constant { |
102
|
12
|
|
|
|
|
1777
|
LINEBREAK_NONE => 0, |
103
|
|
|
|
|
|
|
LINEBREAK_RUNIN => 1, |
104
|
|
|
|
|
|
|
LINEBREAK_RUNOUT => 2, |
105
|
|
|
|
|
|
|
LINEBREAK_ALL => 3, |
106
|
12
|
|
|
12
|
|
2864
|
}; |
|
12
|
|
|
|
|
26
|
|
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
our $DEFAULT_LINEBREAK = LINEBREAK_NONE; |
109
|
|
|
|
|
|
|
our $DEFAULT_RUNIN_WIDTH = 2; |
110
|
|
|
|
|
|
|
our $DEFAULT_RUNOUT_WIDTH = 2; |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
BEGIN { |
113
|
12
|
50
|
|
12
|
|
1062
|
if ($] < 5.016) { |
114
|
0
|
|
|
|
|
0
|
require charnames; |
115
|
0
|
|
|
|
|
0
|
charnames->import(':full'); |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
our %TABSTYLE = ( |
120
|
|
|
|
|
|
|
pairmap { |
121
|
|
|
|
|
|
|
( $a =~ s/_/-/gr => ref $b ? $b : [ $b, $b ] ); |
122
|
|
|
|
|
|
|
} |
123
|
12
|
|
|
12
|
|
6444
|
symbol => [ "\N{SYMBOL FOR HORIZONTAL TABULATION}", # ␉ |
|
12
|
|
|
|
|
102649
|
|
|
12
|
|
|
|
|
82
|
|
124
|
|
|
|
|
|
|
"\N{SYMBOL FOR SPACE}" ], # ␠ |
125
|
|
|
|
|
|
|
shade => [ "\N{MEDIUM SHADE}", # ▒ |
126
|
|
|
|
|
|
|
"\N{LIGHT SHADE}" ], # ░ |
127
|
|
|
|
|
|
|
block => [ "\N{LOWER ONE QUARTER BLOCK}", # ▂ |
128
|
|
|
|
|
|
|
"\N{LOWER ONE EIGHTH BLOCK}" ], # ▁ |
129
|
|
|
|
|
|
|
bar => [ "\N{BOX DRAWINGS HEAVY RIGHT}", # ╺ |
130
|
|
|
|
|
|
|
"\N{BOX DRAWINGS LIGHT HORIZONTAL}" ], # ─ |
131
|
|
|
|
|
|
|
dash => [ "\N{BOX DRAWINGS HEAVY RIGHT}", # ╺ |
132
|
|
|
|
|
|
|
"\N{BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL}" ], # ╌ |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
dot => '.', |
135
|
|
|
|
|
|
|
space => ' ', |
136
|
|
|
|
|
|
|
emspace => "\N{EM SPACE}", # |
137
|
|
|
|
|
|
|
middle_dot => "\N{MIDDLE DOT}", # · |
138
|
|
|
|
|
|
|
arrow => "\N{RIGHTWARDS ARROW}", # → |
139
|
|
|
|
|
|
|
double_arrow => "\N{RIGHTWARDS DOUBLE ARROW}", # ⇒ |
140
|
|
|
|
|
|
|
triple_arrow => "\N{RIGHTWARDS TRIPLE ARROW}", # ⇛ |
141
|
|
|
|
|
|
|
white_arrow => "\N{RIGHTWARDS WHITE ARROW}", # ⇨ |
142
|
|
|
|
|
|
|
wave_arrow => "\N{RIGHTWARDS WAVE ARROW}", # ↝ |
143
|
|
|
|
|
|
|
circle_arrow => "\N{CIRCLED HEAVY WHITE RIGHTWARDS ARROW}", # ➲ |
144
|
|
|
|
|
|
|
curved_arrow => "\N{HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW}",# ➥ |
145
|
|
|
|
|
|
|
shadow_arrow => "\N{HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW}",# ➮ |
146
|
|
|
|
|
|
|
squat_arrow => "\N{SQUAT BLACK RIGHTWARDS ARROW}", # ➧ |
147
|
|
|
|
|
|
|
squiggle => "\N{RIGHTWARDS SQUIGGLE ARROW}", # ⇝ |
148
|
|
|
|
|
|
|
harpoon => "\N{RIGHTWARDS HARPOON WITH BARB UPWARDS}", # ⇀ |
149
|
|
|
|
|
|
|
cuneiform => "\N{CUNEIFORM SIGN TAB}", # 𒋰 |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
); |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
my @default = ( |
154
|
|
|
|
|
|
|
text => '', |
155
|
|
|
|
|
|
|
width => undef, |
156
|
|
|
|
|
|
|
padding => 0, |
157
|
|
|
|
|
|
|
boundary => '', |
158
|
|
|
|
|
|
|
padchar => ' ', |
159
|
|
|
|
|
|
|
prefix => '', |
160
|
|
|
|
|
|
|
ambiguous => 'narrow', |
161
|
|
|
|
|
|
|
margin => 0, |
162
|
|
|
|
|
|
|
linebreak => $DEFAULT_LINEBREAK, |
163
|
|
|
|
|
|
|
runin => $DEFAULT_RUNIN_WIDTH, |
164
|
|
|
|
|
|
|
runout => $DEFAULT_RUNOUT_WIDTH, |
165
|
|
|
|
|
|
|
expand => 0, |
166
|
|
|
|
|
|
|
tabstop => 8, |
167
|
|
|
|
|
|
|
tabhead => ' ', |
168
|
|
|
|
|
|
|
tabspace => ' ', |
169
|
|
|
|
|
|
|
discard => {}, |
170
|
|
|
|
|
|
|
); |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
sub new { |
173
|
13
|
|
|
13
|
0
|
1781
|
my $class = shift; |
174
|
13
|
|
|
|
|
220
|
my $obj = bless { @default }, $class; |
175
|
13
|
100
|
|
|
|
80
|
$obj->configure(@_) if @_; |
176
|
13
|
|
|
|
|
43
|
$obj; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
INTERNAL_METHODS: { |
180
|
|
|
|
|
|
|
sub spawn { |
181
|
619
|
|
|
619
|
0
|
905
|
my $obj = shift; |
182
|
619
|
|
|
|
|
996
|
my $class = ref $obj; |
183
|
619
|
|
|
658
|
|
5308
|
my %new = ( %$obj, pairgrep { defined $b } @_ ); |
|
658
|
|
|
|
|
5474
|
|
184
|
619
|
|
|
|
|
3017
|
bless \%new, $class; |
185
|
|
|
|
|
|
|
} |
186
|
619
|
100
|
|
619
|
0
|
1877
|
sub do_runin { $_[0]->{linebreak} & LINEBREAK_RUNIN && $_[0]->{runin} > 0 } |
187
|
523
|
100
|
|
523
|
0
|
2330
|
sub do_runout { $_[0]->{linebreak} & LINEBREAK_RUNOUT && $_[0]->{runout} > 0 } |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
12
|
|
|
12
|
|
228882
|
use Text::ANSI::Fold::Japanese::W3C qw(%prohibition); |
|
12
|
|
|
|
|
37
|
|
|
12
|
|
|
|
|
11792
|
|
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
sub chars_to_regex { |
193
|
24
|
|
|
24
|
0
|
7291
|
my $chars = join '', @_; |
194
|
24
|
|
|
|
|
55
|
my($c, @s); |
195
|
24
|
|
|
|
|
1136
|
for ($chars =~ /\X/g) { |
196
|
1860
|
100
|
|
|
|
3204
|
if (length == 1) { |
197
|
1848
|
|
|
|
|
2544
|
$c .= $_; |
198
|
|
|
|
|
|
|
} else { |
199
|
12
|
|
|
|
|
38
|
push @s, $_; |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
} |
202
|
24
|
100
|
|
|
|
257
|
if (@s) { |
203
|
12
|
|
|
|
|
33
|
local $" = '|'; |
204
|
12
|
|
|
|
|
935
|
qr/(?:[\Q$c\E]|@s)/; |
205
|
|
|
|
|
|
|
} else { |
206
|
12
|
|
|
|
|
410
|
qr/[\Q$c\E]/; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
my %prohibition_re = do { |
211
|
|
|
|
|
|
|
head => do { |
212
|
|
|
|
|
|
|
my $re = chars_to_regex @prohibition{qw(head postfix)}; |
213
|
|
|
|
|
|
|
qr/(?: $re | \p{Space_Separator} )/x; |
214
|
|
|
|
|
|
|
}, |
215
|
|
|
|
|
|
|
end => chars_to_regex @prohibition{qw(end prefix)}, |
216
|
|
|
|
|
|
|
}; |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
sub configure { |
219
|
47
|
|
|
47
|
0
|
13701
|
my $obj = shift; |
220
|
47
|
100
|
|
|
|
150
|
if (not ref $obj) { |
221
|
12
|
|
|
|
|
40
|
$obj = state $private = __PACKAGE__->new; |
222
|
|
|
|
|
|
|
} |
223
|
47
|
50
|
|
|
|
176
|
croak "invalid parameter" if @_ % 2; |
224
|
47
|
|
|
|
|
151
|
while (@_ >= 2) { |
225
|
71
|
|
|
|
|
236
|
my($a, $b) = splice @_, 0, 2; |
226
|
|
|
|
|
|
|
|
227
|
71
|
100
|
|
|
|
162
|
if ($a eq 'tabstyle') { |
228
|
1
|
|
50
|
|
|
6
|
$b // next; |
229
|
1
|
50
|
|
|
|
10
|
my($h, $s) = $b =~ /([-\w]+)/g or croak "$b: invalid tabstyle"; |
230
|
1
|
|
33
|
|
|
9
|
$s ||= $h; |
231
|
|
|
|
|
|
|
my %style = ( |
232
|
|
|
|
|
|
|
h => ($TABSTYLE{$h} or croak "$h: invalid tabstyle"), |
233
|
1
|
|
33
|
|
|
17
|
s => ($TABSTYLE{$s} or croak "$s: invalid tabstyle"), |
|
|
|
33
|
|
|
|
|
234
|
|
|
|
|
|
|
); |
235
|
|
|
|
|
|
|
unshift @_, |
236
|
|
|
|
|
|
|
tabhead => $style{h}->[0], |
237
|
1
|
|
|
|
|
7
|
tabspace => $style{s}->[1]; |
238
|
1
|
|
|
|
|
4
|
next; |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
70
|
50
|
|
|
|
230
|
croak "$a: invalid parameter" if not exists $obj->{$a}; |
242
|
70
|
|
|
|
|
187
|
$obj->{$a} = $b; |
243
|
|
|
|
|
|
|
} |
244
|
47
|
50
|
|
|
|
166
|
if (ref $obj->{discard} eq 'ARRAY') { |
245
|
0
|
|
|
|
|
0
|
$obj->{discard} = { map { uc $_ => 1 } @{$obj->{discard}} }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
246
|
|
|
|
|
|
|
} |
247
|
47
|
|
|
|
|
104
|
$obj; |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
my @color_stack; |
251
|
|
|
|
|
|
|
my @bg_stack; |
252
|
|
|
|
|
|
|
my @reset; |
253
|
138
|
|
|
138
|
0
|
368
|
sub put_reset { @reset = shift }; |
254
|
|
|
|
|
|
|
sub pop_reset { |
255
|
167
|
100
|
|
167
|
0
|
396
|
@reset ? do { @color_stack = (); pop @reset } : ''; |
|
138
|
|
|
|
|
252
|
|
|
138
|
|
|
|
|
273
|
|
256
|
|
|
|
|
|
|
} |
257
|
68
|
|
|
68
|
0
|
223
|
sub vlength { length $_[0] =~ s/.\cH//gr } |
258
|
|
|
|
|
|
|
|
259
|
12
|
|
|
12
|
|
106
|
use constant MAX_INT => ~0 >> 1; |
|
12
|
|
|
|
|
26
|
|
|
12
|
|
|
|
|
10428
|
|
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
sub fold { |
262
|
619
|
|
|
619
|
0
|
65506
|
my $obj = shift; |
263
|
619
|
|
50
|
|
|
1627
|
local $_ = shift // ''; |
264
|
|
|
|
|
|
|
|
265
|
619
|
100
|
|
|
|
1354
|
if (not ref $obj) { |
266
|
422
|
|
|
|
|
686
|
$obj = state $private = configure(); |
267
|
|
|
|
|
|
|
} |
268
|
619
|
|
|
|
|
1504
|
my $opt = $obj->spawn(splice @_); |
269
|
|
|
|
|
|
|
|
270
|
619
|
|
|
|
|
1185
|
my $width = $opt->{width}; |
271
|
619
|
50
|
|
|
|
1752
|
croak "invalid width" if not looks_like_number $width; |
272
|
619
|
100
|
|
|
|
1243
|
$width = MAX_INT if $width < 0; |
273
|
619
|
50
|
|
|
|
1356
|
($width -= $opt->{margin}) > 0 or croak "margin too big"; |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
my $word_char_re = |
276
|
|
|
|
|
|
|
{ word => $alphanum_re, space => $nonspace_re } |
277
|
619
|
|
50
|
|
|
2148
|
->{$opt->{boundary} // ''}; |
278
|
|
|
|
|
|
|
|
279
|
619
|
|
|
|
|
1897
|
$Text::VisualWidth::PP::EastAsian = $opt->{ambiguous} eq 'wide'; |
280
|
|
|
|
|
|
|
|
281
|
619
|
|
|
|
|
989
|
my $folded = ''; |
282
|
619
|
|
|
|
|
801
|
my $eol = ''; |
283
|
619
|
|
|
|
|
854
|
my $room = $width; |
284
|
619
|
|
|
|
|
1090
|
@bg_stack = @color_stack = @reset = (); |
285
|
619
|
100
|
|
|
|
2302
|
my $yield_re = $opt->{expand} ? qr/[^\e\n\f\r\t]/ : qr/[^\e\n\f\r]/; |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
FOLD: |
288
|
619
|
|
|
|
|
1565
|
while (length) { |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
# newline |
291
|
1774
|
50
|
|
|
|
4201
|
if (s/\A(\r*\n)//) { |
292
|
0
|
|
|
|
|
0
|
$eol = $1; |
293
|
0
|
|
|
|
|
0
|
last; |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
# formfeed / carriage return |
296
|
1774
|
50
|
|
|
|
4873
|
if (s/\A([\f\r]+)//) { |
297
|
0
|
0
|
|
|
|
0
|
last if length == 0; |
298
|
0
|
|
|
|
|
0
|
$folded .= $1; |
299
|
0
|
|
|
|
|
0
|
$room = $width; |
300
|
0
|
|
|
|
|
0
|
next; |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
# ECMA-48 OPERATING SYSTEM COMMAND |
303
|
1774
|
50
|
|
|
|
7430
|
if (s/\A($osc_re)//) { |
304
|
0
|
0
|
|
|
|
0
|
$folded .= $1 unless $obj->{discard}->{OSC}; |
305
|
0
|
|
|
|
|
0
|
next; |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
# erase line (assume 0) |
308
|
1774
|
100
|
|
|
|
5630
|
if (s/\A($erase_re)//) { |
309
|
1
|
50
|
|
|
|
5
|
$folded .= $1 unless $obj->{discard}->{EL}; |
310
|
1
|
|
|
|
|
4
|
@bg_stack = @color_stack; |
311
|
1
|
|
|
|
|
2
|
next; |
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
# reset |
314
|
1773
|
100
|
|
|
|
6027
|
if (s/\A($reset_re+($erase_re*))//) { |
315
|
138
|
|
|
|
|
390
|
put_reset($1); |
316
|
138
|
50
|
|
|
|
322
|
@bg_stack = () if $2; |
317
|
138
|
|
|
|
|
355
|
next; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
1635
|
100
|
|
|
|
3409
|
last if $room < 1; |
321
|
1127
|
100
|
100
|
|
|
2425
|
last if $room != $width and &_startWideSpacing and $room < 2; |
|
|
|
100
|
|
|
|
|
322
|
|
|
|
|
|
|
|
323
|
1119
|
100
|
|
|
|
5121
|
if (@reset) { |
324
|
97
|
|
|
|
|
187
|
$folded .= pop_reset(); |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# ANSI color sequence |
328
|
1119
|
100
|
|
|
|
3915
|
if (s/\A($color_re)//) { |
329
|
182
|
|
|
|
|
479
|
$folded .= $1; |
330
|
182
|
|
|
|
|
398
|
push @color_stack, $1; |
331
|
182
|
|
|
|
|
599
|
next; |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
# tab |
335
|
937
|
100
|
100
|
|
|
3083
|
if ($opt->{expand} and s/\A\t//) { |
336
|
112
|
|
|
|
|
260
|
my $space = $opt->{tabstop} - ($width - $room) % $opt->{tabstop}; |
337
|
112
|
|
|
|
|
315
|
$_ = $opt->{tabhead} . $opt->{tabspace} x ($space - 1) . $_; |
338
|
112
|
|
|
|
|
343
|
next; |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
# backspace |
342
|
825
|
|
|
|
|
1182
|
my $bs = 0; |
343
|
825
|
|
|
|
|
2218
|
while (s/\A(?:\X\cH+)++(?\X|\z)//p) { |
344
|
12
|
|
|
12
|
|
5415
|
my $w = vwidth($+{c}); |
|
12
|
|
|
|
|
5761
|
|
|
12
|
|
|
|
|
22145
|
|
|
839
|
|
|
|
|
2507
|
|
345
|
839
|
100
|
|
|
|
30412
|
if ($w > $room) { |
346
|
7
|
100
|
|
|
|
18
|
if ($folded eq '') { |
347
|
4
|
|
|
|
|
11
|
$folded .= ${^MATCH}; |
348
|
4
|
|
|
|
|
6
|
$room -= $w; |
349
|
|
|
|
|
|
|
} else { |
350
|
3
|
|
|
|
|
8
|
$_ = ${^MATCH} . $_; |
351
|
|
|
|
|
|
|
} |
352
|
7
|
|
|
|
|
23
|
last FOLD; |
353
|
|
|
|
|
|
|
} |
354
|
832
|
|
|
|
|
1489
|
$folded .= ${^MATCH}; |
355
|
832
|
|
|
|
|
1018
|
$room -= $w; |
356
|
832
|
|
|
|
|
1041
|
$bs++; |
357
|
832
|
100
|
|
|
|
4402
|
last if $room < 1; |
358
|
|
|
|
|
|
|
} |
359
|
818
|
100
|
|
|
|
1508
|
next if $bs; |
360
|
|
|
|
|
|
|
|
361
|
762
|
50
|
|
|
|
5227
|
if (s/\A(\e+|(?:${yield_re}(?!\cH))+)//) { |
362
|
762
|
|
|
|
|
2173
|
my $s = $1; |
363
|
762
|
100
|
|
|
|
2068
|
if ((my $w = vwidth($s)) <= $room) { |
364
|
330
|
|
|
|
|
40037
|
$folded .= $s; |
365
|
330
|
|
|
|
|
539
|
$room -= $w; |
366
|
330
|
|
|
|
|
1073
|
next; |
367
|
|
|
|
|
|
|
} |
368
|
432
|
|
|
|
|
121439
|
my($a, $b, $w) = simple_fold($s, $room); |
369
|
432
|
50
|
66
|
|
|
1153
|
if ($w > $room and $room < $width) { |
370
|
0
|
|
|
|
|
0
|
$_ = $s . $_; |
371
|
0
|
|
|
|
|
0
|
last; |
372
|
|
|
|
|
|
|
} |
373
|
432
|
|
|
|
|
1275
|
($folded, $_) = ($folded . $a, $b . $_); |
374
|
432
|
|
|
|
|
1350
|
$room -= $w; |
375
|
|
|
|
|
|
|
} else { |
376
|
0
|
|
|
|
|
0
|
die "panic ($_)"; |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
} |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
## |
381
|
|
|
|
|
|
|
## --boundary=word |
382
|
|
|
|
|
|
|
## |
383
|
619
|
100
|
100
|
|
|
5403
|
if ($word_char_re |
|
|
|
66
|
|
|
|
|
384
|
|
|
|
|
|
|
and my($w2) = /\A( (?: ${word_char_re} \cH ? ) + )/x |
385
|
|
|
|
|
|
|
and my($lead, $w1) = $folded =~ m{ |
386
|
|
|
|
|
|
|
\A ## avoid CSI final char making a word |
387
|
|
|
|
|
|
|
( (?: [^\e]* ${csi_re}++ ) *+ .*? ) |
388
|
|
|
|
|
|
|
( (?: ${word_char_re} \cH ? ) + ) |
389
|
|
|
|
|
|
|
\z }x |
390
|
|
|
|
|
|
|
) { |
391
|
|
|
|
|
|
|
## Break line before word only when enough space will be |
392
|
|
|
|
|
|
|
## provided for the word in the next turn. |
393
|
34
|
|
|
|
|
3947
|
my $l = vlength($w1); |
394
|
|
|
|
|
|
|
## prefix length |
395
|
34
|
100
|
|
|
|
138
|
my $p = $opt->{prefix} eq '' ? 0 : vwidth($opt->{prefix}); |
396
|
34
|
100
|
66
|
|
|
258
|
if ($room + $l < $width - $p and $l + vlength($w2) <= $width - $p) { |
397
|
29
|
|
|
|
|
50
|
$folded = $lead; |
398
|
29
|
|
|
|
|
74
|
$_ = $w1 . pop_reset() . $_; |
399
|
29
|
|
|
|
|
82
|
$room += $l; |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
## |
404
|
|
|
|
|
|
|
## RUN-OUT |
405
|
|
|
|
|
|
|
## |
406
|
619
|
100
|
100
|
|
|
2320
|
if ($_ ne '' and $opt->do_runout) { |
407
|
83
|
100
|
66
|
|
|
1783
|
if ($folded =~ m{ (? (?! ${reset_re}) ${color_re}*+ ) |
|
|
|
100
|
|
|
|
|
408
|
|
|
|
|
|
|
(? |
409
|
|
|
|
|
|
|
(?: ($prohibition_re{end}) (?: \cH{1,2} \g{-1})* )+ |
410
|
|
|
|
|
|
|
) \z |
411
|
|
|
|
|
|
|
}xp |
412
|
|
|
|
|
|
|
and ${^PREMATCH} ne '' |
413
|
|
|
|
|
|
|
and (my $w = pwidth $+{runout}) <= $opt->{runout}) { |
414
|
|
|
|
|
|
|
|
415
|
18
|
|
|
|
|
324
|
$folded = ${^PREMATCH}; |
416
|
18
|
|
|
|
|
66
|
$_ = join '', ${^MATCH}, @reset, $_; |
417
|
18
|
100
|
|
|
|
103
|
pop_reset() if $+{color}; |
418
|
18
|
|
|
|
|
48
|
$room += $w; |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
|
422
|
619
|
100
|
|
|
|
1450
|
$folded .= pop_reset() if @reset; |
423
|
|
|
|
|
|
|
|
424
|
619
|
|
|
|
|
1088
|
$room += $opt->{margin}; |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
## |
427
|
|
|
|
|
|
|
## RUN-IN |
428
|
|
|
|
|
|
|
## |
429
|
619
|
100
|
|
|
|
1288
|
if ($opt->do_runin) { |
430
|
87
|
|
|
|
|
135
|
my @runin; |
431
|
87
|
|
|
|
|
143
|
my $m = $opt->{runin}; |
432
|
87
|
|
100
|
|
|
1140
|
while ($m > 0 and |
433
|
|
|
|
|
|
|
m{\A (? ${color_re}*+) |
434
|
|
|
|
|
|
|
(? $prohibition_re{head} ) |
435
|
|
|
|
|
|
|
( \cH{1,2} \g{runin} )* # multiple strike |
436
|
|
|
|
|
|
|
(? (?: $erase_re* $reset_re+ $erase_re* )? ) |
437
|
|
|
|
|
|
|
}xp) { |
438
|
28
|
|
|
|
|
119
|
my $w = vwidth $+{runin}; |
439
|
28
|
50
|
|
|
|
570
|
last if ($m -= $w) < 0; |
440
|
28
|
100
|
|
|
|
125
|
$+{color} and do { push @color_stack, $+{color} }; |
|
2
|
|
|
|
|
9
|
|
441
|
28
|
100
|
|
|
|
114
|
$+{reset} and do { @color_stack = () }; |
|
2
|
|
|
|
|
5
|
|
442
|
28
|
|
|
|
|
85
|
$room -= $w; |
443
|
28
|
|
|
|
|
66
|
push @runin, ${^MATCH}; |
444
|
28
|
|
|
|
|
167
|
$_ = ${^POSTMATCH}; |
445
|
|
|
|
|
|
|
} |
446
|
87
|
100
|
|
|
|
789
|
$folded .= join '', @runin if @runin; |
447
|
|
|
|
|
|
|
} |
448
|
|
|
|
|
|
|
|
449
|
619
|
100
|
|
|
|
1305
|
if (@color_stack) { |
450
|
44
|
|
|
|
|
87
|
$folded .= SGR_RESET; |
451
|
44
|
50
|
|
|
|
161
|
$_ = join '', @color_stack, $_ if $_ ne ''; |
452
|
|
|
|
|
|
|
} |
453
|
|
|
|
|
|
|
|
454
|
619
|
100
|
100
|
|
|
1453
|
if ($opt->{padding} and $room > 0) { |
455
|
12
|
|
|
|
|
53
|
my $padding = $opt->{padchar} x $room; |
456
|
12
|
100
|
|
|
|
49
|
if (@bg_stack) { |
457
|
1
|
|
|
|
|
5
|
$padding = join '', @bg_stack, $padding, SGR_RESET; |
458
|
|
|
|
|
|
|
} |
459
|
12
|
|
|
|
|
27
|
$folded .= $padding; |
460
|
|
|
|
|
|
|
} |
461
|
|
|
|
|
|
|
|
462
|
619
|
100
|
100
|
|
|
2110
|
if (length and my $p = $opt->{prefix}) { |
463
|
19
|
100
|
|
|
|
53
|
my $s = ref $p eq 'CODE' ? &$p : $p; |
464
|
19
|
|
|
|
|
56
|
$_ = $s . $_; |
465
|
|
|
|
|
|
|
} |
466
|
|
|
|
|
|
|
|
467
|
619
|
|
|
|
|
5838
|
($folded . $eol, $_, $width - $room); |
468
|
|
|
|
|
|
|
} |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
## |
471
|
|
|
|
|
|
|
## Trim off one or more *logical* characters from the top. |
472
|
|
|
|
|
|
|
## |
473
|
|
|
|
|
|
|
sub simple_fold { |
474
|
432
|
|
|
432
|
0
|
699
|
my $orig = shift; |
475
|
432
|
|
|
|
|
900
|
my $width = shift; |
476
|
432
|
50
|
|
|
|
858
|
$width <= 0 and croak "parameter error"; |
477
|
|
|
|
|
|
|
|
478
|
432
|
50
|
|
|
|
7675
|
my($left, $right) = $orig =~ m/^(\X{0,$width}+)(.*)/ or die; |
479
|
|
|
|
|
|
|
|
480
|
432
|
|
|
|
|
1321
|
my $w = vwidth($left); |
481
|
432
|
|
|
|
|
6441
|
while ($w > $width) { |
482
|
76
|
|
|
|
|
150
|
my $trim = do { |
483
|
|
|
|
|
|
|
# use POSIX qw(ceil); |
484
|
|
|
|
|
|
|
# ceil(($w - $width) / 2) || 1; |
485
|
76
|
50
|
|
|
|
328
|
int(($w - $width) / 2 + 0.5) || 1; |
486
|
|
|
|
|
|
|
}; |
487
|
76
|
100
|
|
|
|
2046
|
$left =~ s/\X \K ( \X{$trim} ) \z//x or last; |
488
|
73
|
|
|
|
|
303
|
$right = $1 . $right; |
489
|
73
|
|
|
|
|
185
|
$w -= vwidth($1); |
490
|
|
|
|
|
|
|
} |
491
|
|
|
|
|
|
|
|
492
|
432
|
|
|
|
|
2645
|
($left, $right, $w); |
493
|
|
|
|
|
|
|
} |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
###################################################################### |
496
|
|
|
|
|
|
|
# EXTERNAL METHODS |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
sub text :lvalue { |
499
|
7
|
|
|
7
|
0
|
560
|
my $obj = shift; |
500
|
7
|
100
|
|
|
|
21
|
if (@_ == 0) { |
501
|
6
|
|
|
|
|
44
|
$obj->{text}; |
502
|
|
|
|
|
|
|
} else { |
503
|
1
|
50
|
|
|
|
5
|
croak "Invalid argument" if @_ > 1; |
504
|
1
|
|
|
|
|
3
|
$obj->{text} = shift; |
505
|
1
|
|
|
|
|
3
|
$obj; |
506
|
|
|
|
|
|
|
} |
507
|
|
|
|
|
|
|
} |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
sub retrieve { |
510
|
65
|
|
|
65
|
0
|
94
|
my $obj = shift; |
511
|
65
|
|
|
|
|
148
|
local *_ = \$obj->{text}; |
512
|
65
|
100
|
|
|
|
154
|
return '' if not defined $_; |
513
|
56
|
|
|
|
|
136
|
(my $folded, $_) = $obj->fold($_, @_); |
514
|
56
|
100
|
|
|
|
137
|
$_ = undef if length == 0; |
515
|
56
|
|
|
|
|
179
|
$folded; |
516
|
|
|
|
|
|
|
} |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
sub chops { |
519
|
15
|
|
|
15
|
0
|
36
|
my $obj = shift; |
520
|
15
|
|
|
|
|
30
|
my %opt = @_; |
521
|
15
|
|
66
|
|
|
64
|
my $width = $opt{width} // $obj->{width}; |
522
|
|
|
|
|
|
|
|
523
|
15
|
|
|
|
|
24
|
my @chops; |
524
|
|
|
|
|
|
|
|
525
|
15
|
100
|
|
|
|
40
|
if (ref $width eq 'ARRAY') { |
526
|
8
|
|
|
|
|
10
|
for my $w (@{$width}) { |
|
8
|
|
|
|
|
19
|
|
527
|
40
|
100
|
|
|
|
114
|
if ($w == 0) { |
|
|
100
|
|
|
|
|
|
528
|
2
|
|
|
|
|
4
|
push @chops, ''; |
529
|
|
|
|
|
|
|
} |
530
|
|
|
|
|
|
|
elsif ((my $chop = $obj->retrieve(width => $w)) ne '') { |
531
|
35
|
|
|
|
|
82
|
push @chops, $chop; |
532
|
|
|
|
|
|
|
} |
533
|
|
|
|
|
|
|
else { |
534
|
3
|
|
|
|
|
6
|
last; |
535
|
|
|
|
|
|
|
} |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
} |
538
|
|
|
|
|
|
|
else { |
539
|
7
|
|
|
|
|
20
|
while ((my $chop = $obj->retrieve(width => $width)) ne '') { |
540
|
19
|
|
|
|
|
52
|
push @chops, $chop; |
541
|
|
|
|
|
|
|
} |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
15
|
|
|
|
|
147
|
@chops; |
545
|
|
|
|
|
|
|
} |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
1; |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
__END__ |