1 rizwank 1.1 #!@PERLPROG@
2 # -*- perl -*-
3 #
4 # Pretty-print diff outputs with GNU enscript.
5 # Copyright (c) 1996-2000 Markku Rossi
6 #
7 # Author: Markku Rossi <mtr@iki.fi>
8 #
9
10 #
11 # This file is part of GNU enscript.
12 #
13 # This program is free software; you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation; either version 2, or (at your option)
16 # any later version.
17 #
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
22 rizwank 1.1 #
23 # You should have received a copy of the GNU General Public License
24 # along with this program; see the file COPYING. If not, write to
25 # the Free Software Foundation, 59 Temple Place - Suite 330,
26 # Boston, MA 02111-1307, USA.
27 #
28
29 #
30 # Original idea by Trent Fisher <trent@informix.com>
31 # Thanks to:
32 # - Tero Kivinen <kivinen@iki.fi> for the first prototype
33 # - Tait Cyrus <tait.cyrus@mci.com> for fixes and cleanups
34 #
35
36 $file = shift(@ARGV);
37 $add_gray = ".80";
38 $del_gray = ".60";
39
40 $program = $0;
41 $program =~ s/.*\///g;
42
43 rizwank 1.1 sub usage {
44 warn "Usage: $program [-n] ORIGINAL_FILE < DIFF\n\n";
45 warn "Program reads a diff file from its standard input and annotates
46 ORIGINAL_FILE to show the changes made to the file. The easiest way to use
47 this program is to use it as an input filter for GNU enscript:
48
49 \$ enscript -G2re --filter='rcsdiff %s | diffpp %s' *.c *.h
50 \$ enscript -G2re --filter='diff %s~ %s | diffpp %s~' *.c *.h
51
52 Use -n to output with line numbers (Note: deleted lines are not numbered).
53
54 ";
55 }
56
57 if ($file eq "--help") {
58 &usage;
59 exit 0;
60 }
61
62 if ($file eq "--version") {
63 warn "diffpp 1.1\n";
64 rizwank 1.1 exit 0;
65 }
66
67 if ($file eq "-n") {
68 $do_line_numbers = 1;
69 $file = shift(@ARGV);
70 }
71
72 if (!defined($file) || defined($ARGV[0])) {
73 &usage;
74 exit 1;
75 }
76
77 # Read in original file into internal array.
78 open(FP, $file) || die "$program: couldn't open file `$file' for input: $!\n";
79 @orig_file = <FP>;
80 close(FP);
81 $[ = 1;
82 $orig_line_num = 1;
83 $orig_num_lines = @orig_file;
84
85 rizwank 1.1 # Now read in file of diffs into internal array.
86 @diffs = <STDIN>;
87 $diff_line_num = 1;
88 $diff_num_lines = @diffs;
89
90 $output_line_num = 1;
91 $line_num_switch = 1;
92
93 while ($diff_line_num <= $diff_num_lines) {
94 $_ = $diffs[$diff_line_num];
95 if (/a/) {
96 do_add($_);
97 } elsif (/d/) {
98 do_delete($_);
99 } elsif (/c/) {
100 do_change($_);
101 }
102 }
103
104 while ($orig_line_num <= $orig_num_lines) {
105 &print_line_number();
106 rizwank 1.1 print $orig_file[$orig_line_num++];
107 }
108
109 # Handle new/added lines
110 #
111 # Formats used:
112 # #a#
113 # #a#,#
114 sub do_add {
115 ($line) = @_;
116 if ($line =~ /(\d+)a(\d+),(\d+)/) {
117 $insert_at_line = $1;
118 $num_new_lines = $3 - $2 + 1;
119 } elsif ($line =~ /(\d+)a(\d+)/) {
120 $insert_at_line = $1;
121 $num_new_lines = 1;
122 }
123 &skip_to_line($insert_at_line);
124 printf("\000shade{$add_gray}");
125 &mark_to_line($num_new_lines, "+");
126 printf("\000shade{1.0}");
127 rizwank 1.1 }
128
129 # Handle deleted/removed lines
130 #
131 # Formats used:
132 # #d#
133 # #,#d#
134 sub do_delete {
135 ($line) = @_;
136 if ($line =~ /(\d+),(\d+)d(\d+)/) {
137 $num_del_lines = $2 - $1 + 1;
138 } elsif ($line =~ /(\d+)d(\d+)/) {
139 $num_del_lines = 1;
140 }
141 $del_from = $1;
142 &skip_to_line($del_from - 1);
143 printf("\000shade{$del_gray}");
144 &mark_to_line($num_del_lines, "-");
145 printf("\000shade{1.0}");
146 $orig_line_num += $num_del_lines;
147 }
148 rizwank 1.1
149 # Handle changed/modified lines
150 #
151 # Formats used:
152 # #,#c#,#
153 # #,#c#
154 # #c#,#
155 # #c#
156 sub do_change {
157 ($line) = @_;
158 if ($line =~ /(\d+),(\d+)c(\d+),(\d+)/) {
159 $num_old_lines = $2 - $1 + 1;
160 $num_new_lines = $4 - $3 + 1;
161 $change_at_line = $1;
162 } elsif ($line =~ /(\d+),(\d+)c(\d+)/) {
163 $num_old_lines = $2 - $1 + 1;
164 $num_new_lines = 1;
165 $change_at_line = $1;
166 } elsif ($line =~ /(\d+)c(\d+),(\d+)/) {
167 $num_old_lines = 1;
168 $num_new_lines = $3 - $2 + 1;
169 rizwank 1.1 $change_at_line = $1;
170 } elsif ($line =~ /(\d+)c(\d+)/) {
171 $num_old_lines = 1;
172 $num_new_lines = 1;
173 $change_at_line = $1;
174 }
175 # Mark old lines
176 &skip_to_line($change_at_line - 1);
177 $orig_line_num += $num_old_lines; # skip over changed lines
178 printf("\000shade{$del_gray}");
179 &mark_to_line($num_old_lines, "-");
180 printf("\000shade{1.0}");
181 # Mark new lines
182 printf("\000shade{$add_gray}");
183 &mark_to_line($num_new_lines, "+");
184 printf("\000shade{1.0}");
185 }
186
187 sub skip_to_line {
188 ($line) = @_;
189
190 rizwank 1.1 while ($orig_line_num <= $line) {
191 &print_line_number();
192 print $orig_file[$orig_line_num];
193 $orig_line_num++;
194 }
195 }
196
197 sub mark_to_line {
198 ($num_lines, $marker) = @_;
199
200 # do not line number deleted lines
201 if ($marker eq "-") {
202 $line_num_switch = 0;
203 }
204
205 $diff_line_num++; # skip over diff command
206 while ($num_lines > 0) {
207 $diff_line = substr($diffs[$diff_line_num++],3);
208 print "\000ps{gsave -5 0 rmoveto ($marker) show grestore}";
209 &print_line_number($marker);
210 print $diff_line;
211 rizwank 1.1 $num_lines--;
212 }
213
214 # ensure line numbering is switched on again
215 $line_num_switch = 1;
216 }
217
218 sub print_line_number {
219 if ($do_line_numbers == 1) {
220 if ($line_num_switch == 1) {
221 printf ("%4d: ",$output_line_num);
222 $output_line_num++;
223 } else {
224 printf ("%4s ", " ");
225 }
226 }
227 }
|