small-hacks/cwdiff

258 lines
8.2 KiB
Bash
Executable file
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#! /bin/bash
# Downloaded from: http://code.google.com/p/cj-overlay/source/browse/cwdiff?repo=evergreens
#(C) 2009-2012 C. Junghans
# junghans@votca.org
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#version 0.1 04.08.10 -- initial version
#version 0.1.1, 05.08.10 -- added -D and -o
#version 0.1.2, 04.10.10 -- make -D work again and better help
#version 0.1.3, 10.05.11 -- added --text to diff_opts to allow diff of binary files (issue #3)
#version 0.1.4, 10.05.11 -- removed --text again and handle case of binary files
#version 0.2.0, 15.04.12 -- clean up + bugfix thanks to Arne
#version 0.2.1, 15.04.12 -- clean up + new bug report address
#version 0.2.2, 20.04.12 -- fixed a bug if argument were dirs
#version 0.2.3, 18.12.12 -- replace usage of mktemp with bash built-ins
#version 0.2.4, 31.08.13 -- fixed deleted leading spaces
#version 0.2.5, 06.09.13 -- do not expand escape sequences in diff
#version 0.2.6, 18.09.13 -- allow 1st argument begin a file with --filter
FAT_GREEN=""
GREEN=""
FAT_RED=""
RED=""
MAGENTA=""
FAT_BLACK=""
OFF=""
NL="
"
usage="Usage: ${0##*/} [OPTIONS] FILE1 FILE2"
quiet="no"
diff="no"
filter="no"
diff_opts='--new-file --unified --show-c-function --recursive'
ab="no"
out="-"
style="wdiff"
a2ps=""
a2ps_opts="--prologue=color"
color="yes"
color_filter() {
if [[ $a2ps ]]; then
#seems like a bug in the a2ps style file
sed -e "s/\[-/[wd-/g" -e "s/-\]/-wd]/g" -e "s/{+/{wd+/g" -e "s/+}/+wd}/g" $1
elif [[ $color = yes ]]; then
sed -e "s/\[-/$RED/g" -e "s/-\]/$OFF/g" -e "s/{+/$GREEN/g" -e "s/+}/$OFF/g" $1
else
cat $1
fi
}
die() {
[[ $* ]] && echo "$*"
exit 1
}
qecho() {
[[ $quiet = yes ]] || echo "$*"
}
show_help () {
cat << eof
A colorized version of wdiff
$usage
OPTIONS:
-f, --filter Act as a wdiff color filter only and don't excute diff/wdiff
internally, just colorize input (no ARGS = read from stdin)
-d, --diff Preprocess input with diff and before giving it to wdiff
(very useful for dirs). Option can be used in combination
with --filter option meaning input is a patch.
-D, --diffonly Process input with diff, but NOT with wdiff, so ${0##*/}
basically acts like a colorized version of diff. Option
can be used in combination with --filter option meaning
input is a patch.
--diffopts XXX Change opts of diff
Default: '$diff_opts'
--ab replace trunc of dirname by 'a' and 'b'
--no-color Disable color
(implies --a2psopts '--prologue=ul')
-a, --a2ps Pipe the output to a2ps, which will produce ps code
(also work with --filter)
--a2psopts XXX Change opts of a2ps
Default: '$a2ps_opts'
-o, --out FILE Change output file
Default: stdout
-- Stop parsing options
-h, --help Show this help
-v, --version Show version
--hg Show last log message for hg (or cvs)
Examples: ${0##*/} -d dir1 dir2
${0##*/} file1 file2
${0##*/} --ab -D dir1 dir2
${0##*/} -a --ab -D dir1 dir2 > file.ps
wdiff file1 file2 | ${0##*/} -f
diff -u file1 file2 | ${0##*/} -D -f
Report bugs and comments at https://code.google.com/p/cj-overlay/issues/list
or junghans@votca.org
eof
}
shopt -s extglob
while [[ ${1} = -?* ]]; do
if [[ ${1} = --??*=* ]]; then # case --xx=yy
set -- "${1%%=*}" "${1#*=}" "${@:2}" # --xx=yy to --xx yy
elif [[ ${1} = -[^-]?* ]]; then # case -xy split
if [[ ${1} = -[o]* ]]; then #short opts with arguments
set -- "${1:0:2}" "${1:2}" "${@:2}" # -xy to -x y
else #short opts without arguments
set -- "${1:0:2}" "-${1:2}" "${@:2}" # -xy to -x -y
fi
fi
case $1 in
--ab)
ab="yes"
shift;;
--no-color)
unset FAT_GREEN GREEN FAT_RED RED MAGENTA OFF FAT_BLACK
a2ps_opts="--prologue=ul"
color="no"
shift;;
-f | --filter)
filter="yes"
shift ;;
-d | --diff)
diff="yes"
shift ;;
-D | --diffonly)
diff="only"
shift ;;
-a | --a2ps)
a2ps="a2ps"
unset FAT_GREEN GREEN FAT_RED RED MAGENTA OFF FAT_BLACK
shift ;;
--a2psopts)
a2ps_opts="$2"
shift 2;;
-o | --out)
out="$2"
[[ ! $out ]] && die "Missing filename after --out option"
shift 2;;
--diffopts)
diff_opts="$2"
shift ;;
-q | --quiet)
quiet="yes"
shift ;;
-h | --help)
show_help
exit 0;;
--hg)
echo "${0##*/}: $(sed -ne 's/^#version.* -- \(.*$\)/\1/p' $0 | sed -n '$p')"
exit 0;;
-v | --version)
echo "${0##*/}, $(sed -ne 's/^#\(version.*\) -- .*$/\1/p' $0 | sed -n '$p') by C. Junghans"
exit 0;;
--)
shift
break;;
*)
die "Unknown option '$1'";;
esac
done
[[ $1 = - ]] && filter="yes" && shift
if [[ $filter = no ]]; then
[[ ! $1 || ! $2 ]] && die "Please specify two files/dirs or add --filter option"
#use -e as it could be file or dir
[[ -e $1 ]] || die "Could not read file/dir '$1'"
[[ -e $2 ]] || die "Could not read file/dir '$2'"
[[ $3 ]] && die "I don't know what to do with arguments '${@:3}'"
else
[[ -n $1 && ! -f $1 ]] && die "Could not read file '$1'"
[[ $2 ]] && die "I don't know what to do with arguments '$*' together --filter option"
fi
if [[ $diff != no ]]; then
if [[ $filter = no ]]; then
exec 3< <(diff $diff_opts "$1" "$2")
#don't die here, because diff of binary files give exit code = 2
else
[[ $1 ]] && exec 3<$1 || exec 3<&0
fi
# don't do this if we have not files ;-)
if [[ $ab = yes && $1 && $2 ]]; then
#find the longest equal part in $1 and $2 from the end
for ((i=1;i<=(${#1}<${#2}?${#1}:${#2});i++)); do
[[ ${1:0-$i} != ${2:0-$i} ]] && break
done
((i--))
a="${1:0:${#1}-$i}"
b="${2:0:${#2}-$i}"
else
a=a; b=b
fi
# -r to not expand escape sequences in diff
while read -r -u 3; do
#small trick, because "read -u 3 i" would split the line and
#leading space would be lost.
i="${REPLY}"
if [[ $i = "Files "*" and "*" differ" ]]; then # binary case
i="${i/$a/a}"
i="${i/$b/b}"
echo "$i"
elif [[ $i = diff* ]]; then # diff header line
i="${i/ $diff_opts}"
i="${i/$a/a}"
echo "$FAT_BLACK${i/$b/b}$OFF"
elif [[ $i = ---* ]]; then
echo "${FAT_RED}${i/$a/a}${OFF}"
elif [[ $i = +++* ]]; then
echo "${FAT_GREEN}${i/$b/b}${OFF}"
elif [[ $i = @@* ]]; then
echo "${MAGENTA}${i}${OFF}"
elif [[ $i = -* ]]; then
[[ $diff = only ]] && echo "${RED}${i}${OFF}" || t1+="${i#-}$NL"
elif [[ $i = +* ]]; then
[[ $diff = only ]] && echo "${GREEN}${i}${OFF}" || t2+="${i#+}$NL"
else
# only true for diff != only
# cut the last newline do avoid an empty line at the end (echo append newline)
# echo -n would also work, but wdiff has strange behaviour if the 2nd file is
# empty, it will not append newline, which make the output look strange
[[ $t1 || $t2 ]] && { wdiff <(echo "${t1%$NL}") <(echo "${t2%$NL}") | color_filter; }
t1=
t2=
[[ $diff = only ]] && echo "${i}" || echo "${i## }"
fi
done
# thanks to Arne Babenhauserheide for pointing out this case is missing
# if there was + or - lines at the end, which has not been printed yet
[[ $t1 || $t2 ]] && { wdiff <(echo "${t1%$NL}") <(echo "${t2%$NL}") | color_filter; }
elif [[ $filter = yes ]]; then
color_filter $1
else
wdiff "$1" "$2" | color_filter
fi | if [[ $a2ps ]]; then
a2ps $a2ps_opts "--pretty-print=$style" -o "$out"
else
[[ $out = - ]] && cat || cat > "$out"
fi