3 # gvimdiff: display highlighted differences between two files side-by-side in
6 # Note: This program uses the Unix trick of using its name to alter behavior.
7 # If this file is called gvimdiff, it brings up the differences in gvim.
8 # If it is called vimdiff, it brings up the differences in vim. If it is
9 # called anything else, it fails with an error. If you need vimdiff,
10 # create a symbolic or hard link from gvimdiff to vimdiff.
12 # Author: Gautam H. Mudunuri (gmudunuri@informatica.com)
14 # $Revision: 1.1.1.1 $
18 # Get my name and verify it and determine whether to use vim/gvim
19 progname
=`basename $0`
28 echo >&2 "This program has an invalid name \"$progname\""
33 # Display usage and exit
36 # Options common to vimdiff and gvimdiff
39 -s do not display identical lines
40 -w width width of diff output
41 (default is set for diffs of 80 column wide files)"
43 # Add gvimdiff specific options
44 [ $vim_exe = "gvim" ] && {
45 options
="$options [ -f font ] [ -n ] [ -w width ]"
47 -f font font to use for display
48 -n do not create a wide window
49 (useful if your display is not too wide)
53 # Display usage and exit
56 display highlighted differences between two files side-by-side in $vim_exe
58 Usage: $progname $options arg1 arg2
60 Both the arguments must be file names OR one must be a file name and the
61 other a directory name. If one of the arguments is a directory name, it
62 refers to the file in that directory with the same name as the other
75 while getopts f
:nsw
: option
79 [ $vim_exe != "gvim" ] && Usage
80 [ "$font" != "" ] && Usage
84 [ $vim_exe != "gvim" ] && Usage
91 [ "$width" != "" ] && Usage
99 shift `expr $OPTIND - 1`
100 [ $# -eq 2 ] || Usage
102 # Arguments must be files or directories
104 [ -f $arg1 -o -d $arg1 ] ||
{
105 echo >&2 "$progname: $arg1 is not a valid file or directory"
109 [ -f $arg2 -o -d $arg2 ] ||
{
110 echo >&2 "$progname: $arg2 is not a valid file or directory"
114 # Both arguments cannot be directories
115 [ -d "$arg1" -a -d "$arg2" ] && {
116 echo >&2 "$progname: $arg1 and $arg2 are both directories"
117 echo >&2 "Atleast one file must be specified"
121 # If one argument is a directory, convert it to a filename using the other,
122 # otherwise use it directly
123 [ -d "$arg1" ] && file1
="$arg1/`basename $arg2`" || file1
="$arg1"
124 [ -d "$arg2" ] && file2
="$arg2/`basename $arg1`" || file2
="$arg2"
126 # Both files must be readable
128 echo >&2 "$progname: cannot open $file1 for reading"
132 echo >&2 "$progname: cannot open $file2 for reading"
136 # Width not specified, use default for 80-column wide files and 9 character
137 # sdiff "gutter". (169 = 2 * 80 + 9)
138 [ "$width" = "" ] && width
=169
141 expr "$width" + 0 > /dev
/null
2>&1
143 [ $status -eq 0 -o $status -eq 1 ] ||
{
144 echo >&2 "$progname: invalid width \"$width\""
147 [ $width -gt 0 ] ||
{
148 echo >&2 "$progname: width $width cannot be zero or negative"
151 [ $width -ge 49 ] ||
{
152 echo >&2 "$progname: width $width is too small, should be atleast 29"
155 [ $width -le 209 ] ||
{
156 echo >&2 "$progname: width $width is too large, should be atmost 209"
160 # Compute width per file, allowing 9 characters for the sdiff "gutter"
161 file_width
=`expr '(' $width - 9 ')' / 2`
163 # Compute the range of the number of characters we can expect before the sdiff
164 # separators |, < and >. This is range rather than a specific number because
165 # the presence of tabs can shorten the length
166 min_chars
=`expr $file_width - 5`
167 max_chars
=`expr $file_width + 2`
169 # Define Vim commands for manipulating the sdiff buffer
176 # Define Vim commands for sdiff syntax highlighting. We are going to define
177 # our custom syntax that is not loaded through the standard syntax mechanism.
178 # But we still need the standard colors to be defined. So turn syntax on to
179 # get them and immediately turn it off
183 syn match sdiffRemoved \"^.\{$min_chars,$max_chars} <\"
184 syn match sdiffChanged \"^.\{$min_chars,$max_chars} | .*$\"
185 syn match sdiffAdded \"^.\{$min_chars,$max_chars} > .*$\"
186 hi link sdiffRemoved Comment
187 hi link sdiffChanged PreProc
188 hi link sdiffAdded Identifier
189 let b:current_syntax = \"vimdiff\"
192 # Help commands (doesn't always work)
194 echo 'Ctrl-N: Next Difference Line Ctrl-P: Previous Difference Line'\
197 echo 'Ctrl-P: Previous Difference Line Ctrl-N: Next Difference Line'\
200 # Define Vim mappings to jump to next/previous difference
202 nmap <c-n> /^.\{$min_chars,$max_chars} [<>\|]/e<nl>:$helpcmd_next<nl>
203 nmap <c-p> ?^.\{$min_chars,$max_chars} [<>\|]?e<nl>:$helpcmd_prev<nl>
206 # Collect vim commands to be run
208 set titlestring=\\$progname\\ \\$arg1\\ \\$arg2
209 set noml nows nowrap go=agrb ch=2
213 execute \"normal gg0$max_chars|3l\"
217 # Set sdiff_flags flags
219 [ "$s_flag" = "y" ] && sdiff_flags
="$flags -s"
223 [ "$font" != "" ] && vim_flags
="$vim_flags -fn $font"
224 [ $n_flag != "y" -a $vim_exe = "gvim" ] && {
225 vim_flags
="$vim_flags -geometry $width"
228 # Run the diff and display the output in gvim
229 sdiff -w$width $sdiff_flags $file1 $file2 |
$vim_exe $vim_flags -c "$vimcmds" -