| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#!/usr/bin/env perl |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
## |
|
4
|
|
|
|
|
|
|
## sdif: sdiff clone |
|
5
|
|
|
|
|
|
|
## |
|
6
|
|
|
|
|
|
|
## Copyright (c) 1992- Kazumasa Utashiro |
|
7
|
|
|
|
|
|
|
## |
|
8
|
|
|
|
|
|
|
## Original version on Jul 24 1991 |
|
9
|
|
|
|
|
|
|
## |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=pod |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 NAME |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
sdif - side-by-side diff viewer for ANSI terminal |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 VERSION |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
Version 4.44 |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
sdif file_1 file_2 |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
diff ... | sdif |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
OPTIONS: |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
-i, --ignore-case |
|
30
|
|
|
|
|
|
|
-b, --ignore-space-change |
|
31
|
|
|
|
|
|
|
-w, --ignore-all-space |
|
32
|
|
|
|
|
|
|
-B, --ignore-blank-lines |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
--[no]number, -n print line number |
|
35
|
|
|
|
|
|
|
--digit=# set the line number digits (default 4) |
|
36
|
|
|
|
|
|
|
--truncate, -t truncate long line |
|
37
|
|
|
|
|
|
|
--boundary=# line folding boundary (default word) |
|
38
|
|
|
|
|
|
|
--context, -c, -C# context diff |
|
39
|
|
|
|
|
|
|
--unified, -u, -U# unified diff |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
--width=#, -W# width of output (default 80) |
|
42
|
|
|
|
|
|
|
--margin=# margin column number (default 0) |
|
43
|
|
|
|
|
|
|
--runin=# run-in column number (default --margin) |
|
44
|
|
|
|
|
|
|
--runout=# run-out column number (default --margin) |
|
45
|
|
|
|
|
|
|
--mark=position mark position (right, left, center, side) or no |
|
46
|
|
|
|
|
|
|
--column=order column order (default ONM) |
|
47
|
|
|
|
|
|
|
--view, -v viewer mode |
|
48
|
|
|
|
|
|
|
--parallel[=#], -V treat unknown text as common part (default 2) |
|
49
|
|
|
|
|
|
|
--ambiguous=s ambiguous character width (detect, wide, narrow) |
|
50
|
|
|
|
|
|
|
--[no-]command print diff control command (default on) |
|
51
|
|
|
|
|
|
|
--[no-]filename print diff filename (default on) |
|
52
|
|
|
|
|
|
|
--[no-]prefix process git --graph output (default on) |
|
53
|
|
|
|
|
|
|
--prefix-pattern prefix pattern |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
--color=when 'always' (default), 'never' or 'auto' |
|
56
|
|
|
|
|
|
|
--nocolor --color=never |
|
57
|
|
|
|
|
|
|
--colormap, --cm specify color map |
|
58
|
|
|
|
|
|
|
--colortable[=#] show color table (optional #: 6, 12, 24) |
|
59
|
|
|
|
|
|
|
--[no-]256 on/off ANSI 256 color mode (default on) |
|
60
|
|
|
|
|
|
|
--[no-]cc color command line (default true) |
|
61
|
|
|
|
|
|
|
--[no-]fc file name (default true) |
|
62
|
|
|
|
|
|
|
--[no-]lc line number (default true) |
|
63
|
|
|
|
|
|
|
--[no-]mc diff mark (default true) |
|
64
|
|
|
|
|
|
|
--[no-]tc normal text (default true) |
|
65
|
|
|
|
|
|
|
--[no-]uc unknown text (default true) |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
--man display manual page |
|
68
|
|
|
|
|
|
|
--version show version |
|
69
|
|
|
|
|
|
|
--diff=s set diff command |
|
70
|
|
|
|
|
|
|
--diffopts=s set diff command options |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
--[no-]lenience suppress unexpected input warning (default on) |
|
73
|
|
|
|
|
|
|
--visible xx=1 set visible chars |
|
74
|
|
|
|
|
|
|
--tabhead=char set tabhead char |
|
75
|
|
|
|
|
|
|
--tabspace=char set tabspace char |
|
76
|
|
|
|
|
|
|
--tabstyle=style set tabstyle (dot, symbol, shade, bar, dash...) |
|
77
|
|
|
|
|
|
|
--tabstop=# set tabstop width (default 8) |
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
--[no-]cdif use ``cdif'' as word context diff backend |
|
80
|
|
|
|
|
|
|
--unit=s pass through to cdif (word, letter, char, mecab) |
|
81
|
|
|
|
|
|
|
--cdifopts=s set cdif command options |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=cut |
|
84
|
|
|
|
|
|
|
|
|
85
|
5
|
|
|
5
|
|
31595
|
use v5.14; |
|
|
5
|
|
|
|
|
19
|
|
|
86
|
5
|
|
|
5
|
|
30
|
use warnings; |
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
466
|
|
|
87
|
5
|
|
|
5
|
|
3016
|
use utf8; |
|
|
5
|
|
|
|
|
1904
|
|
|
|
5
|
|
|
|
|
36
|
|
|
88
|
5
|
|
|
5
|
|
5352
|
use Encode; |
|
|
5
|
|
|
|
|
136622
|
|
|
|
5
|
|
|
|
|
857
|
|
|
89
|
5
|
|
|
5
|
|
3423
|
use open IO => ':utf8'; |
|
|
5
|
|
|
|
|
8345
|
|
|
|
5
|
|
|
|
|
32
|
|
|
90
|
5
|
|
|
5
|
|
624
|
use Carp; |
|
|
5
|
|
|
|
|
9
|
|
|
|
5
|
|
|
|
|
441
|
|
|
91
|
5
|
|
|
5
|
|
3166
|
use charnames ':full'; |
|
|
5
|
|
|
|
|
60188
|
|
|
|
5
|
|
|
|
|
45
|
|
|
92
|
5
|
|
|
5
|
|
144782
|
use List::Util qw(min max reduce sum pairmap first); |
|
|
5
|
|
|
|
|
21
|
|
|
|
5
|
|
|
|
|
1048
|
|
|
93
|
5
|
|
|
5
|
|
3171
|
use Pod::Usage; |
|
|
5
|
|
|
|
|
330578
|
|
|
|
5
|
|
|
|
|
907
|
|
|
94
|
5
|
|
|
5
|
|
3403
|
use Text::ParseWords qw(shellwords); |
|
|
5
|
|
|
|
|
10217
|
|
|
|
5
|
|
|
|
|
439
|
|
|
95
|
5
|
|
|
5
|
|
3739
|
use Data::Dumper; { |
|
|
5
|
|
|
|
|
47963
|
|
|
|
5
|
|
|
|
|
673
|
|
|
96
|
5
|
|
|
|
|
1142067
|
$Data::Dumper::Terse = 1; |
|
|
5
|
|
|
|
|
19
|
|
|
97
|
|
|
|
|
|
|
} |
|
98
|
|
|
|
|
|
|
|
|
99
|
5
|
|
|
5
|
|
3046
|
use App::sdif; |
|
|
5
|
|
|
|
|
14
|
|
|
|
5
|
|
|
|
|
519
|
|
|
100
|
5
|
|
|
|
|
27
|
my $version = $App::sdif::VERSION; |
|
101
|
|
|
|
|
|
|
|
|
102
|
5
|
|
|
5
|
|
2899
|
use App::sdif::Util; |
|
|
5
|
|
|
|
|
15
|
|
|
|
5
|
|
|
|
|
937
|
|
|
103
|
5
|
|
|
5
|
|
3095
|
use IO::Divert; |
|
|
5
|
|
|
|
|
4923
|
|
|
|
5
|
|
|
|
|
957
|
|
|
104
|
|
|
|
|
|
|
|
|
105
|
5
|
|
|
|
|
15
|
my $default_cdif = 'cdif'; |
|
106
|
5
|
|
|
|
|
17
|
my @default_cdifopts = qw(--sdif); |
|
107
|
5
|
|
|
|
|
13
|
my $default_lenience = 1; |
|
108
|
5
|
|
|
|
|
12
|
my $default_256 = 1; |
|
109
|
5
|
|
|
|
|
10
|
my $default_prefix = 1; |
|
110
|
5
|
|
|
|
|
13
|
my $default_prefix_pattern = q/(?:\\| )*(?: )?/; |
|
111
|
5
|
|
|
|
|
36
|
my @cdifopts; |
|
112
|
|
|
|
|
|
|
my $read_stdin; |
|
113
|
|
|
|
|
|
|
|
|
114
|
5
|
|
|
|
|
12
|
our $screen_width; |
|
115
|
|
|
|
|
|
|
|
|
116
|
5
|
50
|
|
|
|
31
|
if (my $env = $ENV{'SDIFOPTS'}) { |
|
117
|
0
|
|
|
|
|
0
|
unshift @ARGV, shellwords($env); |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
|
|
120
|
5
|
|
|
5
|
|
43
|
use open IO => ':utf8', ':std'; |
|
|
5
|
|
|
|
|
8
|
|
|
|
5
|
|
|
|
|
48
|
|
|
121
|
5
|
50
|
|
|
|
15
|
map { $_ = decode 'utf8', $_ unless utf8::is_utf8($_) } @ARGV; |
|
|
9
|
|
|
|
|
268
|
|
|
122
|
|
|
|
|
|
|
|
|
123
|
5
|
|
|
|
|
121
|
my $app; |
|
124
|
|
|
|
|
|
|
|
|
125
|
5
|
|
|
5
|
|
4410
|
use Getopt::EX::Hashed; { |
|
|
5
|
|
|
|
|
51833
|
|
|
|
5
|
|
|
|
|
38
|
|
|
126
|
|
|
|
|
|
|
|
|
127
|
5
|
|
|
|
|
12
|
Getopt::EX::Hashed->configure( DEFAULT => [ is => 'rw' ] ); |
|
|
5
|
|
|
|
|
69
|
|
|
128
|
|
|
|
|
|
|
|
|
129
|
5
|
|
|
|
|
229
|
has help => ' h ' ; |
|
130
|
5
|
|
|
|
|
347
|
has version => ' ' ; |
|
131
|
5
|
|
|
|
|
316
|
has man => ' ' ; |
|
132
|
5
|
|
|
|
|
254
|
has debug => 'd + ' ; |
|
133
|
5
|
|
|
|
|
230
|
has number => 'n ! ' ; |
|
134
|
5
|
|
|
|
|
234
|
has digit => ' =i ' , default => 4 ; |
|
135
|
5
|
|
|
|
|
321
|
has column => ' =s ' ; |
|
136
|
5
|
|
|
|
|
289
|
has truncate => 't ! ' ; |
|
137
|
5
|
|
|
|
|
303
|
has boundary => ' =s ' , default => 'word' ; |
|
138
|
5
|
|
|
|
|
290
|
has onword => ' ! ' ; |
|
139
|
5
|
|
|
|
|
307
|
has mark => ' =s ' , default => 'center' ; |
|
140
|
5
|
|
|
|
|
294
|
has prefix => ' ! ' , default => $default_prefix ; |
|
141
|
5
|
|
|
|
|
311
|
has prefix_pattern => ' =s ' , default => $default_prefix_pattern ; |
|
142
|
5
|
|
|
|
|
309
|
has width => 'W =i ' ; |
|
143
|
5
|
|
|
|
|
268
|
has margin => ' =i ' , default => 0 ; |
|
144
|
5
|
|
|
|
|
298
|
has runin => ' =i ' ; |
|
145
|
5
|
|
|
|
|
286
|
has runout => ' =i ' ; |
|
146
|
5
|
|
|
|
|
284
|
has view => 'v ! ' ; |
|
147
|
5
|
|
|
|
|
290
|
has parallel => 'V :2 ' , default => 0 ; |
|
148
|
5
|
|
|
|
|
423
|
has ambiguous => ' =s ' , default => 'narrow' ; |
|
149
|
5
|
|
|
|
|
369
|
has filename => ' ! ' , default => 1 ; |
|
150
|
5
|
|
|
|
|
409
|
has command => ' ! ' , default => 1 ; |
|
151
|
5
|
|
|
|
|
329
|
has diff => ' =s ' , default => 'diff' ; |
|
152
|
5
|
|
|
|
|
334
|
has diffopts => ' =s@' , default => [] ; |
|
153
|
5
|
|
|
|
|
409
|
has color => ' =s ' , default => 'always' ; |
|
154
|
5
|
|
|
|
|
419
|
has colormap => 'cm=s@' , default => [] ; |
|
155
|
5
|
|
|
|
|
379
|
has colordump => ' ' ; |
|
156
|
5
|
|
|
|
|
479
|
has 256 => ' ! ' , default => $default_256 ; |
|
157
|
5
|
|
|
|
|
439
|
has commandcolor => 'cc! ' , default => 1 ; |
|
158
|
5
|
|
|
|
|
354
|
has filecolor => 'fc! ' , default => 1 ; |
|
159
|
5
|
|
|
|
|
454
|
has linecolor => 'lc! ' , default => 1 ; |
|
160
|
5
|
|
|
|
|
416
|
has markcolor => 'mc! ' , default => 1 ; |
|
161
|
5
|
|
|
|
|
396
|
has textcolor => 'tc! ' , default => 1 ; |
|
162
|
5
|
|
|
|
|
369
|
has unknowncolor => 'uc! ' , default => 1 ; |
|
163
|
5
|
|
|
|
|
385
|
has cdif => ' :s ' , default => '' ; |
|
164
|
5
|
|
|
|
|
451
|
has cdifopts => ' =s ' ; |
|
165
|
5
|
|
|
|
|
401
|
has colortable => ' :s ' , any => qr/^(|6|12|24)$/ ; |
|
166
|
5
|
|
|
|
|
419
|
has lenience => ' ! ' , default => $default_lenience ; |
|
167
|
5
|
|
|
|
|
464
|
has visible => ' =i%' , default => {} ; |
|
168
|
5
|
|
|
|
|
461
|
has tabstop => ' =i ' , default => 8 ; |
|
169
|
5
|
|
|
|
|
527
|
has tabhead => ' =s ' ; |
|
170
|
5
|
|
|
|
|
475
|
has tabstyle => 'ts=s ' ; |
|
171
|
5
|
|
|
|
|
504
|
has tabspace => ' =s ' ; |
|
172
|
5
|
|
|
|
|
464
|
has unit => 'by:s ' ; |
|
173
|
|
|
|
|
|
|
|
|
174
|
5
|
|
|
|
|
538
|
has ignore_case => 'i ' ; |
|
175
|
5
|
|
|
|
|
606
|
has ignore_space_change => 'b ' ; |
|
176
|
5
|
|
|
|
|
459
|
has ignore_all_space => 'w ' ; |
|
177
|
5
|
|
|
|
|
439
|
has ignore_blank_lines => 'B ' ; |
|
178
|
5
|
|
|
|
|
497
|
has context => 'C =i' ; |
|
179
|
5
|
|
|
|
|
460
|
has unified => 'U =i' ; |
|
180
|
5
|
|
|
|
|
453
|
has c => ' ' ; |
|
181
|
5
|
|
|
|
|
532
|
has u => ' ' ; |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
has '+onword' |
|
184
|
5
|
0
|
|
0
|
|
555
|
=> sub { $_->boundary = $_[1] ? 'word' : '' } ; |
|
|
0
|
|
|
|
|
0
|
|
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
has '+cdifopts' |
|
187
|
5
|
|
|
0
|
|
303
|
=> sub { push @cdifopts, shellwords $_[1] } ; |
|
|
0
|
|
|
|
|
0
|
|
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
has '+ignore_case' |
|
190
|
5
|
|
|
0
|
|
447
|
=> sub { push @{$app->diffopts}, '-i'; push @cdifopts, '-i' } ; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
191
|
|
|
|
|
|
|
has '+ignore_space_change' |
|
192
|
5
|
|
|
0
|
|
627
|
=> sub { push @{$app->diffopts}, '-b'; push @cdifopts, '-w' } ; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
193
|
|
|
|
|
|
|
has '+ignore_all_space' |
|
194
|
5
|
|
|
0
|
|
545
|
=> sub { push @{$app->diffopts}, '-w'; push @cdifopts, '-w' } ; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
195
|
|
|
|
|
|
|
has '+ignore_blank_lines' |
|
196
|
5
|
|
|
0
|
|
475
|
=> sub { push @{$app->diffopts}, '-B' } ; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
197
|
|
|
|
|
|
|
|
|
198
|
5
|
|
|
0
|
|
443
|
has '+c' => sub { push @{$app->diffopts}, '-c' } ; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
199
|
5
|
|
|
0
|
|
532
|
has '+u' => sub { push @{$app->diffopts}, '-u' } ; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
200
|
5
|
|
|
0
|
|
567
|
has '+context' => sub { push @{$app->diffopts}, '-C' . $_[1] } ; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
201
|
5
|
|
|
0
|
|
502
|
has '+unified' => sub { push @{$app->diffopts}, '-U' . $_[1] } ; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
202
|
|
|
|
|
|
|
|
|
203
|
5
|
|
|
0
|
|
461
|
has nocolor => 'no-color' , action => sub { $app->color = 'never' } ; |
|
|
0
|
|
|
|
|
0
|
|
|
204
|
5
|
|
|
0
|
|
583
|
has nocdif => 'no-cdif' , action => sub { $app->cdif = undef } ; |
|
|
0
|
|
|
|
|
0
|
|
|
205
|
|
|
|
|
|
|
|
|
206
|
5
|
0
|
|
0
|
|
619
|
has mecab => '!' , action => sub { $app->unit = $_[1] ? 'mecab' : undef } ; |
|
|
0
|
|
|
|
|
0
|
|
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
has '+ambiguous' => sub { |
|
209
|
0
|
0
|
|
0
|
|
0
|
if ($_[1] =~ /^(?:wide|full)/) { |
|
210
|
0
|
|
|
|
|
0
|
$Text::VisualWidth::PP::EastAsian = 1; |
|
211
|
0
|
|
|
|
|
0
|
Text::ANSI::Fold->configure(ambiguous => 'wide'); |
|
212
|
|
|
|
|
|
|
} |
|
213
|
5
|
|
|
|
|
605
|
} ; |
|
214
|
|
|
|
|
|
|
|
|
215
|
5
|
|
|
0
|
|
332
|
has '+help' => sub { usage() } ; |
|
|
0
|
|
|
|
|
0
|
|
|
216
|
5
|
|
|
0
|
|
215
|
has '+version' => sub { print "$version\n"; exit 0 } ; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
217
|
5
|
|
|
0
|
|
191
|
has '+man' => sub { pod2usage {-verbose => 2} } ; |
|
|
0
|
|
|
|
|
0
|
|
|
218
|
|
|
|
|
|
|
|
|
219
|
5
|
|
|
5
|
|
9404
|
} no Getopt::EX::Hashed; |
|
|
5
|
|
|
|
|
14
|
|
|
|
5
|
|
|
|
|
27
|
|
|
220
|
|
|
|
|
|
|
|
|
221
|
5
|
50
|
|
|
|
235
|
$app = Getopt::EX::Hashed->new() or die; |
|
222
|
|
|
|
|
|
|
|
|
223
|
5
|
|
|
|
|
11531
|
my @SAVEDARGV = @ARGV; |
|
224
|
5
|
|
|
5
|
|
3669
|
use Getopt::EX::Long qw(:DEFAULT Configure ExConfigure); |
|
|
5
|
|
|
|
|
583156
|
|
|
|
5
|
|
|
|
|
1591
|
|
|
225
|
5
|
|
|
|
|
49
|
ExConfigure BASECLASS => [ "App::sdif", "Getopt::EX" ]; |
|
226
|
5
|
|
|
|
|
219
|
Configure "bundling"; |
|
227
|
5
|
50
|
|
|
|
314
|
$app->getopt or usage({status => 1}); |
|
228
|
|
|
|
|
|
|
|
|
229
|
5
|
50
|
|
|
|
105889
|
warn "\@ARGV = (@SAVEDARGV)\n" if $app->debug; |
|
230
|
|
|
|
|
|
|
|
|
231
|
5
|
|
|
|
|
55
|
$App::sdif::Util::NO_WARNINGS = $app->lenience; |
|
232
|
|
|
|
|
|
|
|
|
233
|
5
|
|
|
5
|
|
3198
|
use Text::VisualWidth::PP qw(vwidth); |
|
|
5
|
|
|
|
|
21738
|
|
|
|
5
|
|
|
|
|
513
|
|
|
234
|
5
|
|
|
5
|
|
3168
|
use Text::ANSI::Fold qw(ansi_fold :constants); { |
|
|
5
|
|
|
|
|
94963
|
|
|
|
5
|
|
|
|
|
4801
|
|
|
235
|
5
|
|
|
|
|
31
|
Text::ANSI::Fold->configure(padding => 1, |
|
|
5
|
|
|
|
|
23
|
|
|
236
|
|
|
|
|
|
|
expand => 1, |
|
237
|
|
|
|
|
|
|
tabstop => $app->tabstop); |
|
238
|
|
|
|
|
|
|
} |
|
239
|
|
|
|
|
|
|
|
|
240
|
5
|
50
|
0
|
|
|
451
|
$app->visible->{ht} //= 1 if $app->tabstyle; |
|
241
|
5
|
50
|
|
|
|
55
|
if ($app->visible->{ht}) { |
|
242
|
|
|
|
|
|
|
Text::ANSI::Fold->configure( |
|
243
|
|
|
|
|
|
|
tabstyle => $app->tabstyle, |
|
244
|
0
|
|
|
|
|
0
|
map { $_->[0] => unicode($_->[1]) } |
|
245
|
0
|
|
|
|
|
0
|
grep { $_->[1] } |
|
|
0
|
|
|
|
|
0
|
|
|
246
|
|
|
|
|
|
|
[ tabhead => $app->tabhead ], |
|
247
|
|
|
|
|
|
|
[ tabspace => $app->tabspace ], |
|
248
|
|
|
|
|
|
|
); |
|
249
|
|
|
|
|
|
|
} |
|
250
|
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub unicode { |
|
252
|
0
|
0
|
|
0
|
|
0
|
my $char = shift or return undef; |
|
253
|
0
|
0
|
|
|
|
0
|
if ($char =~ /^\X$/) { |
|
254
|
0
|
|
|
|
|
0
|
$char; |
|
255
|
|
|
|
|
|
|
} else { |
|
256
|
0
|
0
|
|
|
|
0
|
eval qq["\\N{$char}"] or die "$!"; |
|
257
|
|
|
|
|
|
|
} |
|
258
|
|
|
|
|
|
|
} |
|
259
|
|
|
|
|
|
|
|
|
260
|
5
|
50
|
|
|
|
46
|
if ($app->margin > 0) { |
|
261
|
0
|
0
|
0
|
|
|
0
|
if ($app->runin and $app->margin < $app->runin) { |
|
262
|
0
|
|
|
|
|
0
|
die "margin must be >= runin\n"; |
|
263
|
|
|
|
|
|
|
} |
|
264
|
|
|
|
|
|
|
Text::ANSI::Fold->configure( |
|
265
|
0
|
|
0
|
|
|
0
|
linebreak => LINEBREAK_ALL, |
|
|
|
|
0
|
|
|
|
|
|
266
|
|
|
|
|
|
|
margin => $app->margin, |
|
267
|
|
|
|
|
|
|
runin => $app->runin // $app->margin, |
|
268
|
|
|
|
|
|
|
runout => $app->runout // $app->margin, |
|
269
|
|
|
|
|
|
|
); |
|
270
|
|
|
|
|
|
|
} |
|
271
|
|
|
|
|
|
|
|
|
272
|
5
|
|
|
|
|
36
|
my %colormap = do { |
|
273
|
5
|
50
|
|
|
|
28
|
my $col = $app->{256} ? 0 : 1; |
|
274
|
95
|
100
|
|
95
|
|
320
|
pairmap { $a => (ref $b eq 'ARRAY') ? $b->[$col] : $b } ( |
|
275
|
5
|
|
|
|
|
154
|
UNKNOWN => "" , |
|
276
|
|
|
|
|
|
|
OCOMMAND => [ "555/010" , "GS" ], |
|
277
|
|
|
|
|
|
|
NCOMMAND => [ "555/010" , "GS" ], |
|
278
|
|
|
|
|
|
|
MCOMMAND => [ "555/010" , "GS" ], |
|
279
|
|
|
|
|
|
|
OFILE => [ "551/010D" , "GDS" ], |
|
280
|
|
|
|
|
|
|
NFILE => [ "551/010D" , "GDS" ], |
|
281
|
|
|
|
|
|
|
MFILE => [ "551/010D" , "GDS" ], |
|
282
|
|
|
|
|
|
|
OMARK => [ "010/444" , "G/W" ], |
|
283
|
|
|
|
|
|
|
NMARK => [ "010/444" , "G/W" ], |
|
284
|
|
|
|
|
|
|
MMARK => [ "010/444" , "G/W" ], |
|
285
|
|
|
|
|
|
|
UMARK => "" , |
|
286
|
|
|
|
|
|
|
OLINE => [ "220" , "Y" ], |
|
287
|
|
|
|
|
|
|
NLINE => [ "220" , "Y" ], |
|
288
|
|
|
|
|
|
|
MLINE => [ "220" , "Y" ], |
|
289
|
|
|
|
|
|
|
ULINE => "" , |
|
290
|
|
|
|
|
|
|
OTEXT => [ "K/454" , "G" ], |
|
291
|
|
|
|
|
|
|
NTEXT => [ "K/454" , "G" ], |
|
292
|
|
|
|
|
|
|
MTEXT => [ "K/454" , "G" ], |
|
293
|
|
|
|
|
|
|
UTEXT => "" , |
|
294
|
|
|
|
|
|
|
); |
|
295
|
|
|
|
|
|
|
}; |
|
296
|
|
|
|
|
|
|
|
|
297
|
5
|
|
|
5
|
|
57
|
use Getopt::EX::Colormap; |
|
|
5
|
|
|
|
|
13
|
|
|
|
5
|
|
|
|
|
411
|
|
|
298
|
5
|
|
|
|
|
36
|
$Getopt::EX::Colormap::NO_RESET_EL = 1; |
|
299
|
5
|
|
|
5
|
|
31
|
use constant SGR_RESET => "\e[m"; |
|
|
5
|
|
|
|
|
12
|
|
|
|
5
|
|
|
|
|
6730
|
|
|
300
|
|
|
|
|
|
|
my $color_handler = Getopt::EX::Colormap |
|
301
|
|
|
|
|
|
|
->new(HASH => \%colormap) |
|
302
|
5
|
|
|
|
|
58
|
->load_params(@{$app->colormap}); |
|
|
5
|
|
|
|
|
442
|
|
|
303
|
|
|
|
|
|
|
|
|
304
|
5
|
|
33
|
|
|
254
|
$colormap{OUMARK} ||= $colormap{UMARK} || $colormap{OMARK}; |
|
|
|
|
33
|
|
|
|
|
|
305
|
5
|
|
33
|
|
|
58
|
$colormap{NUMARK} ||= $colormap{UMARK} || $colormap{NMARK}; |
|
|
|
|
33
|
|
|
|
|
|
306
|
5
|
|
33
|
|
|
55
|
$colormap{OULINE} ||= $colormap{ULINE} || $colormap{OLINE}; |
|
|
|
|
33
|
|
|
|
|
|
307
|
5
|
|
33
|
|
|
71
|
$colormap{NULINE} ||= $colormap{ULINE} || $colormap{NLINE}; |
|
|
|
|
33
|
|
|
|
|
|
308
|
|
|
|
|
|
|
|
|
309
|
5
|
|
|
|
|
27
|
for ( |
|
310
|
|
|
|
|
|
|
[ $app->unknowncolor => q/UNKNOWN/ ], |
|
311
|
|
|
|
|
|
|
[ $app->commandcolor => q/COMMAND/ ], |
|
312
|
|
|
|
|
|
|
[ $app->filecolor => q/FILE/ ], |
|
313
|
|
|
|
|
|
|
[ $app->linecolor => q/LINE/ ], |
|
314
|
|
|
|
|
|
|
[ $app->markcolor => q/MARK/ ], |
|
315
|
|
|
|
|
|
|
[ $app->textcolor => q/TEXT/ ], |
|
316
|
|
|
|
|
|
|
) { |
|
317
|
30
|
|
|
|
|
198
|
my($color, $label) = @$_; |
|
318
|
30
|
50
|
|
|
|
98
|
$color and next; |
|
319
|
0
|
|
|
|
|
0
|
for (grep /$label/, keys %colormap) { |
|
320
|
0
|
|
|
|
|
0
|
$colormap{$_} = ''; |
|
321
|
|
|
|
|
|
|
} |
|
322
|
|
|
|
|
|
|
} |
|
323
|
|
|
|
|
|
|
|
|
324
|
5
|
50
|
|
|
|
31
|
if ($app->colordump) { |
|
325
|
0
|
|
|
|
|
0
|
print $color_handler->colormap( |
|
326
|
|
|
|
|
|
|
name => '--changeme', option => '--colormap'); |
|
327
|
0
|
|
|
|
|
0
|
exit; |
|
328
|
|
|
|
|
|
|
} |
|
329
|
|
|
|
|
|
|
|
|
330
|
5
|
|
|
|
|
36
|
my $painter = do { |
|
331
|
5
|
50
|
0
|
|
|
20
|
if (($app->color eq 'always') |
|
|
|
|
33
|
|
|
|
|
|
332
|
|
|
|
|
|
|
or (($app->color eq 'auto') and (-t STDOUT))) { |
|
333
|
5
|
|
|
445
|
|
88
|
sub { $color_handler->color(@_) }; |
|
|
445
|
|
|
|
|
1493
|
|
|
334
|
|
|
|
|
|
|
} else { |
|
335
|
0
|
|
|
0
|
|
0
|
sub { $_[1] } ; |
|
|
0
|
|
|
|
|
0
|
|
|
336
|
|
|
|
|
|
|
} |
|
337
|
|
|
|
|
|
|
}; |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
## |
|
340
|
|
|
|
|
|
|
## setup cdif command and option |
|
341
|
|
|
|
|
|
|
## |
|
342
|
5
|
50
|
33
|
|
|
22
|
if (defined $app->cdif and $app->cdif eq '') { |
|
343
|
5
|
|
|
|
|
77
|
$app->cdif = $default_cdif; |
|
344
|
|
|
|
|
|
|
} |
|
345
|
|
|
|
|
|
|
|
|
346
|
5
|
|
|
|
|
37
|
for ( |
|
347
|
|
|
|
|
|
|
[ "unit" , "=" , $app->unit , undef ] , |
|
348
|
|
|
|
|
|
|
[ "256" , "!" , $app->{256} , $default_256 ] , |
|
349
|
|
|
|
|
|
|
[ "prefix" , "!" , $app->prefix , $default_prefix ] , |
|
350
|
|
|
|
|
|
|
[ "lenience" , "!" , $app->lenience , $default_lenience ] , |
|
351
|
|
|
|
|
|
|
) |
|
352
|
|
|
|
|
|
|
{ |
|
353
|
20
|
|
|
|
|
143
|
my($name, $type, $var, $default) = @$_; |
|
354
|
20
|
100
|
|
|
|
75
|
if ($type eq "!") { |
|
|
|
50
|
|
|
|
|
|
|
355
|
15
|
50
|
|
|
|
45
|
next if not defined $var; |
|
356
|
15
|
50
|
|
|
|
79
|
next if $var == $default; |
|
357
|
0
|
0
|
|
|
|
0
|
unshift @cdifopts, sprintf("--%s%s", $var ? '' : 'no-', $name); |
|
358
|
|
|
|
|
|
|
} elsif ($type eq "=") { |
|
359
|
5
|
50
|
|
|
|
32
|
next if not defined $var; |
|
360
|
0
|
|
|
|
|
0
|
unshift @cdifopts, sprintf("--%s=%s", $name, $var); |
|
361
|
|
|
|
|
|
|
} else { |
|
362
|
0
|
|
|
|
|
0
|
die; |
|
363
|
|
|
|
|
|
|
} |
|
364
|
|
|
|
|
|
|
} |
|
365
|
|
|
|
|
|
|
|
|
366
|
5
|
|
|
|
|
29
|
unshift @cdifopts, @default_cdifopts; |
|
367
|
|
|
|
|
|
|
|
|
368
|
5
|
|
|
|
|
15
|
my($OLD, $NEW, $DIFF); |
|
369
|
5
|
50
|
|
|
|
29
|
if (@ARGV == 2) { |
|
|
|
50
|
|
|
|
|
|
|
370
|
0
|
|
|
|
|
0
|
($OLD, $NEW) = @ARGV; |
|
371
|
0
|
|
|
|
|
0
|
$DIFF = "$app->{diff} @{$app->{diffopts}} $OLD $NEW |"; |
|
|
0
|
|
|
|
|
0
|
|
|
372
|
|
|
|
|
|
|
} elsif (@ARGV < 2) { |
|
373
|
5
|
|
100
|
|
|
24
|
$DIFF = shift || '-'; |
|
374
|
5
|
|
|
|
|
11
|
$read_stdin++; |
|
375
|
|
|
|
|
|
|
} else { |
|
376
|
0
|
|
|
|
|
0
|
usage({status => 1}, "Unexpected arguments.\n\n"); |
|
377
|
|
|
|
|
|
|
} |
|
378
|
|
|
|
|
|
|
my $readfile = |
|
379
|
5
|
|
0
|
|
|
23
|
($OLD and $NEW) && !$read_stdin && !(grep { /^-[cuCU]/ } @{$app->diffopts}); |
|
380
|
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
use constant { |
|
382
|
5
|
|
|
|
|
2118
|
RIGHT => 'right', |
|
383
|
|
|
|
|
|
|
LEFT => 'left', |
|
384
|
|
|
|
|
|
|
NO => 'no', |
|
385
|
5
|
|
|
5
|
|
54
|
}; |
|
|
5
|
|
|
|
|
9
|
|
|
386
|
5
|
|
|
|
|
69
|
my %markpos = ( |
|
387
|
|
|
|
|
|
|
center => [ RIGHT , LEFT , LEFT ], |
|
388
|
|
|
|
|
|
|
side => [ LEFT , RIGHT , LEFT ], |
|
389
|
|
|
|
|
|
|
right => [ RIGHT , RIGHT , RIGHT ], |
|
390
|
|
|
|
|
|
|
left => [ LEFT , LEFT , LEFT ], |
|
391
|
|
|
|
|
|
|
no => [ NO , NO , NO ], |
|
392
|
|
|
|
|
|
|
none => [ NO , NO , NO ], |
|
393
|
|
|
|
|
|
|
); |
|
394
|
5
|
50
|
|
|
|
26
|
unless ($markpos{$app->mark}) { |
|
395
|
0
|
|
|
|
|
0
|
my @keys = sort keys %markpos; |
|
396
|
0
|
|
|
|
|
0
|
usage "Use one from (@keys) for option --mark\n\n"; |
|
397
|
|
|
|
|
|
|
} |
|
398
|
5
|
|
|
|
|
39
|
my @markpos = @{$markpos{$app->mark}}; |
|
|
5
|
|
|
|
|
16
|
|
|
399
|
5
|
|
|
|
|
36
|
my($omarkpos, $nmarkpos, $mmarkpos) = @markpos; |
|
400
|
|
|
|
|
|
|
|
|
401
|
5
|
|
|
|
|
40
|
my $num_format = sprintf '%%%dd', $app->digit; |
|
402
|
|
|
|
|
|
|
|
|
403
|
5
|
|
66
|
|
|
49
|
$screen_width = $app->width || &terminal_width; |
|
404
|
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
sub column_width { |
|
406
|
114
|
|
|
114
|
|
328
|
my $column = shift; |
|
407
|
114
|
|
|
|
|
158
|
state %column_width; |
|
408
|
114
|
|
66
|
|
|
690
|
$column_width{$screen_width * 1000 + $column} //= do { |
|
409
|
5
|
|
|
5
|
|
41
|
use integer; |
|
|
5
|
|
|
|
|
22
|
|
|
|
5
|
|
|
|
|
34
|
|
|
410
|
4
|
|
|
|
|
16
|
my $w = $screen_width; |
|
411
|
4
|
50
|
|
|
|
339
|
$w -= $column if $app->mark; |
|
412
|
4
|
|
|
|
|
117
|
max 1, $w / $column; |
|
413
|
|
|
|
|
|
|
}; |
|
414
|
|
|
|
|
|
|
} |
|
415
|
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
## |
|
417
|
|
|
|
|
|
|
## --colortable |
|
418
|
|
|
|
|
|
|
## |
|
419
|
5
|
100
|
|
|
|
38
|
if (defined(my $n = $app->colortable)) { |
|
420
|
5
|
|
|
5
|
|
809
|
no strict 'refs'; |
|
|
5
|
|
|
|
|
12
|
|
|
|
5
|
|
|
|
|
71645
|
|
|
421
|
1
|
|
|
|
|
6
|
&{"Getopt::EX::Colormap::colortable$n"}($screen_width); |
|
|
1
|
|
|
|
|
15
|
|
|
422
|
1
|
|
|
|
|
0
|
exit; |
|
423
|
|
|
|
|
|
|
} |
|
424
|
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
## |
|
426
|
|
|
|
|
|
|
## Column order |
|
427
|
|
|
|
|
|
|
## |
|
428
|
4
|
50
|
|
|
|
39
|
my @column = !$app->column ? () : do { |
|
429
|
0
|
|
|
|
|
0
|
map { $_ - 1 } |
|
430
|
0
|
|
0
|
|
|
0
|
map { { O=>1, N=>2, M=>3 }->{$_} // $_ } |
|
|
0
|
|
|
|
|
0
|
|
|
431
|
|
|
|
|
|
|
$app->column =~ /[0-9ONM]/g; |
|
432
|
|
|
|
|
|
|
}; |
|
433
|
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
## |
|
435
|
|
|
|
|
|
|
## Git --graph prefix pattern |
|
436
|
|
|
|
|
|
|
## |
|
437
|
4
|
|
|
|
|
26
|
my $prefix_re = do { |
|
438
|
4
|
50
|
|
|
|
14
|
if ($app->prefix) { |
|
439
|
4
|
|
|
|
|
158
|
qr/$app->{prefix_pattern}/; |
|
440
|
|
|
|
|
|
|
} else { |
|
441
|
0
|
|
|
|
|
0
|
""; |
|
442
|
|
|
|
|
|
|
} |
|
443
|
|
|
|
|
|
|
}; |
|
444
|
|
|
|
|
|
|
|
|
445
|
4
|
50
|
|
|
|
21
|
if ($app->debug) { |
|
446
|
0
|
|
0
|
|
|
0
|
printf STDERR "\$OLD = %s\n", $OLD // "undef"; |
|
447
|
0
|
|
0
|
|
|
0
|
printf STDERR "\$NEW = %s\n", $NEW // "undef"; |
|
448
|
0
|
|
0
|
|
|
0
|
printf STDERR "\$DIFF = %s\n", $DIFF // "undef"; |
|
449
|
|
|
|
|
|
|
} |
|
450
|
|
|
|
|
|
|
|
|
451
|
4
|
50
|
|
|
|
34
|
if ($app->cdif) { |
|
452
|
4
|
|
|
|
|
12756
|
my $pid = open DIFF, '-|'; |
|
453
|
4
|
50
|
|
|
|
873
|
if (not defined $pid) { |
|
|
|
50
|
|
|
|
|
|
|
454
|
0
|
0
|
|
|
|
0
|
die "$!" if not defined $pid; |
|
455
|
|
|
|
|
|
|
} |
|
456
|
|
|
|
|
|
|
## child |
|
457
|
|
|
|
|
|
|
elsif ($pid == 0) { |
|
458
|
0
|
0
|
|
|
|
0
|
if ($DIFF ne '-') { |
|
459
|
0
|
0
|
|
|
|
0
|
open(STDIN, $DIFF) || die "cannot open diff: $!\n"; |
|
460
|
|
|
|
|
|
|
} |
|
461
|
0
|
|
|
|
|
0
|
do { exec shellwords($app->cdif), @cdifopts } ; |
|
|
0
|
|
|
|
|
0
|
|
|
462
|
0
|
|
|
|
|
0
|
warn "exec failed: $!"; |
|
463
|
0
|
|
|
|
|
0
|
print while <>; |
|
464
|
0
|
|
|
|
|
0
|
exit; |
|
465
|
|
|
|
|
|
|
} |
|
466
|
|
|
|
|
|
|
## parent |
|
467
|
|
|
|
|
|
|
else { |
|
468
|
|
|
|
|
|
|
## nothing to do |
|
469
|
|
|
|
|
|
|
} |
|
470
|
|
|
|
|
|
|
} else { |
|
471
|
0
|
0
|
|
|
|
0
|
open(DIFF, $DIFF) || die "cannot open diff: $!\n"; |
|
472
|
|
|
|
|
|
|
} |
|
473
|
|
|
|
|
|
|
|
|
474
|
4
|
50
|
|
|
|
339
|
if ($readfile) { |
|
475
|
|
|
|
|
|
|
|
|
476
|
0
|
|
|
|
|
0
|
binmode DIFF, ':raw'; |
|
477
|
0
|
|
|
|
|
0
|
my $DIFFOUT = do { local $/; }; |
|
|
0
|
|
|
|
|
0
|
|
|
|
0
|
|
|
|
|
0
|
|
|
478
|
0
|
|
|
|
|
0
|
close DIFF; |
|
479
|
0
|
0
|
|
|
|
0
|
open DIFF, '<', \$DIFFOUT or die; |
|
480
|
|
|
|
|
|
|
|
|
481
|
0
|
0
|
|
|
|
0
|
open OLD, $OLD or die "$OLD: $!\n"; |
|
482
|
0
|
0
|
|
|
|
0
|
open NEW, $NEW or die "$NEW: $!\n"; |
|
483
|
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
# For reading /dev/fd/* |
|
485
|
0
|
0
|
0
|
|
|
0
|
seek OLD, 0, 0 or die unless -p OLD; |
|
486
|
0
|
0
|
0
|
|
|
0
|
seek NEW, 0, 0 or die unless -p NEW; |
|
487
|
|
|
|
|
|
|
} |
|
488
|
|
|
|
|
|
|
|
|
489
|
4
|
|
|
|
|
1356
|
my @boundary = (boundary => $app->boundary); |
|
490
|
4
|
|
|
|
|
562
|
my $color_re = qr{ \e \[ [\d;]* [mK] }x; |
|
491
|
|
|
|
|
|
|
|
|
492
|
4
|
|
|
|
|
84
|
my $oline = 1; |
|
493
|
4
|
|
|
|
|
64
|
my $nline = 1; |
|
494
|
4
|
|
|
|
|
22
|
my $mline = 1; |
|
495
|
|
|
|
|
|
|
|
|
496
|
4
|
|
|
|
|
3642333
|
while () { |
|
497
|
|
|
|
|
|
|
# |
|
498
|
|
|
|
|
|
|
# normal diff |
|
499
|
|
|
|
|
|
|
# |
|
500
|
40
|
100
|
|
|
|
1472
|
if (/^([\d,]+)([adc])([\d,]+)$/) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
501
|
5
|
|
|
|
|
16
|
my(@old, @new); |
|
502
|
5
|
|
|
|
|
77
|
my($left, $ctrl, $right) = ($1, $2, $3); |
|
503
|
5
|
|
|
|
|
58
|
my($l1, $l2) = range($left); |
|
504
|
5
|
|
|
|
|
21
|
my($r1, $r2) = range($right); |
|
505
|
5
|
50
|
|
|
|
25
|
if ($readfile) { |
|
506
|
0
|
|
|
|
|
0
|
my $identical_line = $l1 - $oline + 1 - ($ctrl ne 'a'); |
|
507
|
0
|
|
|
|
|
0
|
print_identical($identical_line); |
|
508
|
|
|
|
|
|
|
} |
|
509
|
5
|
50
|
33
|
|
|
36
|
if ($app->debug || $read_stdin) { |
|
510
|
5
|
|
|
|
|
297
|
print_command_n($_, $_); |
|
511
|
|
|
|
|
|
|
} |
|
512
|
5
|
100
|
100
|
|
|
34
|
if ($ctrl eq 'd' || $ctrl eq 'c') { |
|
513
|
4
|
|
|
|
|
28
|
($oline) = $left =~ /^(\d+)/; |
|
514
|
4
|
|
|
|
|
17
|
my $n = $l2 - $l1 + 1; |
|
515
|
4
|
|
|
|
|
52
|
@old = read_line(*DIFF, $n); |
|
516
|
4
|
50
|
|
|
|
12
|
$readfile and read_line(*OLD, $n); |
|
517
|
|
|
|
|
|
|
} |
|
518
|
5
|
100
|
|
|
|
22
|
read_line(*DIFF, 1) if $ctrl eq 'c'; |
|
519
|
5
|
100
|
100
|
|
|
50
|
if ($ctrl eq 'a' || $ctrl eq 'c') { |
|
520
|
4
|
|
|
|
|
49
|
($nline) = $right =~ /^(\d+)/; |
|
521
|
4
|
|
|
|
|
14
|
my $n = $r2 - $r1 + 1; |
|
522
|
4
|
|
|
|
|
17
|
@new = read_line(*DIFF, $n); |
|
523
|
4
|
50
|
|
|
|
12
|
$readfile and read_line(*NEW, $n); |
|
524
|
|
|
|
|
|
|
} |
|
525
|
|
|
|
|
|
|
map { |
|
526
|
5
|
|
|
|
|
13
|
s/^([<>])\s?/{'<' => '-', '>' => '+'}->{$1}/e |
|
|
12
|
|
|
|
|
61
|
|
|
|
12
|
|
|
|
|
97
|
|
|
527
|
|
|
|
|
|
|
} @old, @new; |
|
528
|
5
|
|
|
|
|
27
|
flush_buffer([], \@old, \@new); |
|
529
|
|
|
|
|
|
|
} |
|
530
|
|
|
|
|
|
|
# |
|
531
|
|
|
|
|
|
|
# context diff |
|
532
|
|
|
|
|
|
|
# |
|
533
|
|
|
|
|
|
|
elsif (/^\*\*\* /) { |
|
534
|
1
|
|
|
|
|
8
|
my $next = ; |
|
535
|
1
|
|
|
|
|
64
|
print_command_n({ type => 'FILE' }, $_, $next); |
|
536
|
|
|
|
|
|
|
} |
|
537
|
|
|
|
|
|
|
elsif ($_ eq "***************\n") { |
|
538
|
1
|
|
|
|
|
5
|
my(@old, @new); |
|
539
|
1
|
|
|
|
|
17380
|
my $ohead = $_ = ; |
|
540
|
1
|
|
|
|
|
10
|
my($left, $right); |
|
541
|
1
|
50
|
|
|
|
46
|
unless (($left) = /^\*\*\* ([\d,]+) \*\*\*\*$/) { |
|
542
|
0
|
|
|
|
|
0
|
print; |
|
543
|
0
|
|
|
|
|
0
|
next; |
|
544
|
|
|
|
|
|
|
} |
|
545
|
1
|
|
|
|
|
21
|
my $oline = range($left); |
|
546
|
1
|
|
|
|
|
4
|
my $dline = 0; |
|
547
|
1
|
|
|
|
|
5
|
my $cline = 0; |
|
548
|
1
|
|
|
|
|
6
|
my $nhead = $_ = ; |
|
549
|
1
|
50
|
|
|
|
5
|
unless (($right) = /^--- ([\d,]+) ----$/) { |
|
550
|
1
|
|
|
|
|
14
|
@old = read_line(*DIFF, $oline - 1, $nhead); |
|
551
|
1
|
|
|
|
|
2
|
$nhead = $_ = ; |
|
552
|
1
|
50
|
|
|
|
18
|
unless (($right) = /^--- ([\d,]+) ----$/) { |
|
553
|
0
|
|
|
|
|
0
|
print $ohead, @old, $_; |
|
554
|
0
|
|
|
|
|
0
|
next; |
|
555
|
|
|
|
|
|
|
} |
|
556
|
1
|
|
|
|
|
5
|
for (@old) { |
|
557
|
14
|
100
|
|
|
|
19
|
/^-/ and ++$dline; |
|
558
|
14
|
100
|
|
|
|
20
|
/^!/ and ++$cline; |
|
559
|
|
|
|
|
|
|
} |
|
560
|
|
|
|
|
|
|
} |
|
561
|
1
|
|
|
|
|
3
|
my $nline = range($right); |
|
562
|
1
|
50
|
33
|
|
|
14
|
if (@old == 0 or $cline != 0 or ($oline - $dline != $nline)) { |
|
|
|
|
33
|
|
|
|
|
|
563
|
1
|
|
|
|
|
4
|
@new = read_line(*DIFF, $nline); |
|
564
|
|
|
|
|
|
|
} |
|
565
|
1
|
|
|
|
|
9
|
print_command_n($ohead, $nhead); |
|
566
|
1
|
|
|
|
|
6
|
($oline) = $left =~ /^(\d+)/; |
|
567
|
1
|
|
|
|
|
3
|
($nline) = $right =~ /^(\d+)/; |
|
568
|
|
|
|
|
|
|
|
|
569
|
1
|
|
|
|
|
13
|
my @buf = merge_diffc(\@old, \@new); |
|
570
|
1
|
|
|
|
|
7
|
flush_buffer(@buf); |
|
571
|
|
|
|
|
|
|
} |
|
572
|
|
|
|
|
|
|
# |
|
573
|
|
|
|
|
|
|
# unified diff |
|
574
|
|
|
|
|
|
|
# |
|
575
|
|
|
|
|
|
|
elsif (/^($prefix_re)(--- (?s:.*))/) { |
|
576
|
5
|
|
|
|
|
90
|
my($prefix, $left) = ($1, $2); |
|
577
|
5
|
|
|
|
|
29
|
my $right = ; |
|
578
|
5
|
|
|
|
|
32
|
local $screen_width = $screen_width; |
|
579
|
5
|
100
|
|
|
|
144
|
if ($prefix) { |
|
580
|
4
|
|
|
|
|
73
|
$right =~ s/^\Q$prefix//; |
|
581
|
4
|
|
|
|
|
14
|
print $prefix; |
|
582
|
4
|
|
|
|
|
11
|
$screen_width -= length $prefix; |
|
583
|
|
|
|
|
|
|
} |
|
584
|
5
|
|
|
|
|
92
|
print_command_n({ type => 'FILE' }, $left, $right); |
|
585
|
|
|
|
|
|
|
} |
|
586
|
|
|
|
|
|
|
elsif (m{^ |
|
587
|
|
|
|
|
|
|
(?$prefix_re) |
|
588
|
|
|
|
|
|
|
(? |
|
589
|
|
|
|
|
|
|
\@\@ [ ] |
|
590
|
|
|
|
|
|
|
\-(?\d+) (?:,(?\d+))? [ ] |
|
591
|
|
|
|
|
|
|
\+(?\d+) (?:,(?\d+))? [ ] |
|
592
|
|
|
|
|
|
|
\@\@ |
|
593
|
|
|
|
|
|
|
(?s:.*) |
|
594
|
|
|
|
|
|
|
) |
|
595
|
|
|
|
|
|
|
}x) { |
|
596
|
5
|
|
|
|
|
107
|
($oline, $nline) = @+{qw(oline nline)}; |
|
597
|
5
|
|
50
|
|
|
81
|
my($o, $n) = ($+{o}//1, $+{n}//1); |
|
|
|
|
50
|
|
|
|
|
|
598
|
5
|
|
|
|
|
47
|
my($prefix, $command) = @+{qw(prefix command)}; |
|
599
|
|
|
|
|
|
|
|
|
600
|
5
|
|
|
|
|
22
|
local $screen_width = $screen_width; |
|
601
|
5
|
|
|
|
|
11
|
my($divert, %read_opt); |
|
602
|
5
|
100
|
|
|
|
82
|
if ($prefix) { |
|
603
|
4
|
|
|
|
|
14
|
$screen_width -= length $prefix; |
|
604
|
4
|
|
|
|
|
17
|
$read_opt{prefix} = $prefix; |
|
605
|
4
|
|
|
4
|
|
67
|
$divert = IO::Divert->new(FINAL => sub { s/^/$prefix/mg }); |
|
|
4
|
|
|
|
|
389
|
|
|
606
|
|
|
|
|
|
|
} |
|
607
|
|
|
|
|
|
|
|
|
608
|
5
|
|
|
|
|
3360
|
print_command_n({ type => 'COMMAND' }, $command, $command); |
|
609
|
5
|
|
|
|
|
63
|
my @buf = read_unified_2 \%read_opt, *DIFF, $o, $n; |
|
610
|
|
|
|
|
|
|
|
|
611
|
5
|
|
|
|
|
113
|
flush_buffer(@buf); |
|
612
|
|
|
|
|
|
|
} |
|
613
|
|
|
|
|
|
|
# |
|
614
|
|
|
|
|
|
|
# diff --combined (only support 3 files) |
|
615
|
|
|
|
|
|
|
# |
|
616
|
|
|
|
|
|
|
elsif (/^diff --(?:cc|combined)/) { |
|
617
|
0
|
|
|
|
|
0
|
my @lines = ($_); |
|
618
|
0
|
|
|
0
|
|
0
|
push @lines, read_until { /^\+\+\+/ } *DIFF; |
|
|
0
|
|
|
|
|
0
|
|
|
619
|
0
|
0
|
|
|
|
0
|
if (not defined $lines[-1]) { |
|
620
|
0
|
|
|
|
|
0
|
pop @lines; |
|
621
|
0
|
|
|
|
|
0
|
print @lines; |
|
622
|
0
|
|
|
|
|
0
|
next; |
|
623
|
|
|
|
|
|
|
} |
|
624
|
0
|
|
|
|
|
0
|
print @lines; |
|
625
|
|
|
|
|
|
|
} |
|
626
|
|
|
|
|
|
|
elsif (/^\@{3} -(\d+)(?:,(\d+))? -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? \@{3}/) { |
|
627
|
0
|
|
|
|
|
0
|
print_command_n({ type => 'COMMAND' }, $_, $_, $_); |
|
628
|
|
|
|
|
|
|
|
|
629
|
0
|
|
|
|
|
0
|
($oline, $nline, $mline) = ($1, $3, $5); |
|
630
|
0
|
|
|
|
|
0
|
state $read_unified_3 = read_unified_sub(3); |
|
631
|
0
|
|
0
|
|
|
0
|
my @buf = $read_unified_3->(*DIFF, $2 // 1, $4 // 1, $6 // 1); |
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
632
|
0
|
|
|
|
|
0
|
flush_buffer_3(@buf); |
|
633
|
|
|
|
|
|
|
} |
|
634
|
|
|
|
|
|
|
# |
|
635
|
|
|
|
|
|
|
# conflict marker |
|
636
|
|
|
|
|
|
|
# |
|
637
|
|
|
|
|
|
|
elsif (/^<<<<<<<\h*+(.*)/) { |
|
638
|
|
|
|
|
|
|
CONFLICT: |
|
639
|
|
|
|
|
|
|
{ |
|
640
|
0
|
|
|
|
|
0
|
my %name = (o => $_); |
|
|
0
|
|
|
|
|
0
|
|
|
641
|
0
|
|
|
|
|
0
|
my($c1, $c2, $c3, $c4); |
|
642
|
0
|
|
|
|
|
0
|
$c1 = $_; |
|
643
|
|
|
|
|
|
|
|
|
644
|
0
|
|
|
0
|
|
0
|
my @old = read_until { /^=======$/ } *DIFF; |
|
|
0
|
|
|
|
|
0
|
|
|
645
|
0
|
|
0
|
|
|
0
|
$c2 = pop @old // do { |
|
646
|
0
|
|
|
|
|
0
|
flush_unknown($c1, @old); |
|
647
|
0
|
|
|
|
|
0
|
last; |
|
648
|
|
|
|
|
|
|
}; |
|
649
|
|
|
|
|
|
|
|
|
650
|
0
|
|
|
0
|
|
0
|
my @new = read_until { /^>>>>>>>\h*+(.*)/ } *DIFF; |
|
|
0
|
|
|
|
|
0
|
|
|
651
|
0
|
|
0
|
|
|
0
|
$c4 = pop @new // do { |
|
652
|
0
|
|
|
|
|
0
|
flush_unknown($c1, @old, $c2, @new); |
|
653
|
0
|
|
|
|
|
0
|
last; |
|
654
|
|
|
|
|
|
|
}; |
|
655
|
0
|
|
|
|
|
0
|
$name{n} = $c4; |
|
656
|
|
|
|
|
|
|
|
|
657
|
0
|
|
|
|
|
0
|
my @mrg; |
|
658
|
0
|
|
|
0
|
|
0
|
my $mrg = first { $old[$_] =~ /^\Q|||||||\E\h*+(.*)/ } keys @old; |
|
|
0
|
|
|
|
|
0
|
|
|
659
|
0
|
0
|
0
|
|
|
0
|
if (defined $mrg or $app->parallel > 2) { |
|
660
|
0
|
0
|
|
|
|
0
|
if (defined $mrg) { |
|
661
|
0
|
|
|
|
|
0
|
$name{m} = $old[$mrg]; |
|
662
|
0
|
|
|
|
|
0
|
($c3, @mrg) = splice @old, $mrg; |
|
663
|
|
|
|
|
|
|
} else { |
|
664
|
0
|
|
|
|
|
0
|
$name{m} = $name{o}; |
|
665
|
0
|
|
|
|
|
0
|
$name{o} = $name{n}; |
|
666
|
0
|
|
|
|
|
0
|
@mrg = @old; |
|
667
|
0
|
|
|
|
|
0
|
@old = @new; |
|
668
|
|
|
|
|
|
|
} |
|
669
|
0
|
|
|
|
|
0
|
s/^/--/ for @old, @mrg; |
|
670
|
0
|
|
|
|
|
0
|
s/^/++/ for @new; |
|
671
|
0
|
|
|
|
|
0
|
print_command_n({ type => 'FILE' }, @name{qw(o m n)}); |
|
672
|
0
|
|
|
|
|
0
|
flush_buffer_3([], \@old, \@mrg, \@new); |
|
673
|
|
|
|
|
|
|
} else { |
|
674
|
0
|
|
|
|
|
0
|
s/^/-/ for @old; |
|
675
|
0
|
|
|
|
|
0
|
s/^/+/ for @new; |
|
676
|
0
|
|
|
|
|
0
|
print_command_n({ type => 'FILE' }, @name{qw(o n)}); |
|
677
|
0
|
|
|
|
|
0
|
flush_buffer([], \@old, \@new); |
|
678
|
|
|
|
|
|
|
} |
|
679
|
|
|
|
|
|
|
} |
|
680
|
|
|
|
|
|
|
} |
|
681
|
|
|
|
|
|
|
# |
|
682
|
|
|
|
|
|
|
# #ifdef custom container |
|
683
|
|
|
|
|
|
|
# |
|
684
|
|
|
|
|
|
|
# #ifdef JA ::::::: ja |
|
685
|
|
|
|
|
|
|
# japanese text japanese text |
|
686
|
|
|
|
|
|
|
# #endif ::::::: |
|
687
|
|
|
|
|
|
|
# #ifdef EN ::::::: en |
|
688
|
|
|
|
|
|
|
# english text english text |
|
689
|
|
|
|
|
|
|
# #endif ::::::: |
|
690
|
|
|
|
|
|
|
# |
|
691
|
|
|
|
|
|
|
elsif (/^(\#ifdef|:{7,})\h++(.*)/) { |
|
692
|
|
|
|
|
|
|
COLON: |
|
693
|
|
|
|
|
|
|
{ |
|
694
|
0
|
|
|
|
|
0
|
my($c1, $c2, $c3, $c4) = ($_); |
|
|
0
|
|
|
|
|
0
|
|
|
695
|
0
|
|
|
|
|
0
|
my $start = $1; |
|
696
|
0
|
0
|
|
|
|
0
|
my $end = $start eq '#ifdef' ? qr/^#endif$/ : qr/^$start$/; |
|
697
|
0
|
|
|
|
|
0
|
my($m1, $m2) = ($2); |
|
698
|
|
|
|
|
|
|
|
|
699
|
0
|
|
|
0
|
|
0
|
my @old = read_until { /$end/ } *DIFF; |
|
|
0
|
|
|
|
|
0
|
|
|
700
|
0
|
|
0
|
|
|
0
|
$c2 = pop @old // do { |
|
701
|
0
|
|
|
|
|
0
|
flush_unknown($c1, @old); |
|
702
|
0
|
|
|
|
|
0
|
last; |
|
703
|
|
|
|
|
|
|
}; |
|
704
|
0
|
|
|
|
|
0
|
$c3 = ; |
|
705
|
0
|
0
|
|
|
|
0
|
if ($c3 !~ /^${start}\h++(.*)/) { |
|
706
|
0
|
|
|
|
|
0
|
flush_unknown($c1, @old, $c2, $c3); |
|
707
|
0
|
|
|
|
|
0
|
last; |
|
708
|
|
|
|
|
|
|
} |
|
709
|
0
|
|
|
|
|
0
|
$m2 = $1; |
|
710
|
0
|
|
|
0
|
|
0
|
my @new = read_until { /$end/ } *DIFF; |
|
|
0
|
|
|
|
|
0
|
|
|
711
|
0
|
|
0
|
|
|
0
|
$c4 = pop @new // do { |
|
712
|
0
|
|
|
|
|
0
|
flush_unknown($c1, @old, $c2, $c3, @new); |
|
713
|
0
|
|
|
|
|
0
|
last; |
|
714
|
|
|
|
|
|
|
}; |
|
715
|
|
|
|
|
|
|
|
|
716
|
0
|
|
|
|
|
0
|
@old = (" $c1", map(s/^/-/r, @old), " $c2"); |
|
717
|
0
|
|
|
|
|
0
|
@new = (" $c3", map(s/^/+/r, @new), " $c4"); |
|
718
|
0
|
|
|
|
|
0
|
flush_buffer([], \@old, \@new); |
|
719
|
|
|
|
|
|
|
} |
|
720
|
|
|
|
|
|
|
} |
|
721
|
|
|
|
|
|
|
else { |
|
722
|
23
|
|
|
|
|
147
|
flush_unknown($_); |
|
723
|
|
|
|
|
|
|
} |
|
724
|
|
|
|
|
|
|
} |
|
725
|
|
|
|
|
|
|
continue { |
|
726
|
40
|
|
|
|
|
4800821
|
STDOUT->flush; |
|
727
|
|
|
|
|
|
|
} |
|
728
|
|
|
|
|
|
|
|
|
729
|
4
|
|
|
|
|
564
|
close DIFF; |
|
730
|
4
|
50
|
|
|
|
174
|
my $exit = $DIFF =~ /\|$/ ? $? >> 8 : 0; |
|
731
|
|
|
|
|
|
|
|
|
732
|
4
|
50
|
|
|
|
28
|
if ($readfile) { |
|
733
|
0
|
0
|
|
|
|
0
|
if ($exit < 2) { |
|
734
|
0
|
|
|
|
|
0
|
print_identical(-1); |
|
735
|
|
|
|
|
|
|
} |
|
736
|
0
|
|
|
|
|
0
|
close OLD; |
|
737
|
0
|
|
|
|
|
0
|
close NEW; |
|
738
|
|
|
|
|
|
|
} |
|
739
|
|
|
|
|
|
|
|
|
740
|
4
|
|
|
|
|
0
|
exit($exit > 1); |
|
741
|
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
###################################################################### |
|
743
|
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
## |
|
745
|
|
|
|
|
|
|
## Convert diff -c output to -u compatible format. |
|
746
|
|
|
|
|
|
|
## |
|
747
|
|
|
|
|
|
|
sub merge_diffc { |
|
748
|
1
|
|
|
1
|
|
15
|
my @o = @{+shift}; |
|
|
1
|
|
|
|
|
12
|
|
|
749
|
1
|
|
|
|
|
2
|
my @n = @{+shift}; |
|
|
1
|
|
|
|
|
5
|
|
|
750
|
1
|
|
|
|
|
2
|
for (@o, @n) { |
|
751
|
28
|
50
|
|
|
|
86
|
s/(?<= ^[ \-\+\!] ) [\t ]//x or die "Format error (-c).\n"; |
|
752
|
|
|
|
|
|
|
} |
|
753
|
|
|
|
|
|
|
|
|
754
|
1
|
|
|
|
|
2
|
my @buf; |
|
755
|
1
|
|
66
|
|
|
5
|
while (@o or @n) { |
|
756
|
|
|
|
|
|
|
|
|
757
|
6
|
|
|
|
|
9
|
push @buf, \( my( @common, @old, @new ) ); |
|
758
|
|
|
|
|
|
|
|
|
759
|
6
|
|
100
|
|
|
25
|
while (@o and $o[0] =~ /^ /) { |
|
760
|
8
|
|
|
|
|
9
|
push @common, shift @o; |
|
761
|
8
|
100
|
|
|
|
18
|
shift @n if @n; |
|
762
|
|
|
|
|
|
|
} |
|
763
|
6
|
|
100
|
|
|
17
|
while (@n and $n[0] =~ /^ /) { |
|
764
|
3
|
|
|
|
|
7
|
push @common, shift @n; |
|
765
|
|
|
|
|
|
|
} |
|
766
|
|
|
|
|
|
|
|
|
767
|
6
|
|
100
|
|
|
24
|
push @old, shift @o while @o and $o[0] =~ /^\-/; |
|
768
|
6
|
100
|
|
|
|
11
|
next if @old; |
|
769
|
|
|
|
|
|
|
|
|
770
|
5
|
|
100
|
|
|
21
|
push @new, shift @n while @n and $n[0] =~ /^\+/; |
|
771
|
5
|
100
|
|
|
|
8
|
next if @new; |
|
772
|
|
|
|
|
|
|
|
|
773
|
4
|
|
100
|
|
|
20
|
push @old, shift @o while @o and $o[0] =~ s/^!/-/; |
|
774
|
4
|
|
100
|
|
|
35
|
push @new, shift @n while @n and $n[0] =~ s/^!/+/; |
|
775
|
|
|
|
|
|
|
} |
|
776
|
|
|
|
|
|
|
|
|
777
|
1
|
|
|
|
|
4
|
@buf; |
|
778
|
|
|
|
|
|
|
} |
|
779
|
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
sub flush_unknown { |
|
781
|
23
|
50
|
|
23
|
|
98
|
if ($app->parallel > 2) { |
|
|
|
50
|
|
|
|
|
|
|
782
|
0
|
|
|
|
|
0
|
flush_buffer_3( [ map s/^/ /r, @_ ] ); |
|
783
|
|
|
|
|
|
|
} |
|
784
|
|
|
|
|
|
|
elsif ($app->parallel > 1) { |
|
785
|
0
|
|
|
|
|
0
|
flush_buffer( [ map s/^/ /r, @_ ] ); |
|
786
|
|
|
|
|
|
|
} |
|
787
|
|
|
|
|
|
|
else { |
|
788
|
23
|
|
|
|
|
265
|
print $painter->('UNKNOWN', $_) for @_; |
|
789
|
|
|
|
|
|
|
} |
|
790
|
|
|
|
|
|
|
} |
|
791
|
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
sub flush_buffer { |
|
793
|
|
|
|
|
|
|
|
|
794
|
11
|
|
|
11
|
|
48
|
push @_, [] while @_ % 3; |
|
795
|
|
|
|
|
|
|
|
|
796
|
11
|
50
|
|
|
|
70
|
if ($app->view) { |
|
797
|
0
|
|
|
|
|
0
|
@_ = do { |
|
798
|
0
|
|
|
|
|
0
|
map { @$_ } |
|
799
|
|
|
|
|
|
|
reduce { |
|
800
|
|
|
|
|
|
|
[ [] , |
|
801
|
0
|
|
|
|
|
0
|
[ map { @$_ } $a->[1], $b->[0], $b->[1] ] , |
|
802
|
0
|
|
|
0
|
|
0
|
[ map { @$_ } $a->[2], $b->[0], $b->[2] ] ] } |
|
|
0
|
|
|
|
|
0
|
|
|
803
|
0
|
0
|
|
|
|
0
|
map { $_ ? [ ( splice @_, 0, 3 ) ] : [ [], [], [] ] } |
|
|
0
|
|
|
|
|
0
|
|
|
804
|
|
|
|
|
|
|
0 .. @_ / 3 ; |
|
805
|
|
|
|
|
|
|
}; |
|
806
|
|
|
|
|
|
|
} |
|
807
|
|
|
|
|
|
|
|
|
808
|
11
|
|
|
|
|
180
|
while (my($s, $o, $n) = splice @_, 0, 3) { |
|
809
|
26
|
|
|
|
|
66
|
for (@$s) { |
|
810
|
32
|
50
|
|
|
|
247
|
s/^(.)// or die; |
|
811
|
32
|
|
|
|
|
105
|
print_column_23($1, $_, $1, $_); |
|
812
|
32
|
|
|
|
|
75
|
$oline++; |
|
813
|
32
|
|
|
|
|
84
|
$nline++; |
|
814
|
|
|
|
|
|
|
} |
|
815
|
|
|
|
|
|
|
|
|
816
|
26
|
|
100
|
|
|
154
|
while (@$o or @$n) { |
|
817
|
65
|
|
|
|
|
136
|
my $old = shift @$o; |
|
818
|
65
|
|
|
|
|
125
|
my $new = shift @$n; |
|
819
|
65
|
100
|
33
|
|
|
407
|
my $omark = $old ? $old =~ s/^(.)// && $1 : ' '; |
|
820
|
65
|
100
|
33
|
|
|
546
|
my $nmark = $new ? $new =~ s/^(.)// && $1 : ' '; |
|
821
|
|
|
|
|
|
|
|
|
822
|
65
|
|
|
|
|
196
|
print_column_23($omark, $old, $nmark, $new); |
|
823
|
|
|
|
|
|
|
|
|
824
|
65
|
100
|
|
|
|
183
|
$oline++ if defined $old; |
|
825
|
65
|
100
|
|
|
|
515
|
$nline++ if defined $new; |
|
826
|
|
|
|
|
|
|
} |
|
827
|
|
|
|
|
|
|
} |
|
828
|
|
|
|
|
|
|
} |
|
829
|
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
sub flush_buffer_3 { |
|
831
|
|
|
|
|
|
|
|
|
832
|
0
|
|
|
0
|
|
0
|
push @_, [] while @_ % 4; |
|
833
|
|
|
|
|
|
|
|
|
834
|
0
|
0
|
|
|
|
0
|
if ($app->view) { |
|
835
|
0
|
|
|
|
|
0
|
@_ = do { |
|
836
|
0
|
|
|
|
|
0
|
map { @$_ } |
|
837
|
|
|
|
|
|
|
reduce { |
|
838
|
|
|
|
|
|
|
[ [] , |
|
839
|
0
|
|
|
|
|
0
|
[ map { @$_ } $a->[1], $b->[0], $b->[1] ] , |
|
840
|
0
|
|
|
|
|
0
|
[ map { @$_ } $a->[2], $b->[0], $b->[2] ] , |
|
841
|
0
|
|
|
0
|
|
0
|
[ map { @$_ } $a->[3], $b->[0], $b->[3] ] ] } |
|
|
0
|
|
|
|
|
0
|
|
|
842
|
0
|
0
|
|
|
|
0
|
map { $_ ? [ splice @_, 0, 4 ] : [ [], [], [], [] ] } |
|
|
0
|
|
|
|
|
0
|
|
|
843
|
|
|
|
|
|
|
0 .. @_ / 4; |
|
844
|
|
|
|
|
|
|
}; |
|
845
|
|
|
|
|
|
|
} |
|
846
|
|
|
|
|
|
|
|
|
847
|
0
|
|
|
|
|
0
|
while (@_) { |
|
848
|
0
|
|
|
|
|
0
|
my @d = splice @_, 0, 4; |
|
849
|
|
|
|
|
|
|
|
|
850
|
0
|
|
|
|
|
0
|
for my $common (@{shift @d}) { |
|
|
0
|
|
|
|
|
0
|
|
|
851
|
0
|
|
|
|
|
0
|
$common =~ s/^ //; |
|
852
|
0
|
|
|
|
|
0
|
print_column_23(' ', $common, ' ', $common, ' ', $common); |
|
853
|
0
|
|
|
|
|
0
|
$oline++; |
|
854
|
0
|
|
|
|
|
0
|
$nline++; |
|
855
|
0
|
|
|
|
|
0
|
$mline++; |
|
856
|
|
|
|
|
|
|
} |
|
857
|
|
|
|
|
|
|
|
|
858
|
0
|
|
|
0
|
|
0
|
while (first { @$_ > 0 } @d) { |
|
|
0
|
|
|
|
|
0
|
|
|
859
|
0
|
|
|
|
|
0
|
my $old = shift @{$d[0]}; |
|
|
0
|
|
|
|
|
0
|
|
|
860
|
0
|
|
|
|
|
0
|
my $new = shift @{$d[1]}; |
|
|
0
|
|
|
|
|
0
|
|
|
861
|
0
|
|
|
|
|
0
|
my $mrg = shift @{$d[2]}; |
|
|
0
|
|
|
|
|
0
|
|
|
862
|
0
|
0
|
0
|
|
|
0
|
my $om = $old ? $old =~ s/^(?|(\-).| (\+)|( ) )// && $1 : ' '; |
|
863
|
0
|
0
|
0
|
|
|
0
|
my $nm = $new ? $new =~ s/^(?|.(\-)|(\+) |( ) )// && $1 : ' '; |
|
864
|
0
|
0
|
0
|
|
|
0
|
my $mm = $mrg ? $mrg =~ s/^(?|(\+).|.(\+)|( ) )// && $1 : ' '; |
|
865
|
|
|
|
|
|
|
|
|
866
|
0
|
|
|
|
|
0
|
print_column_23($om, $old, $nm, $new, $mm, $mrg); |
|
867
|
|
|
|
|
|
|
|
|
868
|
0
|
0
|
|
|
|
0
|
$oline++ if defined $old; |
|
869
|
0
|
0
|
|
|
|
0
|
$nline++ if defined $new; |
|
870
|
0
|
0
|
|
|
|
0
|
$mline++ if defined $mrg; |
|
871
|
|
|
|
|
|
|
} |
|
872
|
|
|
|
|
|
|
} |
|
873
|
|
|
|
|
|
|
} |
|
874
|
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
sub print_identical { |
|
876
|
0
|
|
|
0
|
|
0
|
my $n = shift; |
|
877
|
0
|
|
|
|
|
0
|
while ($n--) { |
|
878
|
0
|
|
|
|
|
0
|
my $old = ; |
|
879
|
0
|
|
|
|
|
0
|
my $new = ; |
|
880
|
0
|
0
|
0
|
|
|
0
|
defined $old or defined $new or last; |
|
881
|
0
|
|
|
|
|
0
|
print_column_23(' ', $old, ' ', $new); |
|
882
|
0
|
|
|
|
|
0
|
$oline++; |
|
883
|
0
|
|
|
|
|
0
|
$nline++; |
|
884
|
0
|
|
|
|
|
0
|
$mline++; |
|
885
|
|
|
|
|
|
|
} |
|
886
|
|
|
|
|
|
|
} |
|
887
|
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
sub linenum { |
|
889
|
0
|
|
|
0
|
|
0
|
my $n = shift; |
|
890
|
0
|
0
|
|
|
|
0
|
defined $n ? (sprintf $num_format, $n) : (' ' x $app->digit); |
|
891
|
|
|
|
|
|
|
} |
|
892
|
|
|
|
|
|
|
|
|
893
|
|
|
|
|
|
|
sub print_column_23 { |
|
894
|
97
|
|
|
97
|
|
234
|
my $column = @_ / 2; |
|
895
|
97
|
|
|
|
|
243
|
my $width = column_width $column; |
|
896
|
97
|
|
|
|
|
377
|
my($omark, $old, $nmark, $new, $mmark, $mrg) = @_; |
|
897
|
97
|
|
|
|
|
369
|
my $print_number = $app->number; |
|
898
|
|
|
|
|
|
|
|
|
899
|
97
|
|
|
|
|
605
|
my($onum, $nnum, $mnum) = ('', '', ''); |
|
900
|
97
|
50
|
|
|
|
219
|
my $nspace = $print_number ? ' ' : ''; |
|
901
|
97
|
100
|
|
|
|
223
|
if (defined $old) { |
|
902
|
58
|
|
|
|
|
433
|
$old =~ s/\R\z//; |
|
903
|
58
|
50
|
|
|
|
149
|
$onum = linenum($oline) if $print_number; |
|
904
|
|
|
|
|
|
|
} |
|
905
|
97
|
100
|
|
|
|
192
|
if (defined $new) { |
|
906
|
85
|
|
|
|
|
467
|
$new =~ s/\R\z//; |
|
907
|
85
|
50
|
|
|
|
218
|
$nnum = linenum($nline) if $print_number; |
|
908
|
|
|
|
|
|
|
} |
|
909
|
97
|
50
|
|
|
|
199
|
if (defined $mrg) { |
|
910
|
0
|
|
|
|
|
0
|
$mrg =~ s/\R\z//; |
|
911
|
0
|
0
|
|
|
|
0
|
$mnum = linenum($mline) if $print_number; |
|
912
|
|
|
|
|
|
|
} |
|
913
|
|
|
|
|
|
|
|
|
914
|
97
|
100
|
|
|
|
386
|
my($OTEXT, $OLINE, $OMARK) = |
|
915
|
|
|
|
|
|
|
$omark =~ /\S/ ? qw(OTEXT OLINE OMARK) : qw(UTEXT OULINE OUMARK); |
|
916
|
97
|
100
|
|
|
|
348
|
my($NTEXT, $NLINE, $NMARK) = |
|
917
|
|
|
|
|
|
|
$nmark =~ /\S/ ? qw(NTEXT NLINE NMARK) : qw(UTEXT NULINE NUMARK); |
|
918
|
97
|
0
|
|
|
|
227
|
my($MTEXT, $MLINE, $MMARK) = |
|
|
|
50
|
|
|
|
|
|
|
919
|
|
|
|
|
|
|
$mmark =~ /\S/ ? qw(MTEXT MLINE MMARK) : qw(UTEXT NULINE NUMARK) |
|
920
|
|
|
|
|
|
|
if $column >= 3; |
|
921
|
|
|
|
|
|
|
|
|
922
|
97
|
|
|
|
|
153
|
while (1) { |
|
923
|
97
|
|
|
|
|
606
|
(my $o, $old) = ansi_fold($old, |
|
924
|
|
|
|
|
|
|
max(1, $width - length($onum . $nspace)), |
|
925
|
|
|
|
|
|
|
@boundary); |
|
926
|
97
|
|
|
|
|
26102
|
(my $n, $new) = ansi_fold($new, |
|
927
|
|
|
|
|
|
|
max(1, $width - length($nnum . $nspace)), |
|
928
|
|
|
|
|
|
|
@boundary); |
|
929
|
97
|
50
|
|
|
|
32964
|
(my $m, $mrg) = ansi_fold($mrg, |
|
930
|
|
|
|
|
|
|
max(1, $width - length($mnum . $nspace)), |
|
931
|
|
|
|
|
|
|
@boundary) |
|
932
|
|
|
|
|
|
|
if $column >= 3; |
|
933
|
|
|
|
|
|
|
|
|
934
|
97
|
|
|
|
|
168
|
my @f; |
|
935
|
97
|
|
|
|
|
284
|
$f[0]{MARK} = $painter->($OMARK, $omark); |
|
936
|
97
|
50
|
|
|
|
11191
|
$f[0]{LINE} = $painter->($OLINE, $onum) . $nspace if $print_number; |
|
937
|
97
|
50
|
|
|
|
354
|
$f[0]{TEXT} = $painter->($OTEXT, $o) if $o ne ""; |
|
938
|
97
|
|
|
|
|
8686
|
$f[1]{MARK} = $painter->($NMARK, $nmark); |
|
939
|
97
|
50
|
|
|
|
6885
|
$f[1]{LINE} = $painter->($NLINE, $nnum) . $nspace if $print_number; |
|
940
|
97
|
50
|
|
|
|
280
|
$f[1]{TEXT} = $painter->($NTEXT, $n) if $n ne ""; |
|
941
|
97
|
50
|
|
|
|
9915
|
if ($column >= 3) { |
|
942
|
0
|
|
|
|
|
0
|
$f[2]{MARK} = $painter->($MMARK, $mmark); |
|
943
|
0
|
0
|
|
|
|
0
|
$f[2]{LINE} = $painter->($MLINE, $mnum) . $nspace if $print_number; |
|
944
|
0
|
0
|
|
|
|
0
|
$f[2]{TEXT} = $painter->($MTEXT, $m) if $m ne ""; |
|
945
|
|
|
|
|
|
|
} |
|
946
|
97
|
|
|
|
|
297
|
print_field_n(@f); |
|
947
|
|
|
|
|
|
|
|
|
948
|
97
|
50
|
|
|
|
399
|
last if $app->truncate; |
|
949
|
97
|
50
|
33
|
|
|
1577
|
last unless $old ne '' or $new ne '' or ($mrg and $mrg ne ''); |
|
|
|
|
33
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
950
|
|
|
|
|
|
|
|
|
951
|
0
|
0
|
|
|
|
0
|
if ($print_number) { |
|
952
|
0
|
|
|
|
|
0
|
$onum =~ s/./ /g; |
|
953
|
0
|
|
|
|
|
0
|
$nnum =~ s/./ /g; |
|
954
|
0
|
0
|
|
|
|
0
|
$mnum =~ s/./ /g if $column >= 3; |
|
955
|
|
|
|
|
|
|
} |
|
956
|
0
|
0
|
|
|
|
0
|
$omark = $old ne '' ? '.' : ' '; |
|
957
|
0
|
0
|
|
|
|
0
|
$nmark = $new ne '' ? '.' : ' '; |
|
958
|
0
|
0
|
|
|
|
0
|
$mmark = $mrg ne '' ? '.' : ' ' if $column >= 3; |
|
|
|
0
|
|
|
|
|
|
|
959
|
|
|
|
|
|
|
} |
|
960
|
|
|
|
|
|
|
} |
|
961
|
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
sub print_command_n { |
|
963
|
17
|
100
|
|
17
|
|
124
|
my $opt = ref $_[0] ? shift : {}; |
|
964
|
17
|
|
|
|
|
42
|
my $column = @_; |
|
965
|
17
|
|
|
|
|
129
|
my $width = column_width $column; |
|
966
|
17
|
|
|
|
|
44
|
my @f; |
|
967
|
|
|
|
|
|
|
|
|
968
|
17
|
|
100
|
|
|
145
|
$opt->{type} //= 'COMMAND'; |
|
969
|
|
|
|
|
|
|
|
|
970
|
17
|
100
|
50
|
|
|
125
|
$app->command or return if $opt->{type} eq 'COMMAND'; |
|
971
|
17
|
100
|
50
|
|
|
180
|
$app->filename or return if $opt->{type} eq 'FILE'; |
|
972
|
|
|
|
|
|
|
|
|
973
|
17
|
|
|
|
|
92
|
my @color = map { $_ . $opt->{type} } "O", "N", "M"; |
|
|
51
|
|
|
|
|
205
|
|
|
974
|
|
|
|
|
|
|
|
|
975
|
17
|
|
|
|
|
86
|
for my $i (keys @_) { |
|
976
|
34
|
|
|
|
|
120
|
local $_ = $_[$i]; |
|
977
|
34
|
50
|
|
|
|
187
|
chomp if defined; |
|
978
|
34
|
|
|
|
|
194
|
($_) = ansi_fold($_, $width); |
|
979
|
34
|
|
|
|
|
97305
|
my %f; |
|
980
|
34
|
50
|
|
|
|
181
|
my $color = $i < @color ? $color[$i] : $color[-1]; |
|
981
|
34
|
|
|
|
|
189
|
$f{TEXT} = $painter->($color, $_); |
|
982
|
34
|
|
|
|
|
15389
|
$f{MARK} = ' '; |
|
983
|
34
|
|
|
|
|
127
|
push @f, \%f; |
|
984
|
|
|
|
|
|
|
} |
|
985
|
|
|
|
|
|
|
|
|
986
|
17
|
|
|
|
|
125
|
print_field_n(@f); |
|
987
|
|
|
|
|
|
|
} |
|
988
|
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
sub print_field_n { |
|
990
|
114
|
50
|
|
114
|
|
348
|
if (@column >= @_) { |
|
991
|
0
|
|
|
|
|
0
|
@_ = @_[ @column[ keys @_ ] ]; |
|
992
|
|
|
|
|
|
|
} |
|
993
|
114
|
|
|
|
|
515
|
while (my($i, $f) = each @_) { |
|
994
|
228
|
50
|
|
|
|
686
|
my $markpos = $i < @markpos ? $markpos[$i] : $markpos[-1]; |
|
995
|
228
|
|
|
|
|
370
|
local $_; |
|
996
|
228
|
100
|
33
|
|
|
689
|
$_ = $f->{"MARK"} and print if $markpos eq LEFT; |
|
997
|
228
|
50
|
|
|
|
583
|
$_ = $f->{"LINE"} and print; |
|
998
|
228
|
50
|
|
|
|
1124
|
$_ = $f->{"TEXT"} and print; |
|
999
|
228
|
100
|
33
|
|
|
1152
|
$_ = $f->{"MARK"} and print if $markpos eq RIGHT; |
|
1000
|
|
|
|
|
|
|
} |
|
1001
|
114
|
|
|
|
|
438
|
print "\n"; |
|
1002
|
|
|
|
|
|
|
} |
|
1003
|
|
|
|
|
|
|
|
|
1004
|
|
|
|
|
|
|
__END__ |