#!/bin/sh -

dfltout=.grep.err

# vigrep - edit all files containing the given regexp
# Steve Kinzler, steve@kinzler.com, Nov 93/Jul 98/Jun 01
# https://kinzler.com/me/home.html#unix

set x $VIGREPOPTS ${1+"$@"}; shift

grepout=; perl=; case=; word=; multi=; grepopts=; bad=

while :
do
	case $# in
	0)	break;;
	*)	case "$1" in
		-e)	shift; EDITOR="$1";;
		-l)	EDITOR='ls -d';;
		-f)	shift; grepout="$1";;
		-g)	perl=;;
		-p)	perl=t;;
		-i)	case=i;;
		-w)	word=w;;
		-m)	multi=m;;
		--?*)	grepopts="$grepopts $1";;

		--)	shift; break;;
		-h)	bad=t; break;;
		-*)	bad=t; echo "$0: unknown option ($1)" 1>&2;;
		*)	break;;
		esac
		shift;;
	esac
done

case "$bad" in
?*)	cat << EOF 1>&2
usage: $0 [ -e editor ] [ -l ] [ -f file ] [ -g | -p ]
       [ -i ] [ -w ] [ -m ] [ --grepopt ... ] [ regexp [ file ... ] ]
with no regexp, reads from the -f file else $dfltout else ~/$dfltout
with no files, greps on all files in the current directory
	-e	invokes the given editor or command head (default vi)
	-l	just lists the matched files
	-g	use grep regular expressions (default)
	-p	use perl regular expressions
	-i	use case-insensitive matching with the regexp
	-w	imply word boundaries around the regexp (newer greps only)
	-m	use multiline matching (implies -p)
Any options beginning with -- are taken to be single-word grep options
and used with grep (only, not perl) reinterpreted (so double-escape the
option if needed).
EOF
	exit 1;;
esac

case $# in
0)	case "$grepout" in
	'')	if   test -r $dfltout;	     then grepout=$dfltout
		elif test -r $HOME/$dfltout; then grepout=$HOME/$dfltout
		else echo "$0: cannot find $dfltout" 1>&2; exit 2
		fi;;
	esac

	expr=`sed -n "2s/^[^']*'\([^']*\)'.*/\1/p; 2q" "$grepout"`

	set x `sed 's/:.*//; /[	 ]/d' "$grepout" | uniq`;;

*)	expr="$1"; shift
	case "$word" in
	?*)	pexpr="\\b$expr\\b"; expr="\\<$expr\\>";;
	*)	pexpr="$expr";;
	esac

	case $# in
	0)	set x `ls -a | sed '/^\.$/d; /^\.\.$/d'`; shift;;
	esac

	case $# in
	0)	set x;;
	*)	case "$multi,$perl" in
		?*,*)	set x `perl -e  'for $a (@ARGV) {
					   open(A, $a) || warn "$0: $a: $!\n";
					   print "$a\n" if join("", <A>) =~
						'"m$pexpros$case }" "$@"`;;
		*,?*)	set x `perl -ne 'print("$ARGV\n"), close ARGV
					     if '"m$pexpro$case"    "$@"`;;
		*)	set x `grep -d skip -l"$case"$grepopts "$expr" "$@"`;;
		esac;;
	esac;;
esac

shift
case $# in
0)	exit;;
esac

EDITOR=${EDITOR-vi}
case "$EDITOR" in
vi|vi[ma]|nvi|elvis|view|vedit|ex|edit|e|more|less|\
[rg]vim|[rg]view|[rg]ex|rgvim|rgview|\
*/vi|*/vi[ma]|*/nvi|*/elvis|*/view|*/vedit|*/ex|*/edit|*/e|*/more|*/less|\
*/[rg]vim|*/[rg]view|*/[rg]ex|*/rgvim|*/rgview)
	case "$case,$EDITOR" in
	*more|*less)	;;
	?*,*)		EDITOR="$EDITOR -c 'set ic'";;
	esac
	case "$expr" in
	?*)		expr=`echo "$expr" | sed 's,/,\\\\/,g'`
			EDITOR="$EDITOR '+/$expr'";;
	esac;;
'')	echo "$0: aborting, null editor" 1>&2; exit 3;;
esac

for arg
do
	args="$args '$arg'"
done

exec ${SHELL-sh} -c "$EDITOR $args"
