line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Text::ANSI::Fold; |
2
|
|
|
|
|
|
|
|
3
|
12
|
|
|
12
|
|
784914
|
use v5.14; |
|
12
|
|
|
|
|
158
|
|
4
|
12
|
|
|
12
|
|
68
|
use warnings; |
|
12
|
|
|
|
|
25
|
|
|
12
|
|
|
|
|
300
|
|
5
|
12
|
|
|
12
|
|
1203
|
use utf8; |
|
12
|
|
|
|
|
48
|
|
|
12
|
|
|
|
|
57
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = "2.2102"; |
8
|
|
|
|
|
|
|
|
9
|
12
|
|
|
12
|
|
5333
|
use Data::Dumper; |
|
12
|
|
|
|
|
55178
|
|
|
12
|
|
|
|
|
813
|
|
10
|
|
|
|
|
|
|
$Data::Dumper::Sortkeys = 1; |
11
|
12
|
|
|
12
|
|
82
|
use Carp; |
|
12
|
|
|
|
|
26
|
|
|
12
|
|
|
|
|
754
|
|
12
|
12
|
|
|
12
|
|
76
|
use List::Util qw(pairmap pairgrep); |
|
12
|
|
|
|
|
23
|
|
|
12
|
|
|
|
|
1223
|
|
13
|
12
|
|
|
12
|
|
85
|
use Scalar::Util qw(looks_like_number); |
|
12
|
|
|
|
|
23
|
|
|
12
|
|
|
|
|
576
|
|
14
|
12
|
|
|
12
|
|
5308
|
use Text::VisualWidth::PP 'vwidth'; |
|
12
|
|
|
|
|
293452
|
|
|
12
|
|
|
|
|
1634
|
|
15
|
95
|
|
|
95
|
0
|
402
|
sub pwidth { vwidth $_[0] =~ s/\X\cH{1,2}//gr } |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
###################################################################### |
18
|
12
|
|
|
12
|
|
116
|
use Exporter 'import'; |
|
12
|
|
|
|
|
22
|
|
|
12
|
|
|
|
|
1954
|
|
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
|
429
|
|
|
429
|
0
|
142888
|
my($text, $width, @option) = @_; |
42
|
429
|
|
|
|
|
1356
|
__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
|
|
27595
|
use constant SGR_RESET => "\e[m"; |
|
12
|
|
|
|
|
27
|
|
|
12
|
|
|
|
|
1938
|
|
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
sub IsPrintableLatin { |
68
|
2
|
|
|
2
|
0
|
1043
|
return <<"END"; |
69
|
|
|
|
|
|
|
+utf8::ASCII |
70
|
|
|
|
|
|
|
+utf8::Latin |
71
|
|
|
|
|
|
|
-utf8::White_Space |
72
|
|
|
|
|
|
|
END |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub IsWideSpacing { |
76
|
5
|
|
|
5
|
0
|
746
|
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
|
135
|
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
|
374
|
100
|
|
374
|
|
658
|
if ($Text::VisualWidth::PP::EastAsian) { |
95
|
2
|
|
|
|
|
18
|
/^\p{IsWideAmbiguousSpacing}/; |
96
|
|
|
|
|
|
|
} else { |
97
|
372
|
|
|
|
|
1693
|
/^\p{IsWideSpacing}/; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
use constant { |
102
|
12
|
|
|
|
|
1725
|
LINEBREAK_NONE => 0, |
103
|
|
|
|
|
|
|
LINEBREAK_RUNIN => 1, |
104
|
|
|
|
|
|
|
LINEBREAK_RUNOUT => 2, |
105
|
|
|
|
|
|
|
LINEBREAK_ALL => 3, |
106
|
12
|
|
|
12
|
|
2876
|
}; |
|
12
|
|
|
|
|
28
|
|
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
|
|
1056
|
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
|
|
6399
|
symbol => [ "\N{SYMBOL FOR HORIZONTAL TABULATION}", # ␉ |
|
12
|
|
|
|
|
101383
|
|
|
12
|
|
|
|
|
80
|
|
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
|
1823
|
my $class = shift; |
174
|
13
|
|
|
|
|
290
|
my $obj = bless { @default }, $class; |
175
|
13
|
100
|
|
|
|
73
|
$obj->configure(@_) if @_; |
176
|
13
|
|
|
|
|
47
|
$obj; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
INTERNAL_METHODS: { |
180
|
|
|
|
|
|
|
sub spawn { |
181
|
626
|
|
|
626
|
0
|
921
|
my $obj = shift; |
182
|
626
|
|
|
|
|
986
|
my $class = ref $obj; |
183
|
626
|
|
|
672
|
|
5400
|
my %new = ( %$obj, pairgrep { defined $b } @_ ); |
|
672
|
|
|
|
|
5392
|
|
184
|
626
|
|
|
|
|
3030
|
bless \%new, $class; |
185
|
|
|
|
|
|
|
} |
186
|
626
|
100
|
|
626
|
0
|
1861
|
sub do_runin { $_[0]->{linebreak} & LINEBREAK_RUNIN && $_[0]->{runin} > 0 } |
187
|
530
|
100
|
|
530
|
0
|
2408
|
sub do_runout { $_[0]->{linebreak} & LINEBREAK_RUNOUT && $_[0]->{runout} > 0 } |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
12
|
|
|
12
|
|
225402
|
use Text::ANSI::Fold::Japanese::W3C qw(%prohibition); |
|
12
|
|
|
|
|
37
|
|
|
12
|
|
|
|
|
11107
|
|
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
sub chars_to_regex { |
193
|
24
|
|
|
24
|
0
|
7029
|
my $chars = join '', @_; |
194
|
24
|
|
|
|
|
53
|
my($c, @s); |
195
|
24
|
|
|
|
|
1150
|
for ($chars =~ /\X/g) { |
196
|
1860
|
100
|
|
|
|
3249
|
if (length == 1) { |
197
|
1848
|
|
|
|
|
2512
|
$c .= $_; |
198
|
|
|
|
|
|
|
} else { |
199
|
12
|
|
|
|
|
50
|
push @s, $_; |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
} |
202
|
24
|
100
|
|
|
|
245
|
if (@s) { |
203
|
12
|
|
|
|
|
34
|
local $" = '|'; |
204
|
12
|
|
|
|
|
905
|
qr/(?:[\Q$c\E]|@s)/; |
205
|
|
|
|
|
|
|
} else { |
206
|
12
|
|
|
|
|
341
|
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
|
13856
|
my $obj = shift; |
220
|
47
|
100
|
|
|
|
155
|
if (not ref $obj) { |
221
|
12
|
|
|
|
|
38
|
$obj = state $private = __PACKAGE__->new; |
222
|
|
|
|
|
|
|
} |
223
|
47
|
50
|
|
|
|
156
|
croak "invalid parameter" if @_ % 2; |
224
|
47
|
|
|
|
|
151
|
while (@_ >= 2) { |
225
|
71
|
|
|
|
|
187
|
my($a, $b) = splice @_, 0, 2; |
226
|
|
|
|
|
|
|
|
227
|
71
|
100
|
|
|
|
153
|
if ($a eq 'tabstyle') { |
228
|
1
|
|
50
|
|
|
4
|
$b // next; |
229
|
1
|
50
|
|
|
|
20
|
my($h, $s) = $b =~ /([-\w]+)/g or croak "$b: invalid tabstyle"; |
230
|
1
|
|
33
|
|
|
8
|
$s ||= $h; |
231
|
|
|
|
|
|
|
my %style = ( |
232
|
|
|
|
|
|
|
h => ($TABSTYLE{$h} or croak "$h: invalid tabstyle"), |
233
|
1
|
|
33
|
|
|
16
|
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
|
|
|
|
|
5
|
next; |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
70
|
50
|
|
|
|
196
|
croak "$a: invalid parameter" if not exists $obj->{$a}; |
242
|
70
|
|
|
|
|
206
|
$obj->{$a} = $b; |
243
|
|
|
|
|
|
|
} |
244
|
47
|
50
|
|
|
|
181
|
if (ref $obj->{discard} eq 'ARRAY') { |
245
|
0
|
|
|
|
|
0
|
$obj->{discard} = { map { uc $_ => 1 } @{$obj->{discard}} }; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
246
|
|
|
|
|
|
|
} |
247
|
47
|
|
|
|
|
99
|
$obj; |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
my @color_stack; |
251
|
|
|
|
|
|
|
my @bg_stack; |
252
|
|
|
|
|
|
|
my @reset; |
253
|
138
|
|
|
138
|
0
|
441
|
sub put_reset { @reset = shift }; |
254
|
|
|
|
|
|
|
sub pop_reset { |
255
|
169
|
100
|
|
169
|
0
|
393
|
@reset ? do { @color_stack = (); pop @reset } : ''; |
|
138
|
|
|
|
|
231
|
|
|
138
|
|
|
|
|
278
|
|
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
12
|
|
|
12
|
|
106
|
use constant MAX_INT => ~0 >> 1; |
|
12
|
|
|
|
|
27
|
|
|
12
|
|
|
|
|
10092
|
|
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
sub fold { |
261
|
626
|
|
|
626
|
0
|
65319
|
my $obj = shift; |
262
|
626
|
|
50
|
|
|
1552
|
local $_ = shift // ''; |
263
|
|
|
|
|
|
|
|
264
|
626
|
100
|
|
|
|
1368
|
if (not ref $obj) { |
265
|
429
|
|
|
|
|
742
|
$obj = state $private = configure(); |
266
|
|
|
|
|
|
|
} |
267
|
626
|
|
|
|
|
1957
|
my $opt = $obj->spawn(splice @_); |
268
|
|
|
|
|
|
|
|
269
|
626
|
|
|
|
|
1111
|
my $width = $opt->{width}; |
270
|
626
|
50
|
|
|
|
1807
|
croak "invalid width" if not looks_like_number $width; |
271
|
626
|
100
|
|
|
|
1268
|
$width = MAX_INT if $width < 0; |
272
|
626
|
50
|
|
|
|
1345
|
($width -= $opt->{margin}) > 0 or croak "margin too big"; |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
my $word_char_re = |
275
|
|
|
|
|
|
|
{ word => $alphanum_re, space => $nonspace_re } |
276
|
626
|
|
50
|
|
|
2222
|
->{$opt->{boundary} // ''}; |
277
|
|
|
|
|
|
|
|
278
|
626
|
|
|
|
|
1596
|
$Text::VisualWidth::PP::EastAsian = $opt->{ambiguous} eq 'wide'; |
279
|
|
|
|
|
|
|
|
280
|
626
|
|
|
|
|
939
|
my $folded = ''; |
281
|
626
|
|
|
|
|
842
|
my $eol = ''; |
282
|
626
|
|
|
|
|
829
|
my $room = $width; |
283
|
626
|
|
|
|
|
1069
|
@bg_stack = @color_stack = @reset = (); |
284
|
626
|
100
|
|
|
|
2281
|
my $yield_re = $opt->{expand} ? qr/[^\e\n\f\r\t]/ : qr/[^\e\n\f\r]/; |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
FOLD: |
287
|
626
|
|
|
|
|
1560
|
while (length) { |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
# newline |
290
|
1788
|
50
|
|
|
|
4372
|
if (s/\A(\r*\n)//) { |
291
|
0
|
|
|
|
|
0
|
$eol = $1; |
292
|
0
|
|
|
|
|
0
|
last; |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
# formfeed / carriage return |
295
|
1788
|
50
|
|
|
|
4786
|
if (s/\A([\f\r]+)//) { |
296
|
0
|
0
|
|
|
|
0
|
last if length == 0; |
297
|
0
|
|
|
|
|
0
|
$folded .= $1; |
298
|
0
|
|
|
|
|
0
|
$room = $width; |
299
|
0
|
|
|
|
|
0
|
next; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
# ECMA-48 OPERATING SYSTEM COMMAND |
302
|
1788
|
50
|
|
|
|
7826
|
if (s/\A($osc_re)//) { |
303
|
0
|
0
|
|
|
|
0
|
$folded .= $1 unless $obj->{discard}->{OSC}; |
304
|
0
|
|
|
|
|
0
|
next; |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
# erase line (assume 0) |
307
|
1788
|
100
|
|
|
|
5594
|
if (s/\A($erase_re)//) { |
308
|
1
|
50
|
|
|
|
6
|
$folded .= $1 unless $obj->{discard}->{EL}; |
309
|
1
|
|
|
|
|
4
|
@bg_stack = @color_stack; |
310
|
1
|
|
|
|
|
2
|
next; |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
# reset |
313
|
1787
|
100
|
|
|
|
6038
|
if (s/\A($reset_re+($erase_re*))//) { |
314
|
138
|
|
|
|
|
380
|
put_reset($1); |
315
|
138
|
50
|
|
|
|
315
|
@bg_stack = () if $2; |
316
|
138
|
|
|
|
|
405
|
next; |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
|
319
|
1649
|
100
|
|
|
|
3401
|
last if $room < 1; |
320
|
1136
|
100
|
100
|
|
|
2478
|
last if $room != $width and &_startWideSpacing and $room < 2; |
|
|
|
100
|
|
|
|
|
321
|
|
|
|
|
|
|
|
322
|
1126
|
100
|
|
|
|
5265
|
if (@reset) { |
323
|
97
|
|
|
|
|
182
|
$folded .= pop_reset(); |
324
|
|
|
|
|
|
|
} |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
# ANSI color sequence |
327
|
1126
|
100
|
|
|
|
3993
|
if (s/\A($color_re)//) { |
328
|
182
|
|
|
|
|
461
|
$folded .= $1; |
329
|
182
|
|
|
|
|
456
|
push @color_stack, $1; |
330
|
182
|
|
|
|
|
578
|
next; |
331
|
|
|
|
|
|
|
} |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
# tab |
334
|
944
|
100
|
100
|
|
|
3008
|
if ($opt->{expand} and s/\A\t//) { |
335
|
112
|
|
|
|
|
266
|
my $space = $opt->{tabstop} - ($width - $room) % $opt->{tabstop}; |
336
|
112
|
|
|
|
|
322
|
$_ = $opt->{tabhead} . $opt->{tabspace} x ($space - 1) . $_; |
337
|
112
|
|
|
|
|
331
|
next; |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
# backspace |
341
|
832
|
|
|
|
|
1170
|
my $bs = 0; |
342
|
832
|
|
|
|
|
2204
|
while (s/\A(?:\X\cH+)++(?\X|\z)//p) { |
343
|
12
|
|
|
12
|
|
5449
|
my $w = vwidth($+{c}); |
|
12
|
|
|
|
|
5686
|
|
|
12
|
|
|
|
|
21766
|
|
|
839
|
|
|
|
|
2533
|
|
344
|
839
|
100
|
|
|
|
30128
|
if ($w > $room) { |
345
|
7
|
100
|
|
|
|
17
|
if ($folded eq '') { |
346
|
4
|
|
|
|
|
9
|
$folded .= ${^MATCH}; |
347
|
4
|
|
|
|
|
6
|
$room -= $w; |
348
|
|
|
|
|
|
|
} else { |
349
|
3
|
|
|
|
|
8
|
$_ = ${^MATCH} . $_; |
350
|
|
|
|
|
|
|
} |
351
|
7
|
|
|
|
|
23
|
last FOLD; |
352
|
|
|
|
|
|
|
} |
353
|
832
|
|
|
|
|
1491
|
$folded .= ${^MATCH}; |
354
|
832
|
|
|
|
|
1071
|
$room -= $w; |
355
|
832
|
|
|
|
|
980
|
$bs++; |
356
|
832
|
100
|
|
|
|
4447
|
last if $room < 1; |
357
|
|
|
|
|
|
|
} |
358
|
825
|
100
|
|
|
|
1516
|
next if $bs; |
359
|
|
|
|
|
|
|
|
360
|
769
|
50
|
|
|
|
5270
|
if (s/\A(\e+|(?:${yield_re}(?!\cH))+)//) { |
361
|
769
|
|
|
|
|
1891
|
my $s = $1; |
362
|
769
|
100
|
|
|
|
1957
|
if ((my $w = vwidth($s)) <= $room) { |
363
|
330
|
|
|
|
|
41121
|
$folded .= $s; |
364
|
330
|
|
|
|
|
479
|
$room -= $w; |
365
|
330
|
|
|
|
|
1044
|
next; |
366
|
|
|
|
|
|
|
} |
367
|
439
|
|
|
|
|
117490
|
my($a, $b, $w) = simple_fold($s, $room); |
368
|
439
|
50
|
66
|
|
|
1225
|
if ($w > $room and $room < $width) { |
369
|
0
|
|
|
|
|
0
|
$_ = $s . $_; |
370
|
0
|
|
|
|
|
0
|
last; |
371
|
|
|
|
|
|
|
} |
372
|
439
|
|
|
|
|
1213
|
($folded, $_) = ($folded . $a, $b . $_); |
373
|
439
|
|
|
|
|
1431
|
$room -= $w; |
374
|
|
|
|
|
|
|
} else { |
375
|
0
|
|
|
|
|
0
|
die "panic ($_)"; |
376
|
|
|
|
|
|
|
} |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
## |
380
|
|
|
|
|
|
|
## --boundary=word |
381
|
|
|
|
|
|
|
## |
382
|
626
|
100
|
100
|
|
|
5400
|
if ($word_char_re |
|
|
|
100
|
|
|
|
|
383
|
|
|
|
|
|
|
and my($w2) = /\A( (?: ${word_char_re} \cH ? ) + )/x |
384
|
|
|
|
|
|
|
and my($lead, $w1) = $folded =~ m{ |
385
|
|
|
|
|
|
|
\A ## avoid CSI final char making a word |
386
|
|
|
|
|
|
|
( (?: [^\e]* ${csi_re}++ ) *+ .*? ) |
387
|
|
|
|
|
|
|
( (?: ${word_char_re} \cH ? ) + ) |
388
|
|
|
|
|
|
|
\z }x |
389
|
|
|
|
|
|
|
) { |
390
|
|
|
|
|
|
|
## Break line before word only when enough space will be |
391
|
|
|
|
|
|
|
## provided for the word in the next turn. |
392
|
36
|
|
|
|
|
3861
|
my $l = pwidth($w1); |
393
|
|
|
|
|
|
|
## prefix length |
394
|
36
|
100
|
|
|
|
607
|
my $p = $opt->{prefix} eq '' ? 0 : vwidth($opt->{prefix}); |
395
|
36
|
100
|
66
|
|
|
210
|
if ($room + $l < $width - $p and $l + pwidth($w2) <= $width - $p) { |
396
|
31
|
|
|
|
|
527
|
$folded = $lead; |
397
|
31
|
|
|
|
|
74
|
$_ = $w1 . pop_reset() . $_; |
398
|
31
|
|
|
|
|
57
|
$room += $l; |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
## |
403
|
|
|
|
|
|
|
## RUN-OUT |
404
|
|
|
|
|
|
|
## |
405
|
626
|
100
|
100
|
|
|
2232
|
if ($_ ne '' and $opt->do_runout) { |
406
|
83
|
100
|
66
|
|
|
1795
|
if ($folded =~ m{ (? (?! ${reset_re}) ${color_re}*+ ) |
|
|
|
100
|
|
|
|
|
407
|
|
|
|
|
|
|
(? |
408
|
|
|
|
|
|
|
(?: ($prohibition_re{end}) (?: \cH{1,2} \g{-1})* )+ |
409
|
|
|
|
|
|
|
) \z |
410
|
|
|
|
|
|
|
}xp |
411
|
|
|
|
|
|
|
and ${^PREMATCH} ne '' |
412
|
|
|
|
|
|
|
and (my $w = pwidth $+{runout}) <= $opt->{runout}) { |
413
|
|
|
|
|
|
|
|
414
|
18
|
|
|
|
|
314
|
$folded = ${^PREMATCH}; |
415
|
18
|
|
|
|
|
77
|
$_ = join '', ${^MATCH}, @reset, $_; |
416
|
18
|
100
|
|
|
|
104
|
pop_reset() if $+{color}; |
417
|
18
|
|
|
|
|
49
|
$room += $w; |
418
|
|
|
|
|
|
|
} |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
|
421
|
626
|
100
|
|
|
|
1499
|
$folded .= pop_reset() if @reset; |
422
|
|
|
|
|
|
|
|
423
|
626
|
|
|
|
|
1057
|
$room += $opt->{margin}; |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
## |
426
|
|
|
|
|
|
|
## RUN-IN |
427
|
|
|
|
|
|
|
## |
428
|
626
|
100
|
|
|
|
1356
|
if ($opt->do_runin) { |
429
|
87
|
|
|
|
|
125
|
my @runin; |
430
|
87
|
|
|
|
|
134
|
my $m = $opt->{runin}; |
431
|
87
|
|
100
|
|
|
1176
|
while ($m > 0 and |
432
|
|
|
|
|
|
|
m{\A (? ${color_re}*+) |
433
|
|
|
|
|
|
|
(? $prohibition_re{head} ) |
434
|
|
|
|
|
|
|
( \cH{1,2} \g{runin} )* # multiple strike |
435
|
|
|
|
|
|
|
(? (?: $erase_re* $reset_re+ $erase_re* )? ) |
436
|
|
|
|
|
|
|
}xp) { |
437
|
28
|
|
|
|
|
129
|
my $w = vwidth $+{runin}; |
438
|
28
|
50
|
|
|
|
583
|
last if ($m -= $w) < 0; |
439
|
28
|
100
|
|
|
|
123
|
$+{color} and do { push @color_stack, $+{color} }; |
|
2
|
|
|
|
|
8
|
|
440
|
28
|
100
|
|
|
|
115
|
$+{reset} and do { @color_stack = () }; |
|
2
|
|
|
|
|
5
|
|
441
|
28
|
|
|
|
|
51
|
$room -= $w; |
442
|
28
|
|
|
|
|
65
|
push @runin, ${^MATCH}; |
443
|
28
|
|
|
|
|
155
|
$_ = ${^POSTMATCH}; |
444
|
|
|
|
|
|
|
} |
445
|
87
|
100
|
|
|
|
840
|
$folded .= join '', @runin if @runin; |
446
|
|
|
|
|
|
|
} |
447
|
|
|
|
|
|
|
|
448
|
626
|
100
|
|
|
|
1284
|
if (@color_stack) { |
449
|
44
|
|
|
|
|
96
|
$folded .= SGR_RESET; |
450
|
44
|
50
|
|
|
|
149
|
$_ = join '', @color_stack, $_ if $_ ne ''; |
451
|
|
|
|
|
|
|
} |
452
|
|
|
|
|
|
|
|
453
|
626
|
100
|
100
|
|
|
1444
|
if ($opt->{padding} and $room > 0) { |
454
|
12
|
|
|
|
|
47
|
my $padding = $opt->{padchar} x $room; |
455
|
12
|
100
|
|
|
|
37
|
if (@bg_stack) { |
456
|
1
|
|
|
|
|
5
|
$padding = join '', @bg_stack, $padding, SGR_RESET; |
457
|
|
|
|
|
|
|
} |
458
|
12
|
|
|
|
|
29
|
$folded .= $padding; |
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
|
461
|
626
|
100
|
100
|
|
|
2204
|
if (length and my $p = $opt->{prefix}) { |
462
|
19
|
100
|
|
|
|
46
|
my $s = ref $p eq 'CODE' ? &$p : $p; |
463
|
19
|
|
|
|
|
57
|
$_ = $s . $_; |
464
|
|
|
|
|
|
|
} |
465
|
|
|
|
|
|
|
|
466
|
626
|
|
|
|
|
5923
|
($folded . $eol, $_, $width - $room); |
467
|
|
|
|
|
|
|
} |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
## |
470
|
|
|
|
|
|
|
## Trim off one or more *logical* characters from the top. |
471
|
|
|
|
|
|
|
## |
472
|
|
|
|
|
|
|
sub simple_fold { |
473
|
439
|
|
|
439
|
0
|
711
|
my $orig = shift; |
474
|
439
|
|
|
|
|
696
|
my $width = shift; |
475
|
439
|
50
|
|
|
|
872
|
$width <= 0 and croak "parameter error"; |
476
|
|
|
|
|
|
|
|
477
|
439
|
50
|
|
|
|
7147
|
my($left, $right) = $orig =~ m/^(\X{0,$width}+)(.*)/ or die; |
478
|
|
|
|
|
|
|
|
479
|
439
|
|
|
|
|
1319
|
my $w = vwidth($left); |
480
|
439
|
|
|
|
|
6730
|
while ($w > $width) { |
481
|
86
|
|
|
|
|
199
|
my $trim = do { |
482
|
|
|
|
|
|
|
# use POSIX qw(ceil); |
483
|
|
|
|
|
|
|
# ceil(($w - $width) / 2) || 1; |
484
|
86
|
50
|
|
|
|
314
|
int(($w - $width) / 2 + 0.5) || 1; |
485
|
|
|
|
|
|
|
}; |
486
|
86
|
100
|
|
|
|
2232
|
$left =~ s/\X \K ( \X{$trim} ) \z//x or last; |
487
|
83
|
|
|
|
|
285
|
$right = $1 . $right; |
488
|
83
|
|
|
|
|
203
|
$w -= vwidth($1); |
489
|
|
|
|
|
|
|
} |
490
|
|
|
|
|
|
|
|
491
|
439
|
|
|
|
|
2739
|
($left, $right, $w); |
492
|
|
|
|
|
|
|
} |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
###################################################################### |
495
|
|
|
|
|
|
|
# EXTERNAL METHODS |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
sub text :lvalue { |
498
|
7
|
|
|
7
|
0
|
592
|
my $obj = shift; |
499
|
7
|
100
|
|
|
|
55
|
if (@_ == 0) { |
500
|
6
|
|
|
|
|
46
|
$obj->{text}; |
501
|
|
|
|
|
|
|
} else { |
502
|
1
|
50
|
|
|
|
5
|
croak "Invalid argument" if @_ > 1; |
503
|
1
|
|
|
|
|
3
|
$obj->{text} = shift; |
504
|
1
|
|
|
|
|
2
|
$obj; |
505
|
|
|
|
|
|
|
} |
506
|
|
|
|
|
|
|
} |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
sub retrieve { |
509
|
65
|
|
|
65
|
0
|
125
|
my $obj = shift; |
510
|
65
|
|
|
|
|
148
|
local *_ = \$obj->{text}; |
511
|
65
|
100
|
|
|
|
147
|
return '' if not defined $_; |
512
|
56
|
|
|
|
|
141
|
(my $folded, $_) = $obj->fold($_, @_); |
513
|
56
|
100
|
|
|
|
125
|
$_ = undef if length == 0; |
514
|
56
|
|
|
|
|
183
|
$folded; |
515
|
|
|
|
|
|
|
} |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
sub chops { |
518
|
15
|
|
|
15
|
0
|
35
|
my $obj = shift; |
519
|
15
|
|
|
|
|
30
|
my %opt = @_; |
520
|
15
|
|
66
|
|
|
61
|
my $width = $opt{width} // $obj->{width}; |
521
|
|
|
|
|
|
|
|
522
|
15
|
|
|
|
|
24
|
my @chops; |
523
|
|
|
|
|
|
|
|
524
|
15
|
100
|
|
|
|
38
|
if (ref $width eq 'ARRAY') { |
525
|
8
|
|
|
|
|
13
|
for my $w (@{$width}) { |
|
8
|
|
|
|
|
18
|
|
526
|
40
|
100
|
|
|
|
114
|
if ($w == 0) { |
|
|
100
|
|
|
|
|
|
527
|
2
|
|
|
|
|
4
|
push @chops, ''; |
528
|
|
|
|
|
|
|
} |
529
|
|
|
|
|
|
|
elsif ((my $chop = $obj->retrieve(width => $w)) ne '') { |
530
|
35
|
|
|
|
|
85
|
push @chops, $chop; |
531
|
|
|
|
|
|
|
} |
532
|
|
|
|
|
|
|
else { |
533
|
3
|
|
|
|
|
6
|
last; |
534
|
|
|
|
|
|
|
} |
535
|
|
|
|
|
|
|
} |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
else { |
538
|
7
|
|
|
|
|
17
|
while ((my $chop = $obj->retrieve(width => $width)) ne '') { |
539
|
19
|
|
|
|
|
52
|
push @chops, $chop; |
540
|
|
|
|
|
|
|
} |
541
|
|
|
|
|
|
|
} |
542
|
|
|
|
|
|
|
|
543
|
15
|
|
|
|
|
139
|
@chops; |
544
|
|
|
|
|
|
|
} |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
1; |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
__END__ |