| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package App::ansifold; |
|
2
|
|
|
|
|
|
|
our $VERSION = "1.35"; |
|
3
|
|
|
|
|
|
|
|
|
4
|
90
|
|
|
90
|
|
11295568
|
use v5.14; |
|
|
90
|
|
|
|
|
329
|
|
|
5
|
90
|
|
|
90
|
|
403
|
use warnings; |
|
|
90
|
|
|
|
|
156
|
|
|
|
90
|
|
|
|
|
6012
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
90
|
|
|
90
|
|
1311
|
use open IO => 'utf8', ':std'; |
|
|
90
|
|
|
|
|
1748
|
|
|
|
90
|
|
|
|
|
611
|
|
|
8
|
90
|
|
|
90
|
|
56416
|
use Encode; |
|
|
90
|
|
|
|
|
1637111
|
|
|
|
90
|
|
|
|
|
10534
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
90
|
|
|
90
|
|
65938
|
use Pod::Usage; |
|
|
90
|
|
|
|
|
4888046
|
|
|
|
90
|
|
|
|
|
19650
|
|
|
11
|
90
|
|
|
90
|
|
1010
|
use List::Util qw(min); |
|
|
90
|
|
|
|
|
200
|
|
|
|
90
|
|
|
|
|
6330
|
|
|
12
|
90
|
|
|
90
|
|
56403
|
use Hash::Util qw(lock_keys); |
|
|
90
|
|
|
|
|
341044
|
|
|
|
90
|
|
|
|
|
762
|
|
|
13
|
90
|
|
|
90
|
|
63576
|
use Text::ANSI::Fold qw(:constants); |
|
|
90
|
|
|
|
|
5366095
|
|
|
|
90
|
|
|
|
|
20396
|
|
|
14
|
90
|
|
|
90
|
|
55817
|
use Text::ANSI::Fold::Util qw(ansi_width); { |
|
|
90
|
|
|
|
|
78577
|
|
|
|
90
|
|
|
|
|
9646
|
|
|
15
|
|
|
|
|
|
|
Text::ANSI::Fold->configure(expand => 1); |
|
16
|
|
|
|
|
|
|
} |
|
17
|
90
|
|
|
90
|
|
755
|
use Unicode::EastAsianWidth; |
|
|
90
|
|
|
|
|
201
|
|
|
|
90
|
|
|
|
|
8015
|
|
|
18
|
90
|
|
|
90
|
|
557
|
use Data::Dumper; |
|
|
90
|
|
|
|
|
161
|
|
|
|
90
|
|
|
|
|
4332
|
|
|
19
|
|
|
|
|
|
|
|
|
20
|
90
|
|
|
90
|
|
445
|
use Exporter 'import'; |
|
|
90
|
|
|
|
|
113
|
|
|
|
90
|
|
|
|
|
27612
|
|
|
21
|
|
|
|
|
|
|
our @EXPORT_OK = qw(ansifold ansiexpand ansicolrm ansicut); |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
our $DEFAULT_WIDTH //= 72; |
|
24
|
|
|
|
|
|
|
our $DEFAULT_SEPARATE //= "\n"; |
|
25
|
|
|
|
|
|
|
our $DEFAULT_EXPAND //= 0; |
|
26
|
|
|
|
|
|
|
our $DEFAULT_COLRM //= 0; |
|
27
|
|
|
|
|
|
|
our $DEFAULT_CUT //= 0; |
|
28
|
|
|
|
|
|
|
our $DEFAULT_SPLITWIDE; |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub ansifold { |
|
31
|
0
|
|
|
0
|
0
|
0
|
__PACKAGE__->new->perform(@_); |
|
32
|
|
|
|
|
|
|
} |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
sub ansiexpand { |
|
35
|
0
|
|
|
0
|
0
|
0
|
local $DEFAULT_WIDTH = -1; |
|
36
|
0
|
|
|
|
|
0
|
local $DEFAULT_EXPAND = -1; |
|
37
|
0
|
|
|
|
|
0
|
goto &ansifold; |
|
38
|
|
|
|
|
|
|
} |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub ansicolrm { |
|
41
|
0
|
|
|
0
|
0
|
0
|
local $DEFAULT_SEPARATE = ""; |
|
42
|
0
|
|
|
|
|
0
|
local $DEFAULT_COLRM = 1; |
|
43
|
0
|
|
|
|
|
0
|
goto &ansifold; |
|
44
|
|
|
|
|
|
|
} |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
sub ansicut { |
|
47
|
0
|
|
|
0
|
0
|
0
|
local $DEFAULT_SEPARATE = ""; |
|
48
|
0
|
|
|
|
|
0
|
goto &ansifold; |
|
49
|
|
|
|
|
|
|
} |
|
50
|
|
|
|
|
|
|
|
|
51
|
90
|
|
|
90
|
|
54381
|
use Getopt::EX::Hashed 'has'; { |
|
|
90
|
|
|
|
|
427083
|
|
|
|
90
|
|
|
|
|
745
|
|
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
Getopt::EX::Hashed->configure(DEFAULT => [ is => 'rw' ]); |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
has width => ' w =s@ ' , default => []; |
|
56
|
|
|
|
|
|
|
has boundary => ' =s ' , default => 'none'; |
|
57
|
|
|
|
|
|
|
has padding => ' :s ' , action => sub { |
|
58
|
|
|
|
|
|
|
$_->padding = 1; |
|
59
|
|
|
|
|
|
|
$_->padchar = $_[1] if $_[1] ne ''; |
|
60
|
|
|
|
|
|
|
}; |
|
61
|
|
|
|
|
|
|
has padchar => ' =s ' ; |
|
62
|
|
|
|
|
|
|
has prefix => ' =s ' ; |
|
63
|
|
|
|
|
|
|
has autoindent => ' =s ' ; |
|
64
|
|
|
|
|
|
|
has keepindent => ' ! ' ; |
|
65
|
|
|
|
|
|
|
has indentchar => ' =s ' , default => ' '; |
|
66
|
|
|
|
|
|
|
has ambiguous => ' =s ' ; |
|
67
|
|
|
|
|
|
|
has paragraph => ' p + ' , default => 0; |
|
68
|
|
|
|
|
|
|
has refill => ' r + ' , default => 0; |
|
69
|
|
|
|
|
|
|
has separate => ' =s ' , default => $DEFAULT_SEPARATE; |
|
70
|
|
|
|
|
|
|
has linebreak => ' =s ' , alias => 'lb'; |
|
71
|
|
|
|
|
|
|
has runin => ' =i ' , min => 0, default => 4; |
|
72
|
|
|
|
|
|
|
has runout => ' =i ' , min => 0, default => 4; |
|
73
|
|
|
|
|
|
|
has runlen => ' =i ' , min => 0; |
|
74
|
|
|
|
|
|
|
has margin => ' =i ' , min => 0; |
|
75
|
|
|
|
|
|
|
has nonewline => ' n ' ; |
|
76
|
|
|
|
|
|
|
has splitwide => ' :s ' , default => $DEFAULT_SPLITWIDE; |
|
77
|
90
|
|
|
90
|
|
36640
|
has lefthalf => ' =s ' , default => "\N{LEFT HALF BLACK CIRCLE}"; |
|
|
90
|
|
|
|
|
224
|
|
|
|
90
|
|
|
|
|
756
|
|
|
78
|
|
|
|
|
|
|
has righthalf => ' =s ' , default => "\N{RIGHT HALF BLACK CIRCLE}"; |
|
79
|
|
|
|
|
|
|
has smart => ' s ! ' ; |
|
80
|
|
|
|
|
|
|
has crmode => ' ! ' ; |
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
has '+crmode' => sub { |
|
83
|
|
|
|
|
|
|
$_->{$_[0]} = $_[1]; |
|
84
|
|
|
|
|
|
|
$_->separate = "\r" if $_[1]; |
|
85
|
|
|
|
|
|
|
}; |
|
86
|
|
|
|
|
|
|
has expand => ' x :-1 ' , default => $DEFAULT_EXPAND; |
|
87
|
|
|
|
|
|
|
has tabstop => ' =i ' , min => 1; |
|
88
|
|
|
|
|
|
|
has tabhead => ' =s ' ; |
|
89
|
|
|
|
|
|
|
has tabspace => ' =s ' ; |
|
90
|
|
|
|
|
|
|
has tabstyle => ' =s ' ; |
|
91
|
|
|
|
|
|
|
has discard => ' =s@ ' , default => []; |
|
92
|
|
|
|
|
|
|
has colrm => ' ' , default => $DEFAULT_COLRM; |
|
93
|
|
|
|
|
|
|
has cut => ' c =s ' ; |
|
94
|
|
|
|
|
|
|
has debug => ' d ' ; |
|
95
|
|
|
|
|
|
|
has help => ' h ' ; |
|
96
|
|
|
|
|
|
|
has version => ' v ' ; |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
has '+boundary' => any => [ qw(none word space) ]; |
|
99
|
|
|
|
|
|
|
has '+ambiguous' => any => [ qw(wide narrow) ] ; |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
has '+help' => sub { |
|
102
|
|
|
|
|
|
|
pod2usage |
|
103
|
|
|
|
|
|
|
-verbose => 99, |
|
104
|
|
|
|
|
|
|
-sections => [ qw(SYNOPSIS VERSION) ]; |
|
105
|
|
|
|
|
|
|
}; |
|
106
|
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
has '+version' => sub { |
|
108
|
|
|
|
|
|
|
print "Version: $VERSION\n"; |
|
109
|
|
|
|
|
|
|
exit; |
|
110
|
|
|
|
|
|
|
}; |
|
111
|
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
has '+nonewline' => sub { |
|
113
|
|
|
|
|
|
|
$_->separate = ""; |
|
114
|
|
|
|
|
|
|
}; |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
has '+linebreak' => |
|
117
|
|
|
|
|
|
|
default => LINEBREAK_NONE, |
|
118
|
|
|
|
|
|
|
action => sub { |
|
119
|
|
|
|
|
|
|
my($name, $value) = @_; |
|
120
|
|
|
|
|
|
|
$_->$name = do { |
|
121
|
|
|
|
|
|
|
local $_ = $value; |
|
122
|
|
|
|
|
|
|
my $v = LINEBREAK_NONE; |
|
123
|
|
|
|
|
|
|
$v |= LINEBREAK_ALL if /all/i; |
|
124
|
|
|
|
|
|
|
$v |= LINEBREAK_RUNIN if /runin/i; |
|
125
|
|
|
|
|
|
|
$v |= LINEBREAK_RUNOUT if /runout/i; |
|
126
|
|
|
|
|
|
|
$v; |
|
127
|
|
|
|
|
|
|
}; |
|
128
|
|
|
|
|
|
|
}; |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
### --runlen |
|
131
|
|
|
|
|
|
|
has '+runlen' => sub { |
|
132
|
|
|
|
|
|
|
$_->runin = $_->runout = $_[1]; |
|
133
|
|
|
|
|
|
|
}; |
|
134
|
|
|
|
|
|
|
# for backward compatibility, would be deplicated |
|
135
|
|
|
|
|
|
|
has run => '=i'; |
|
136
|
|
|
|
|
|
|
has '+run' => sub { |
|
137
|
|
|
|
|
|
|
$_->runin = $_->runout = $_[1]; |
|
138
|
|
|
|
|
|
|
}; |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
has '+smart' => sub { |
|
141
|
|
|
|
|
|
|
my $smart = $_->{$_[0]} = $_[1]; |
|
142
|
|
|
|
|
|
|
($_->boundary, $_->linebreak) = do { |
|
143
|
|
|
|
|
|
|
if ($smart) { |
|
144
|
|
|
|
|
|
|
('word', LINEBREAK_ALL); |
|
145
|
|
|
|
|
|
|
} else { |
|
146
|
|
|
|
|
|
|
('none', LINEBREAK_NONE); |
|
147
|
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
}; |
|
149
|
|
|
|
|
|
|
}; |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
# internal use |
|
152
|
|
|
|
|
|
|
has width_index => default => []; |
|
153
|
|
|
|
|
|
|
has indent_pat => ; |
|
154
|
|
|
|
|
|
|
has min_width => ; |
|
155
|
|
|
|
|
|
|
|
|
156
|
90
|
|
|
90
|
|
166033
|
} no Getopt::EX::Hashed; |
|
|
90
|
|
|
|
|
251
|
|
|
|
90
|
|
|
|
|
435
|
|
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
sub perform { |
|
159
|
80
|
|
|
80
|
0
|
267977976
|
my $app = shift; |
|
160
|
80
|
|
|
|
|
4834
|
local @ARGV = @_; |
|
161
|
80
|
|
|
|
|
4913
|
$app->options->params->doit; |
|
162
|
74
|
|
|
|
|
1396
|
return 0; |
|
163
|
|
|
|
|
|
|
} |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub options { |
|
166
|
80
|
|
|
80
|
0
|
1364
|
my $app = shift; |
|
167
|
|
|
|
|
|
|
|
|
168
|
80
|
|
|
|
|
1387
|
for (@ARGV) { |
|
169
|
243
|
50
|
|
|
|
17727
|
$_ = decode 'utf8', $_ unless utf8::is_utf8($_); |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
|
|
172
|
90
|
|
|
90
|
|
72594
|
use Getopt::EX::Long qw(:DEFAULT ExConfigure Configure); |
|
|
90
|
|
|
|
|
9616953
|
|
|
|
90
|
|
|
|
|
65929
|
|
|
173
|
80
|
|
|
|
|
8269
|
ExConfigure BASECLASS => [ __PACKAGE__, 'Getopt::EX' ]; |
|
174
|
80
|
|
|
|
|
19303
|
Configure "bundling"; |
|
175
|
80
|
100
|
|
|
|
13779
|
$app->getopt || pod2usage(); |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
## --colrm |
|
178
|
74
|
100
|
|
|
|
241465
|
if ($app->colrm) { |
|
|
|
100
|
|
|
|
|
|
|
179
|
7
|
|
|
|
|
66
|
my @params; |
|
180
|
7
|
|
66
|
|
|
343
|
while (@ARGV > 0 and $ARGV[0] =~ /^\d+$/) { |
|
181
|
13
|
|
|
|
|
173
|
push @params, shift @ARGV; |
|
182
|
|
|
|
|
|
|
} |
|
183
|
7
|
|
|
|
|
353
|
@{$app->width} = colrm_to_width(@params); |
|
|
7
|
|
|
|
|
73
|
|
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
## --cut |
|
186
|
|
|
|
|
|
|
elsif ($app->cut) { |
|
187
|
6
|
|
|
|
|
143
|
@{$app->width} = cut_to_width($app->cut); |
|
|
6
|
|
|
|
|
36
|
|
|
188
|
|
|
|
|
|
|
} |
|
189
|
|
|
|
|
|
|
|
|
190
|
74
|
50
|
|
|
|
3190
|
if ($app->expand > 0) { |
|
191
|
0
|
|
|
|
|
0
|
$app->tabstop = $app->expand; |
|
192
|
|
|
|
|
|
|
} |
|
193
|
|
|
|
|
|
|
|
|
194
|
74
|
|
33
|
|
|
956
|
$app->separate //= $DEFAULT_SEPARATE; |
|
195
|
|
|
|
|
|
|
|
|
196
|
90
|
|
|
90
|
|
57029
|
use charnames ':loose'; |
|
|
90
|
|
|
|
|
75768
|
|
|
|
90
|
|
|
|
|
592
|
|
|
197
|
74
|
|
|
|
|
874
|
for (@{$app}{qw(tabhead tabspace)}) { |
|
|
74
|
|
|
|
|
850
|
|
|
198
|
148
|
50
|
33
|
|
|
978
|
defined && length > 1 or next; |
|
199
|
0
|
|
0
|
|
|
0
|
$_ = charnames::string_vianame($_) || die "$_: invalid name\n"; |
|
200
|
|
|
|
|
|
|
} |
|
201
|
|
|
|
|
|
|
|
|
202
|
74
|
50
|
|
|
|
544
|
if (my $indent = $app->autoindent) { |
|
203
|
0
|
|
|
|
|
0
|
$app->indent_pat = qr/$indent/; |
|
204
|
|
|
|
|
|
|
} |
|
205
|
|
|
|
|
|
|
|
|
206
|
74
|
100
|
|
|
|
1340
|
if (defined (my $char = $app->splitwide)) { |
|
207
|
4
|
|
|
|
|
42
|
$app->splitwide = 1; |
|
208
|
4
|
50
|
|
|
|
120
|
if ($char =~ s/\A(\X)(\X)?//) { |
|
209
|
0
|
|
|
|
|
0
|
$app->lefthalf = $1; |
|
210
|
0
|
|
0
|
|
|
0
|
$app->righthalf = $2 // $1; |
|
211
|
|
|
|
|
|
|
} |
|
212
|
|
|
|
|
|
|
} |
|
213
|
|
|
|
|
|
|
|
|
214
|
74
|
|
|
|
|
4172
|
return $app; |
|
215
|
|
|
|
|
|
|
} |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
sub params { |
|
218
|
74
|
|
|
74
|
0
|
493
|
my $app = shift; |
|
219
|
|
|
|
|
|
|
|
|
220
|
90
|
|
|
90
|
|
115679
|
use Getopt::EX::Numbers; |
|
|
90
|
|
|
|
|
142378
|
|
|
|
90
|
|
|
|
|
158331
|
|
|
221
|
74
|
|
|
|
|
6446
|
my $numbers = Getopt::EX::Numbers->new; |
|
222
|
|
|
|
|
|
|
|
|
223
|
74
|
|
|
|
|
8471
|
my @width = do { |
|
224
|
|
|
|
|
|
|
map { |
|
225
|
135
|
100
|
|
|
|
3262
|
if (/^$/) { 0 } # empty |
|
|
26
|
50
|
|
|
|
477
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
226
|
109
|
|
|
|
|
918
|
elsif (/^-?\d+$/) { $_ } # number |
|
227
|
|
|
|
|
|
|
elsif (/^(-?[-\d:]+) (?:\{(\d+)\})? $/x) { # a:b:c:d{e} |
|
228
|
0
|
|
0
|
|
|
0
|
($numbers->parse($1)->sequence) x ($2 // 1); |
|
229
|
|
|
|
|
|
|
} |
|
230
|
|
|
|
|
|
|
elsif (/^=(.*)/) { |
|
231
|
0
|
|
|
|
|
0
|
require Getopt::EX::RPN; |
|
232
|
0
|
|
|
|
|
0
|
int Getopt::EX::RPN::rpn_calc(terminal_width(), $1); |
|
233
|
|
|
|
|
|
|
} |
|
234
|
0
|
|
|
|
|
0
|
else { die "$_: width format error.\n" } |
|
235
|
|
|
|
|
|
|
} |
|
236
|
66
|
|
|
|
|
734
|
map { split /,/, $_, -1 } |
|
237
|
74
|
|
|
|
|
262
|
@{$app->width}; |
|
|
74
|
|
|
|
|
584
|
|
|
238
|
|
|
|
|
|
|
}; |
|
239
|
|
|
|
|
|
|
|
|
240
|
74
|
|
|
|
|
412
|
$app->width = do { |
|
241
|
74
|
100
|
|
|
|
668
|
if (@width == 0) { $DEFAULT_WIDTH } |
|
|
8
|
100
|
|
|
|
43
|
|
|
242
|
26
|
|
|
|
|
198
|
elsif (@width == 1) { $width[0] } |
|
243
|
|
|
|
|
|
|
else { |
|
244
|
40
|
|
|
|
|
551
|
my @map = map [ abs $_ => $_ >= 0 ], @width; |
|
245
|
40
|
|
|
|
|
154
|
$map[-1] = [ $width[-1] => $width[-1] ]; |
|
246
|
40
|
|
|
|
|
276
|
@width = map $_->[0], @map; |
|
247
|
40
|
|
|
|
|
193
|
$app->width_index = [ grep { $map[$_][1] != 0 } keys @map ]; |
|
|
109
|
|
|
|
|
728
|
|
|
248
|
40
|
|
|
|
|
500
|
\@width; |
|
249
|
|
|
|
|
|
|
} |
|
250
|
|
|
|
|
|
|
}; |
|
251
|
|
|
|
|
|
|
|
|
252
|
74
|
100
|
|
|
|
1548
|
$app->min_width = ref $app->width ? min @{$app->width} : $app->width; |
|
|
40
|
|
|
|
|
1062
|
|
|
253
|
|
|
|
|
|
|
|
|
254
|
74
|
|
|
|
|
5825
|
return $app; |
|
255
|
|
|
|
|
|
|
} |
|
256
|
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
sub doit { |
|
258
|
74
|
|
|
74
|
0
|
512
|
my $app = shift; |
|
259
|
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
my $fold = Text::ANSI::Fold->new( |
|
261
|
680
|
|
|
|
|
7477
|
map { $_ => $app->$_ } |
|
262
|
74
|
|
|
|
|
559
|
grep { defined $app->$_ } |
|
|
1406
|
|
|
|
|
9774
|
|
|
263
|
|
|
|
|
|
|
qw(width boundary padding padchar prefix ambiguous |
|
264
|
|
|
|
|
|
|
margin linebreak runin runout |
|
265
|
|
|
|
|
|
|
splitwide lefthalf righthalf |
|
266
|
|
|
|
|
|
|
expand tabstyle tabstop tabhead tabspace discard) |
|
267
|
|
|
|
|
|
|
); |
|
268
|
|
|
|
|
|
|
|
|
269
|
74
|
|
33
|
1
|
|
27130
|
my $separator = eval sprintf(qq["%s"], $app->separate) // do { |
|
|
1
|
|
|
|
|
231
|
|
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
31
|
|
|
270
|
0
|
|
|
|
|
0
|
warn $@ =~ s/ at .*//r; |
|
271
|
0
|
|
|
|
|
0
|
$DEFAULT_SEPARATE; |
|
272
|
|
|
|
|
|
|
}; |
|
273
|
|
|
|
|
|
|
|
|
274
|
74
|
|
|
|
|
851
|
my @index = @{$app->width_index}; |
|
|
74
|
|
|
|
|
470
|
|
|
275
|
|
|
|
|
|
|
|
|
276
|
74
|
50
|
|
|
|
928
|
local $/ = "\n\n" if $app->refill; |
|
277
|
74
|
|
|
|
|
7170
|
while (<>) { |
|
278
|
73
|
50
|
66
|
|
|
1379
|
if (not $app->padding and s/\A(\n+)//) { |
|
279
|
0
|
|
|
|
|
0
|
print $1; |
|
280
|
0
|
0
|
|
|
|
0
|
next if length == 0; |
|
281
|
|
|
|
|
|
|
} |
|
282
|
|
|
|
|
|
|
# chomp() does not remove single "\n" when $/ is "\n\n" |
|
283
|
73
|
100
|
|
|
|
3620
|
my $chomped = s/(\R+)\z// ? $1 : ''; |
|
284
|
73
|
50
|
|
|
|
465
|
my $eol = $chomped =~ /\r/ ? "\r\n" : "\n"; |
|
285
|
73
|
50
|
|
|
|
351
|
fill_paragraph() if $app->refill; |
|
286
|
73
|
100
|
|
|
|
968
|
fill_cr() if $app->crmode; |
|
287
|
73
|
50
|
33
|
|
|
1098
|
if ($app->{indent_pat} && /^$app->{indent_pat}/p) { |
|
288
|
0
|
|
|
|
|
0
|
my $matched = ${^MATCH}; |
|
289
|
0
|
|
|
|
|
0
|
my $indent = ansi_width $matched; |
|
290
|
0
|
0
|
|
|
|
0
|
if ($indent >= $app->min_width) { |
|
291
|
0
|
|
|
|
|
0
|
die sprintf("%s\n%s\n%s\n", $_, ("^" x $indent), |
|
292
|
|
|
|
|
|
|
"ERROR: Autoindent pattern is longer than folding width."); |
|
293
|
|
|
|
|
|
|
} |
|
294
|
0
|
|
|
|
|
0
|
my $prefix = do { |
|
295
|
0
|
0
|
|
|
|
0
|
if ($app->keepindent) { |
|
296
|
0
|
|
|
|
|
0
|
$matched; |
|
297
|
|
|
|
|
|
|
} else { |
|
298
|
0
|
|
|
|
|
0
|
$app->indentchar x $indent; |
|
299
|
|
|
|
|
|
|
} |
|
300
|
|
|
|
|
|
|
}; |
|
301
|
0
|
|
|
|
|
0
|
$fold->configure(prefix => $prefix); |
|
302
|
|
|
|
|
|
|
} |
|
303
|
73
|
|
|
|
|
2196
|
my @chops = $fold->text($_)->chops; |
|
304
|
73
|
100
|
|
|
|
1082400
|
if (ref $app->width eq 'ARRAY') { |
|
305
|
40
|
|
|
|
|
515
|
while (my($i, $w) = each @{$app->width}) { |
|
|
149
|
|
|
|
|
464
|
|
|
306
|
109
|
50
|
33
|
|
|
2650
|
$w = 0 if not $app->padding or $w < 0; |
|
307
|
109
|
|
66
|
|
|
895
|
$chops[$i] //= ' ' x $w; |
|
308
|
|
|
|
|
|
|
} |
|
309
|
|
|
|
|
|
|
} |
|
310
|
73
|
100
|
|
|
|
834
|
if (@index > 0) { |
|
311
|
40
|
|
|
|
|
182
|
@chops = grep { defined } @chops[@index]; |
|
|
65
|
|
|
|
|
243
|
|
|
312
|
|
|
|
|
|
|
} |
|
313
|
73
|
|
|
|
|
6093
|
print join $separator, @chops; |
|
314
|
73
|
100
|
|
|
|
780
|
print $chomped if $chomped; |
|
315
|
73
|
50
|
|
|
|
510
|
print $eol x $app->paragraph if $app->paragraph > 0; |
|
316
|
|
|
|
|
|
|
} |
|
317
|
|
|
|
|
|
|
|
|
318
|
74
|
|
|
|
|
4998
|
return $app; |
|
319
|
|
|
|
|
|
|
} |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
sub InConcatScript { |
|
322
|
14
|
|
|
14
|
0
|
1286
|
return <<"END"; |
|
323
|
|
|
|
|
|
|
+App::ansifold::InFullwidth |
|
324
|
|
|
|
|
|
|
-utf8::Hangul |
|
325
|
|
|
|
|
|
|
END |
|
326
|
|
|
|
|
|
|
} |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
sub InFullwidthPunctuation { |
|
329
|
14
|
|
|
14
|
0
|
1306
|
return <<"END"; |
|
330
|
|
|
|
|
|
|
+App::ansifold::InFullwidth |
|
331
|
|
|
|
|
|
|
&utf8::Punctuation |
|
332
|
|
|
|
|
|
|
END |
|
333
|
|
|
|
|
|
|
} |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
sub fill_up { |
|
336
|
18
|
|
33
|
18
|
0
|
81
|
my $pat = shift // qr/\R/; |
|
337
|
18
|
|
|
|
|
552
|
s/(?<=\p{InFullwidthPunctuation})$pat//g; |
|
338
|
18
|
|
|
|
|
15786
|
s/(?<=\p{InConcatScript})$pat(?=\p{InConcatScript})//g; |
|
339
|
18
|
|
|
|
|
445
|
s/[ ]*$pat[ ]*/ /g; |
|
340
|
|
|
|
|
|
|
} |
|
341
|
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
sub fill_paragraph { |
|
343
|
0
|
|
|
0
|
0
|
0
|
fill_up(qr/\R/); |
|
344
|
|
|
|
|
|
|
} |
|
345
|
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
sub fill_cr { |
|
347
|
18
|
|
|
18
|
0
|
545
|
fill_up(qr/\r/); |
|
348
|
|
|
|
|
|
|
} |
|
349
|
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
sub terminal_width { |
|
351
|
90
|
|
|
90
|
|
52574
|
use Term::ReadKey; |
|
|
90
|
|
|
|
|
230875
|
|
|
|
90
|
|
|
|
|
78003
|
|
|
352
|
0
|
|
|
0
|
0
|
0
|
my $default = 80; |
|
353
|
0
|
|
|
|
|
0
|
my @size; |
|
354
|
0
|
0
|
|
|
|
0
|
if (open my $tty, ">", "/dev/tty") { |
|
355
|
|
|
|
|
|
|
# Term::ReadKey 2.31 on macOS 10.15 has a bug in argument handling |
|
356
|
|
|
|
|
|
|
# and the latest version 2.38 fails to install. |
|
357
|
|
|
|
|
|
|
# This code should work on both versions. |
|
358
|
0
|
|
|
|
|
0
|
@size = GetTerminalSize $tty, $tty; |
|
359
|
|
|
|
|
|
|
} |
|
360
|
0
|
0
|
|
|
|
0
|
$size[0] or $default; |
|
361
|
|
|
|
|
|
|
} |
|
362
|
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
sub colrm_to_width { |
|
364
|
7
|
|
|
7
|
0
|
25
|
my @width; |
|
365
|
7
|
|
|
|
|
75
|
my $pos = 0; |
|
366
|
7
|
|
|
|
|
68
|
while (my($start, $end) = splice @_, 0, 2) { |
|
367
|
8
|
50
|
|
|
|
38
|
$pos < $start or die "$start: invalid arg\n"; |
|
368
|
8
|
|
|
|
|
24
|
$start--; |
|
369
|
8
|
100
|
|
|
|
125
|
push @width, |
|
370
|
|
|
|
|
|
|
$start - $pos, |
|
371
|
|
|
|
|
|
|
defined $end ? $start - $end : ''; |
|
372
|
8
|
|
100
|
|
|
44
|
$pos = $end // last; |
|
373
|
|
|
|
|
|
|
} |
|
374
|
7
|
100
|
100
|
|
|
178
|
push @width, -1 if @width == 0 or $width[-1] ne ''; |
|
375
|
7
|
|
|
|
|
49
|
join ',', @width; |
|
376
|
|
|
|
|
|
|
} |
|
377
|
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
sub cut_to_width { |
|
379
|
6
|
|
|
6
|
0
|
327
|
my $list = shift; |
|
380
|
6
|
|
|
|
|
277
|
my @params = split /[\s,]+/, $list; |
|
381
|
6
|
|
|
|
|
73
|
my @width; |
|
382
|
6
|
|
|
|
|
20
|
my $pos = 1; |
|
383
|
6
|
|
|
|
|
18
|
for (@params) { |
|
384
|
11
|
50
|
|
|
|
103
|
next if $_ eq ''; |
|
385
|
11
|
50
|
|
|
|
381
|
my($start, $end) = |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
/^(\d+)$/ ? ( $1, $1 ) : |
|
387
|
|
|
|
|
|
|
/^-(\d+)/ ? ( $pos, $1 ) : |
|
388
|
|
|
|
|
|
|
/^(\d+)-$/ ? ( $1, -1 ) : |
|
389
|
|
|
|
|
|
|
/^(\d+)-(\d+)$/ ? ( $1, $2 ) : die "$list: format error"; |
|
390
|
11
|
50
|
|
|
|
61
|
$pos <= $start or die "$start: invalid arg\n"; |
|
391
|
11
|
100
|
|
|
|
46
|
if ($start > $pos) { |
|
392
|
7
|
|
|
|
|
18
|
push @width, $pos - $start; |
|
393
|
|
|
|
|
|
|
} |
|
394
|
11
|
100
|
|
|
|
31
|
if ($end < 0) { |
|
395
|
1
|
|
|
|
|
12
|
push @width, -1; |
|
396
|
1
|
|
|
|
|
3
|
last; |
|
397
|
|
|
|
|
|
|
} else { |
|
398
|
10
|
|
|
|
|
25
|
push @width, $end - $start + 1; |
|
399
|
|
|
|
|
|
|
} |
|
400
|
10
|
|
|
|
|
21
|
$pos = $end + 1; |
|
401
|
|
|
|
|
|
|
} |
|
402
|
6
|
100
|
|
|
|
21
|
push @width, 0 if $width[-1] != -1; |
|
403
|
6
|
|
|
|
|
46
|
join ',', @width; |
|
404
|
|
|
|
|
|
|
} |
|
405
|
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
1; |
|
407
|
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
__END__ |