home *** CD-ROM | disk | FTP | other *** search
Text File | 1999-09-25 | 6.1 KB | 230 lines | [TEXT/ALFA] |
- #!/bin/sh
- #
- # gvimdiff: display highlighted differences between two files side-by-side in
- # gvim
- #
- # Note: This program uses the Unix trick of using its name to alter behavior.
- # If this file is called gvimdiff, it brings up the differences in gvim.
- # If it is called vimdiff, it brings up the differences in vim. If it is
- # called anything else, it fails with an error. If you need vimdiff,
- # create a symbolic or hard link from gvimdiff to vimdiff.
- #
- # Author: Gautam H. Mudunuri (gmudunuri@informatica.com)
- #
- # $Revision: 1.1 $
- #
-
-
- # Get my name and verify it and determine whether to use vim/gvim
- progname=`basename $0`
- case "$progname" in
- vimdiff)
- vim_exe="vim"
- ;;
- gvimdiff)
- vim_exe="gvim"
- ;;
- *)
- echo >&2 "This program has an invalid name \"$progname\""
- exit 1
- ;;
- esac
-
- # Display usage and exit
- Usage()
- {
- # Options common to vimdiff and gvimdiff
- options="[ -s ]"
- options_desc="\
- -s do not display identical lines
- -w width width of diff output
- (default is set for diffs of 80 column wide files)"
-
- # Add gvimdiff specific options
- [ $vim_exe = "gvim" ] && {
- options="$options [ -f font ] [ -n ] [ -w width ]"
- options_desc="\
- -f font font to use for display
- -n do not create a wide window
- (useful if your display is not too wide)
- $options_desc"
- }
-
- # Display usage and exit
- echo >&2 "\
- $progname: \
- display highlighted differences between two files side-by-side in $vim_exe
-
- Usage: $progname $options arg1 arg2
-
- Both the arguments must be file names OR one must be a file name and the
- other a directory name. If one of the arguments is a directory name, it
- refers to the file in that directory with the same name as the other
- argument.
-
- Options:
- $options_desc"
- exit 1
- }
-
- # Parse commandline
- n_flag="n"
- s_flag="n"
- width=
- font=
- while getopts f:nsw: option
- do
- case "$option" in
- f)
- [ $vim_exe != "gvim" ] && Usage
- [ "$font" != "" ] && Usage
- font="$OPTARG"
- ;;
- n)
- [ $vim_exe != "gvim" ] && Usage
- n_flag="y"
- ;;
- s)
- s_flag="y"
- ;;
- w)
- [ "$width" != "" ] && Usage
- width="$OPTARG"
- ;;
- *)
- Usage
- ;;
- esac
- done
- shift `expr $OPTIND - 1`
- [ $# -eq 2 ] || Usage
-
- # Arguments must be files or directories
- arg1="$1"
- [ -f $arg1 -o -d $arg1 ] || {
- echo >&2 "$progname: $arg1 is not a valid file or directory"
- exit 1
- }
- arg2="$2"
- [ -f $arg2 -o -d $arg2 ] || {
- echo >&2 "$progname: $arg2 is not a valid file or directory"
- exit 1
- }
-
- # Both arguments cannot be directories
- [ -d "$arg1" -a -d "$arg2" ] && {
- echo >&2 "$progname: $arg1 and $arg2 are both directories"
- echo >&2 "Atleast one file must be specified"
- exit 1
- }
-
- # If one argument is a directory, convert it to a filename using the other,
- # otherwise use it directly
- [ -d "$arg1" ] && file1="$arg1/`basename $arg2`" || file1="$arg1"
- [ -d "$arg2" ] && file2="$arg2/`basename $arg1`" || file2="$arg2"
-
- # Both files must be readable
- [ -r "$file1" ] || {
- echo >&2 "$progname: cannot open $file1 for reading"
- exit 1
- }
- [ -r "$file2" ] || {
- echo >&2 "$progname: cannot open $file2 for reading"
- exit 1
- }
-
- # Width not specified, use default for 80-column wide files and 9 character
- # sdiff "gutter". (169 = 2 * 80 + 9)
- [ "$width" = "" ] && width=169
-
- # Validate width
- expr "$width" + 0 > /dev/null 2>&1
- status="$?"
- [ $status -eq 0 -o $status -eq 1 ] || {
- echo >&2 "$progname: invalid width \"$width\""
- exit 1
- }
- [ $width -gt 0 ] || {
- echo >&2 "$progname: width $width cannot be zero or negative"
- exit 1
- }
- [ $width -ge 49 ] || {
- echo >&2 "$progname: width $width is too small, should be atleast 29"
- exit 1
- }
- [ $width -le 209 ] || {
- echo >&2 "$progname: width $width is too large, should be atmost 209"
- exit 1
- }
-
- # Compute width per file, allowing 9 characters for the sdiff "gutter"
- file_width=`expr '(' $width - 9 ')' / 2`
-
- # Compute the range of the number of characters we can expect before the sdiff
- # separators |, < and >. This is range rather than a specific number because
- # the presence of tabs can shorten the length
- min_chars=`expr $file_width - 5`
- max_chars=`expr $file_width + 2`
-
- # Define Vim commands for manipulating the sdiff buffer
- buffercmds="
- set ts=8 et noro
- retab
- set nomod ro nows
- "
-
- # Define Vim commands for sdiff syntax highlighting. We are going to define
- # our custom syntax that is not loaded through the standard syntax mechanism.
- # But we still need the standard colors to be defined. So turn syntax on to
- # get them and immediately turn it off
- syncmds="
- syn on
- syn off
- syn match sdiffRemoved \"^.\{$min_chars,$max_chars} <\"
- syn match sdiffChanged \"^.\{$min_chars,$max_chars} | .*$\"
- syn match sdiffAdded \"^.\{$min_chars,$max_chars} > .*$\"
- hi link sdiffRemoved Comment
- hi link sdiffChanged PreProc
- hi link sdiffAdded Identifier
- let b:current_syntax = \"vimdiff\"
- "
-
- # Help commands (doesn't always work)
- helpcmd_next="\
- echo 'Ctrl-N: Next Difference Line Ctrl-P: Previous Difference Line'\
- "
- helpcmd_prev="\
- echo 'Ctrl-P: Previous Difference Line Ctrl-N: Next Difference Line'\
- "
-
- # Define Vim mappings to jump to next/previous difference
- mapcmds="
- nmap <c-n> /^.\{$min_chars,$max_chars} [<>\|]/e<nl>:$helpcmd_next<nl>
- nmap <c-p> ?^.\{$min_chars,$max_chars} [<>\|]?e<nl>:$helpcmd_prev<nl>
- "
-
- # Collect vim commands to be run
- vimcmds="
- set titlestring=\\$progname\\ \\$arg1\\ \\$arg2
- set noml nows nowrap go=agrb ch=2
- $buffercmds
- $syncmds
- $mapcmds
- execute \"normal gg0$max_chars|3l\"
- $helpcmd_next
- "
-
- # Set sdiff_flags flags
- sdiff_flags=
- [ "$s_flag" = "y" ] && sdiff_flags="$flags -s"
-
- # Set vim flags
- vim_flags="-R -N"
- [ "$font" != "" ] && vim_flags="$vim_flags -fn $font"
- [ $n_flag != "y" -a $vim_exe = "gvim" ] && {
- vim_flags="$vim_flags -geometry $width"
- }
-
- # Run the diff and display the output in gvim
- sdiff -w$width $sdiff_flags $file1 $file2 | $vim_exe $vim_flags -c "$vimcmds" -
-