├── .gitignore ├── .travis.yml ├── Makefile ├── README.md ├── cwdiff └── cwdiff.rc /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | cwdiff.1 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | sudo: false 4 | 5 | addons: 6 | apt: 7 | packages: 8 | - help2man 9 | - groff 10 | 11 | script: 12 | - make && make install DESTDIR="${HOME}" 13 | 14 | after_success: 15 | - git config --global user.name "Automatic Deployment (Travis CI)" 16 | - git config --global user.email "junghans@votca.org" 17 | - git fetch origin gh-pages && git checkout -b gh-pages FETCH_HEAD 18 | - make clean && make 19 | - if [[ ${encrypted_e6f2ead16db9_key} && ${encrypted_e6f2ead16db9_iv} && ${TRAVIS_PULL_REQUEST} == false && ${TRAVIS_BRANCH} == master ]]; then 20 | git commit -a -m "Manpage update"; 21 | openssl aes-256-cbc -K $encrypted_e6f2ead16db9_key -iv $encrypted_e6f2ead16db9_iv -in deploy.enc -out ~/.ssh/id_rsa -d; 22 | chmod 600 ~/.ssh/id_rsa; 23 | git push git@github.com:${TRAVIS_REPO_SLUG} gh-pages:gh-pages; 24 | else 25 | git diff --no-color; 26 | fi 27 | 28 | compiler: 29 | - gcc 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PREFIX=/usr 2 | HGRCDIR=/etc/mercurial/hgrc.d 3 | BINDIR=$(PREFIX)/bin 4 | MANDIR=$(PREFIX)/share/man 5 | 6 | INSTALL=install 7 | 8 | NAME=cwdiff 9 | MAN=$(NAME).1 10 | HGRC=$(NAME).rc 11 | all: $(NAME) $(MAN) 12 | 13 | %.1: % 14 | help2man --no-info --output $@ ./$< 15 | 16 | .PHONY: all clean install 17 | 18 | clean: 19 | rm -f $(MAN) 20 | 21 | install: all 22 | $(INSTALL) -m0755 -D $(NAME) $(DESTDIR)/$(BINDIR)/$(NAME) 23 | [ -z '$(MAN)' ] || $(INSTALL) -m0644 -D $(MAN) $(DESTDIR)/$(MANDIR)/man1/$(MAN) 24 | [ -z '$(HGRCDIR)' ] || $(INSTALL) -m0644 -D $(HGRC) $(DESTDIR)/$(HGRCDIR)/$(HGRC) 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # (w)diff wrapper to support directories and colorize the output 2 | 3 | ## [Documentation](http://junghans.github.io/cwdiff/) 4 | 5 | ## Usage with mercurial 6 | 7 | * add `cwdiff.rc` to your `~/.hgrc` or `/etc/mercurial/hgrc.d/` 8 | 9 | or 10 | 11 | * Download cwdiff 12 | * Enable ExtdiffExtension (in `~/.hgrc`): 13 | ``` 14 | [extensions] 15 | extdiff = 16 | ``` 17 | * Add wdiff command (in `~/.hgrc`): 18 | ``` 19 | [extdiff] 20 | # if cwdiff is in your path, otherwise set to wherever you've installed cwdiff 21 | cmd.wdiff = cwdiff 22 | #add --no-color below, if you dislike colors! 23 | opts.wdiff = --diff --ab 24 | ``` 25 | * Run 26 | ``` 27 | $ hg wdiff 28 | ``` 29 | 30 | ## Packages 31 | 32 | Packages are available for: 33 | * [tarball](https://github.com/junghans/cwdiff/releases) 34 | * [MacPorts](http://www.macports.org/ports.php?by=name&substr=cwdiff) 35 | * [Arch Linux](https://aur.archlinux.org/packages/cwdiff) 36 | * [NetBSD](http://cvsweb.netbsd.org/bsdweb.cgi/pkgsrc/textproc/cwdiff/) 37 | * [Gentoo Linux](http://packages.gentoo.org/package/dev-util/cwdiff) 38 | 39 | ## Issues 40 | 41 | Report bugs on the [github issues site](https://github.com/junghans/cwdiff/issues) 42 | 43 | -------------------------------------------------------------------------------- /cwdiff: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # Copyright (C) 2009-2015 Christoph Junghans 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | # 19 | #version 0.1 04.08.10 -- initial version 20 | #version 0.1.1, 05.08.10 -- added -D and -o 21 | #version 0.1.2, 04.10.10 -- make -D work again and better help 22 | #version 0.1.3, 10.05.11 -- added --text to diff_opts to allow diff of binary files (issue #3) 23 | #version 0.1.4, 10.05.11 -- removed --text again and handle case of binary files 24 | #version 0.2.0, 15.04.12 -- clean up + bugfix thanks to Arne 25 | #version 0.2.1, 15.04.12 -- clean up + new bug report address 26 | #version 0.2.2, 20.04.12 -- fixed a bug if argument were dirs 27 | #version 0.2.3, 18.12.12 -- replace usage of mktemp with bash built-ins 28 | #version 0.2.4, 31.08.13 -- fixed deleted leading spaces 29 | #version 0.2.5, 06.09.13 -- do not expand escape sequences in diff 30 | #version 0.2.6, 18.09.13 -- allow 1st argument begin a file with --filter 31 | #version 0.2.7, 09.03.15 -- included a patch from NetBSD 32 | #version 0.2.8, 13.03.15 -- moved issue tracker to github 33 | #version 0.3.0, 15.03.15 -- print help2man compliant help and version 34 | #version 0.3.1, 30.06.15 -- fix --diffopts option (fixes #4) 35 | #version 0.3.2, 12.11.15 -- make output processable by less -r/-R 36 | #version 0.4.0, 12.11.15 -- dropped a2ps and out option, clean up 37 | 38 | FAT_GREEN="" 39 | GREEN="" 40 | FAT_RED="" 41 | RED="" #also used as indicator 42 | MAGENTA="" 43 | FAT_BLACK="" 44 | OFF="" 45 | NL=" 46 | " 47 | 48 | usage="Usage: ${0##*/} [OPTIONS] FILE1 FILE2" 49 | diff="no" 50 | filter= 51 | diff_opts='--new-file --unified --show-c-function --recursive' 52 | wdiff_opts= 53 | ab= 54 | 55 | color_filter() { 56 | #use RED as an indicator if colors are on 57 | if [[ ${RED} ]]; then 58 | sed -e "s/\[-/$RED/g" -e "s/-\]/$OFF/g" -e "s/{+/$GREEN/g" -e "s/+}/$OFF/g" $1 59 | else 60 | cat $1 61 | fi 62 | } 63 | 64 | die() { 65 | [[ $* ]] && echo "$*" 66 | exit 1 67 | } 68 | 69 | show_help () { 70 | cat << eof 71 | A colorized version of (w)diff, which can be used a wrapper script, too. 72 | $usage 73 | 74 | Options: 75 | -f, --filter Act as a wdiff color filter only and don't execute diff/wdiff 76 | internally, just colorize input (no ARGS = read from stdin) 77 | -d, --diff Preprocess input with diff and before giving it to wdiff 78 | (very useful for dirs). Option can be used in combination 79 | with --filter option meaning input is a patch. 80 | -D, --diffonly Process input with diff, but NOT with wdiff, so ${0##*/} 81 | basically acts like a colorized version of diff. Option 82 | can be used in combination with --filter option meaning 83 | input is a patch. 84 | --diffopts XXX Change options given to diff. The default is '$diff_opts'. 85 | --ab Replace common trunc of dirname by 'a' and 'b' 86 | --no-color Disable color 87 | -- Stop parsing options 88 | -h, --help Show this help 89 | -v, --version Show version 90 | 91 | Examples: 92 | ${0##*/} -d dir1 dir2 Compare two directories 93 | ${0##*/} file1 file2 Compare two files 94 | ${0##*/} --ab -D dir1 dir2 VCS like output from compaing two directories 95 | wdiff file1 file2 | ${0##*/} -f Colorize the output of wdiff 96 | diff -u file1 file2 | ${0##*/} -D -f Colorize the output of diff 97 | 98 | Report bugs and comments at https://github.com/junghans/cwdiff/issues or junghans@votca.org 99 | eof 100 | } 101 | 102 | shopt -s extglob 103 | while [[ ${1} = -?* ]]; do 104 | if [[ ${1} = --??*=* ]]; then # case --xx=yy 105 | set -- "${1%%=*}" "${1#*=}" "${@:2}" # --xx=yy to --xx yy 106 | elif [[ ${1} = -[^-]?* ]]; then # case -xy split 107 | if [[ ${1} = -[o]* ]]; then #short opts with arguments 108 | set -- "${1:0:2}" "${1:2}" "${@:2}" # -xy to -x y 109 | else #short opts without arguments 110 | set -- "${1:0:2}" "-${1:2}" "${@:2}" # -xy to -x -y 111 | fi 112 | fi 113 | case $1 in 114 | --ab) 115 | ab="yes" 116 | shift;; 117 | --no-color) 118 | unset FAT_GREEN GREEN FAT_RED RED MAGENTA OFF FAT_BLACK 119 | shift;; 120 | -f | --filter) 121 | filter="yes" 122 | shift ;; 123 | -d | --diff) 124 | diff="yes" 125 | shift ;; 126 | -D | --diffonly) 127 | diff="only" 128 | shift ;; 129 | --diffopts) 130 | diff_opts="$2" 131 | shift 2;; 132 | -h | --help) 133 | show_help 134 | exit 0;; 135 | --vcs) 136 | echo "${0##*/}: $(sed -ne 's/^#version.* -- \(.*$\)/\1/p' $0 | sed -n '$p')" 137 | exit 0;; 138 | -v | --version) 139 | cat << eov 140 | ${0##*/} $(sed -ne 's/^#version \(.*\) -- .*$/\1/p' "$0" | sed -n '$p') 141 | 142 | $(sed -ne 's/^# \(Copyright.*\)/\1/p' "$0") 143 | This is free software: you are free to change and redistribute it. 144 | License GPLv2+: GNU GPL version 2 or later 145 | There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 146 | 147 | Written by C. Junghans 148 | eov 149 | exit 0;; 150 | --) 151 | shift 152 | break;; 153 | *) 154 | die "Unknown option '$1'";; 155 | esac 156 | done 157 | 158 | [[ $1 = - ]] && filter="yes" && shift 159 | if [[ ! $filter ]]; then 160 | [[ ! $1 || ! $2 ]] && die "Please specify two files/dirs or add --filter option" 161 | #use -e as it could be file or dir 162 | [[ -e $1 ]] || die "Could not read file/dir '$1'" 163 | [[ -e $2 ]] || die "Could not read file/dir '$2'" 164 | [[ $3 ]] && die "I don't know what to do with arguments '${@:3}'" 165 | else 166 | [[ -n $1 && ! -f $1 ]] && die "Could not read file '$1'" 167 | [[ $2 ]] && die "I don't know what to do with arguments '$*' together --filter option" 168 | fi 169 | 170 | if [[ $diff != no ]]; then 171 | if [[ ! $filter ]]; then 172 | exec 3< <(diff $diff_opts "$1" "$2") 173 | #don't die here, because diff of binary files give exit code = 2 174 | else 175 | [[ $1 ]] && exec 3<$1 || exec 3<&0 176 | fi 177 | # don't do this if we have not files ;-) 178 | if [[ $ab && $1 && $2 ]]; then 179 | #find the longest equal part in $1 and $2 from the end 180 | for ((i=1;i<=(${#1}<${#2}?${#1}:${#2});i++)); do 181 | [[ ${1:0-$i} != ${2:0-$i} ]] && break 182 | done 183 | ((i--)) 184 | a="${1:0:${#1}-$i}" 185 | b="${2:0:${#2}-$i}" 186 | else 187 | a=a; b=b 188 | fi 189 | # -r to not expand escape sequences in diff 190 | while read -r -u 3; do 191 | #small trick, because "read -u 3 i" would split the line and 192 | #leading space would be lost. 193 | i="${REPLY}" 194 | if [[ $i = "Files "*" and "*" differ" ]]; then # binary case 195 | i="${i/$a/a}" 196 | i="${i/$b/b}" 197 | echo "$i" 198 | elif [[ $i = diff* ]]; then # diff header line 199 | i="${i/ $diff_opts}" 200 | i="${i/$a/a}" 201 | echo "$FAT_BLACK${i/$b/b}$OFF" 202 | elif [[ $i = ---* ]]; then 203 | echo "${FAT_RED}${i/$a/a}${OFF}" 204 | elif [[ $i = +++* ]]; then 205 | echo "${FAT_GREEN}${i/$b/b}${OFF}" 206 | elif [[ $i = @@* ]]; then 207 | echo "${MAGENTA}${i}${OFF}" 208 | elif [[ $i = -* ]]; then 209 | [[ $diff = only ]] && echo "${RED}${i}${OFF}" || t1+="${i#-}$NL" 210 | elif [[ $i = +* ]]; then 211 | [[ $diff = only ]] && echo "${GREEN}${i}${OFF}" || t2+="${i#+}$NL" 212 | else 213 | # only true for diff != only 214 | # cut the last newline do avoid an empty line at the end (echo append newline) 215 | # echo -n would also work, but wdiff has strange behaviour if the 2nd file is 216 | # empty, it will not append newline, which make the output look strange 217 | [[ $t1 || $t2 ]] && { wdiff $wdiff_opts ${RED:+-n} <(echo "${t1%$NL}") <(echo "${t2%$NL}") | color_filter; } 218 | t1= 219 | t2= 220 | [[ $diff = only ]] && echo "${i}" || echo "${i## }" 221 | fi 222 | done 223 | # thanks to Arne Babenhauserheide for pointing out this case is missing 224 | # if there was + or - lines at the end, which has not been printed yet 225 | [[ $t1 || $t2 ]] && { wdiff $wdiff_opts ${RED:+-n} <(echo "${t1%$NL}") <(echo "${t2%$NL}") | color_filter; } 226 | elif [[ $filter ]]; then 227 | color_filter $1 228 | else 229 | wdiff $wdiff_opts ${RED:+-n} "$1" "$2" | color_filter 230 | fi 231 | -------------------------------------------------------------------------------- /cwdiff.rc: -------------------------------------------------------------------------------- 1 | #see http://mercurial.selenic.com/wiki/WordDiff 2 | #add this to your ~/.hgrc or install this file as /etc/mercurial/hgrc.d/cwdiff.rc 3 | [extensions] 4 | extdiff = 5 | 6 | [extdiff] 7 | cmd.wdiff = cwdiff 8 | opts.wdiff = --diff --ab 9 | --------------------------------------------------------------------------------