#!/bin/sh

# Script for using ViM as a PAGER.
# Based on Bram's less.sh.
# Version 1.7.0
# git://github.com/rkitover/vimpager.git

# Just pass through if not on a tty
if [ ! -t 1 ]; then
	exec cat "$@"
fi

case `uname -s` in
	Linux) linux=1 ;;
	SunOS) solaris=1 ;;
        Darwin) osx=1; bsd=1 ;;
	CYGWIN*) cygwin=1 ;;
	MINGW*) msys=1 ;;
	OpenBSD) openbsd=1; bsd=1 ;;
	*) bsd=1 ;;
esac

less_vim() {
	vimrc=""

	if [ -n "$VIMPAGER_RC" ]; then
		vimrc=$VIMPAGER_RC
	elif [ -n "$msys" ]; then
		if [ -f ~/_vimpagerrc ]; then
			vimrc=~/_vimpagerrc
		elif [ -f ~/.vimpagerrc ]; then
			vimrc=~/.vimpagerrc
		fi
	elif [ -f ~/.vimpagerrc ]; then
		vimrc=~/.vimpagerrc
	elif [ -f ~/_vimpagerrc ]; then
		vimrc=~/_vimpagerrc
	fi

	if [ -z "$msys" ]; then
		trap "rm -f /tmp/vimpager_opts_$$" HUP INT QUIT ILL TRAP KILL BUS TERM

		# the echo "foo" is to skip the color codes and make matching the first line easier

		if [ -n "$vimrc" ]; then
			(vim -u "$vimrc" -X -e -c 'echo "foo"' -c 'if exists("vimpager_use_gvim") | echo vimpager_use_gvim | else | echo 0 | endif' -c 'if exists("vimpager_disable_x11") | echo vimpager_disable_x11 | else | echo 0 | endif' -c 'if exists("vimpager_scrolloff") | echo vimpager_scrolloff | else | echo 5 | endif | echo 0' -c q < /dev/tty) > /tmp/vimpager_opts_$$
		else
			(vim -X -e -c 'echo "foo"' -c 'if exists("vimpager_use_gvim") | echo vimpager_use_gvim | else | echo 0 | endif' -c 'if exists("vimpager_disable_x11") | echo vimpager_disable_x11 | else | echo 0 | endif' -c 'if exists("vimpager_scrolloff") | echo vimpager_scrolloff | else | echo 5 | endif | echo 0' -c q < /dev/tty) > /tmp/vimpager_opts_$$
		fi

		head -2 < /tmp/vimpager_opts_$$ | tail -1 | awk '$1 ~ /^1/ {t=1} END {exit 1-t}' && \
			use_gvim=1

		head -3 < /tmp/vimpager_opts_$$ | tail -1 | awk '$1 ~ /^1/ {t=1} END {exit 1-t}' && \
			disable_x11=1

		head -4 < /tmp/vimpager_opts_$$ | tail -1 | awk '$1 ~ /^[0-9]+/ {t=1} END {exit 1-t}' && \
			scrolloff=`head -4 < /tmp/vimpager_opts_$$ | tail -1 | sed -e 's/.*//'`

		rm -f /tmp/vimpager_opts_$$
	else
		# The above doesn't work on msys for some reason, so we use
		# grep.

		_vimrc_file="${vimrc:-~/_vimrc}"

		if [ ! -e "$_vimrc_file" ]; then
			_vimrc_file=~/.vimrc
		fi

		use_gvim=`grep '^[ \t]*\<let[ \t]\+vimpager_use_gvim[ \t]\+=[ \t]\+1' "$_vimrc_file" 2>/dev/null | head -1`

		disable_x11=`grep '^[ \t]*\<let[ \t]\+vimpager_disable_x11[ \t]\+=[ \t]\+1' "$_vimrc_file" 2>/dev/null | head -1`

		scrolloff=`grep '^[ \t]*\<let[ \t]\+vimpager_scrolloff[ \t]\+=[ \t]\+[0-9]+' "$_vimrc_file" 2>/dev/null | head -1`

		# msys may not be installed with an msys vim, and if we're
		# not in a real console the native Windows vim will not
		# work, so we have to use gvim.

		if [ "x$TERM" != "xdumb" -a "x$TERM" != "xcygwin" -a "x$TERM" != "x" ]; then
			if [ \( ! -x /bin/vim \) -a \( ! -x /usr/bin/vim \) -a \( ! -x /usr/local/bin/vim \) ]; then
				use_gvim=1
			fi
		fi

		unset _vimrc_file
	fi

        if [ -n "$use_gvim" ]; then
                if [ -n "$osx" ]; then
			if [ -z "$SSH_CONNECTION" ] && command -v mvim >/dev/null; then
				vim_cmd="mvim -R"
			else
				vim_cmd="vim -R"
			fi
		elif [ -n "$cygwin" ]; then
			if command -v gvim >/dev/null; then
				# The Cygwin gvim uses X
				if ldd `command -v gvim` 2>/dev/null \
				   | awk '$1 ~ /cygwin/ {t=1} END { exit 1-t }'; then
					if [ -z "$DISPLAY" ]; then
						vim_cmd="vim -R"
					else
						vim_cmd='gvim -R'
					fi
				elif [ -z "$SSH_CONNECTION" ]; then
					vim_cmd='gvim -R'
				else
					vim_cmd="vim -R"
				fi
			else
				vim_cmd="vim -R"
			fi
		elif [ -n "$msys" ]; then
			if [ -z "$SSH_CONNECTION" ] && command -v gvim >/dev/null; then
				vim_cmd='gvim -R'
			else
				vim_cmd="vim -R"
			fi
		elif [ -z "$DISPLAY" ]; then
			vim_cmd='vim -R'
		else
			if command -v gvim >/dev/null; then
				vim_cmd='gvim -R'
			else
				vim_cmd="vim -R"
			fi
		fi
	else
	        vim_cmd='vim -R'
	fi

	rm -f gvim.exe.stackdump # for cygwin gvim, which can be part of vim

	case $vim_cmd in
		vim*)
			if [ -n "$disable_x11" ]; then
				vim_cmd="$vim_cmd -X"
			fi

			if [ -n "$vimrc" ]; then
				$vim_cmd \
				--cmd 'let vimpager=1' \
				--cmd 'runtime! macros/less.vim' \
				-u $vimrc \
				-c 'set scrolloff='${scrolloff:-5}' | set foldlevel=999 | set nonu | silent! set nornu' \
				-c 'nmap <ESC>u :nohlsearch<cr> | nnoremap <Down> 1<C-d> | nnoremap <Up> 1<C-u> | noremap q :q<CR>' \
				"${@:--}"
			else
				$vim_cmd \
				--cmd 'let vimpager=1' \
				--cmd 'runtime! macros/less.vim' \
				-c 'set scrolloff='${scrolloff:-5}' | set foldlevel=999 | set nonu | silent! set nornu' \
				-c 'nmap <ESC>u :nohlsearch<cr> | nnoremap <Down> 1<C-d> | nnoremap <Up> 1<C-u> | noremap q :q<CR>' \
				"${@:--}"
			fi
			;;
		*) # gvim or mvim GUI
			if [ -f ~/.gvimrc ]; then
				gvimrc=~/.gvimrc
			elif [ -f ~/_gvimrc ]; then
				gvimrc=~/_gvimrc
			elif [ -n "$cygwin" ]; then
# this from Corinna at http://cygwin.com/ml/cygwin/2010-08/msg00246.html
				_sid=$(grep "^$USER:" /etc/passwd | sed -e 's/[^:]*:[^:]*:[^:]*:[^:]*:[^:]*,\(S-1-5-[^:]*\):.*/\1/')
				_prof=$(cat /proc/registry/HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows\ NT/CurrentVersion/ProfileList/${_sid}/ProfileImagePath)

				if [ -f "${_prof}/_gvimrc" ]; then
					gvimrc="${_prof}/_gvimrc"
				elif [ -f "${_prof}/.gvimrc" ]; then
					gvimrc="${_prof}/.gvimrc"
				fi

				unset _sid
				unset _prof
			fi

			[ -n "$gvimrc" ] && colors=`grep guifg $gvimrc 2>/dev/null | head -1`

			# Check if the user maximized the window in ~/_gvimrc on Win32, if
			# so restore on startup.
			if [ -n "$gvimrc" -a \( -n "$cygwin" -o -n "$msys" \) ]; then
				simalt=`grep simalt $gvimrc 2>/dev/null | head -1`

				if [ -n "$simalt" ]; then
					restore="simalt ~r"
				fi
			fi

			if command -v tput > /dev/null; then
				# this is the only way it works on Cygwin
				trap "rm -f /tmp/vimpager_cols_$$ /tmp/vimpager_lines_$$" HUP INT QUIT ILL TRAP KILL BUS TERM

				tput cols  > /tmp/vimpager_cols_$$
				tput lines > /tmp/vimpager_lines_$$

				cols=`cat /tmp/vimpager_cols_$$`
				lines=`cat /tmp/vimpager_lines_$$`

				rm -f /tmp/vimpager_cols_$$ /tmp/vimpager_lines_$$
			fi

			# msys has no tput, this doesn't work on Cygwin by the way
			if [ -z "$cols" ] && command -v bash >/dev/null; then
				cols=`bash -i -c 'echo $COLUMNS'`
				lines=`bash -i -c 'echo $LINES'`
			fi

			# If we are unable to detect lines/columns, maximize
			# the window.
			if [ -z "$cols" ]; then
				cols=999
				lines=999
			fi

			if [ -n "$vimrc" ]; then
				$vim_cmd \
				--cmd 'let vimpager=1' \
				--cmd 'runtime! macros/less.vim ' \
				-u $vimrc \
				-c 'set scrolloff='${scrolloff:-5}' | set foldlevel=999 | set nonu | silent! set nornu' \
				-c 'nmap <ESC>u :nohlsearch<cr> | nnoremap <Down> 1<C-d> | nnoremap <Up> 1<C-u> | noremap q :q<CR>' \
				-c "${colors:-echo}" \
				-c "${restore:-echo}" \
				-c "set lines=$lines | set columns=$cols" \
				"${@:--}" &
			else
				$vim_cmd \
				--cmd 'let vimpager=1' \
				--cmd 'runtime! macros/less.vim ' \
				-c 'set scrolloff='${scrolloff:-5}' | set foldlevel=999 | set nonu | silent! set nornu' \
				-c 'nmap <ESC>u :nohlsearch<cr> | nnoremap <Down> 1<C-d> | nnoremap <Up> 1<C-u> | noremap q :q<CR>' \
				-c "${colors:-echo}" \
				-c "${restore:-echo}" \
				-c "set lines=$lines | set columns=$cols" \
				"${@:--}" &
			fi
			;;
	esac

	rm -f gvim.exe.stackdump # for cygwin gvim, which can be part of vim
}

awk_pstree() {
	awk -v mypid=$1 '{
		cmd[$1]=$3
		ppid[$1]=$2
	}
	END {
		while (mypid != 1 && cmd[mypid]) {
			ptree=mypid " " cmd[mypid] "\n" ptree
			mypid=ppid[mypid]
		}
		print ptree
	}'
}

do_ptree() {
	if [ -n "$solaris" ]; then
		# Tested on Solaris 8 and 10
		ptree $$
	elif [ -n "$cygwin" -o -n "$msys" ]; then
		ps | awk '{ print $1 "\t" $2 "\t" $NF }' | awk_pstree $$
	elif [ -n "$openbsd" ]; then
		ps awo pid=,ppid=,command= | awk_pstree $$
	else
		# Tested on Linux and OS X
		ps awo pid=,ppid=,comm= | awk_pstree $$
	fi
}

# Check if called from man, perldoc or pydoc
if do_ptree | awk '$2 ~ /(^|\/)(man|perl(doc)?([0-9.]*)?|py(thon|doc|doc2))/ {t=1} END { exit 1-t }'; then
	extra_c="set ft=man"
fi

extra_cmd="let vimpager_ptree=[$(do_ptree | awk '{ print "\"" $2 "\"" }' | tr '\n' ',')] | call remove(vimpager_ptree, -1)"

trap "rm -rf /tmp/vimpager_$$" HUP INT QUIT ILL TRAP KILL BUS TERM

mkdir -m 0700 /tmp/vimpager_$$

command -v perl > /dev/null && \
	perl -le 'exit($] >= 5.008001 ? 0 : 1)' && have_perl=1

col_b() {
	if [ "x$have_perl" != "x" ]; then
		perl -CIOL -pe 'no warnings "utf8"; s/.\010//g'
	else
		sed -e 's/.//g'
	fi
}

filename=${@:-stdin}
filename=`echo "$filename" | tr '/' '_'`
filename="/tmp/vimpager_${$}/$filename"

case "$@" in
	*.gz) gunzip -c "$@" | sed -e 's/\[[^m]*m//g' | col_b > "$filename" ;;
	*.Z) uncompress -c "$@" | sed -e 's/\[[^m]*m//g' | col_b > "$filename" ;;
	*) sed -e 's/\[[^m]*m//g' "$@" | col_b > "$filename" ;;
esac

# if file is zero length, or one blank line (cygwin) exit immediately
if [ \( ! -s "$filename" \) \
	-o \( \( "`cat \"$filename\"`" = "" \) \
		-a \( "`wc -l \"$filename\" | awk '{print $1}'`" = "1" \) \) ]; then
	exit
fi

# On cygwin it might be the win32 gvim, but windows paths work for cygwin
# vim just fine as well.
if [ -n "$cygwin" ]; then
	filename=`cygpath -w "$filename"`
fi

less_vim -c "${extra_c:-echo}" --cmd "${extra_cmd:-echo}" "$filename" </dev/tty

# terminal vim on OSX can screw up the terminal
# (but doesn't anymore for some reason...)
#if [ -n "$osx" ]; then
#	case $vim_cmd in
#		vim*)
#			reset
#			clear
#			;;
#	esac
#fi

# Give gvim/mvim time to open the file.
# On Cygwin we must also wait for the process to exit before the file can
# be deleted.
(
	while [ -d /tmp/vimpager_$$ ]; do
		sleep 3
		rm -rf /tmp/vimpager_$$ 2>/dev/null
		rm -f gvim.exe.stackdump 2>/dev/null
	done
) &

# CONTRIBUTORS:
#
# Rafael Kitover
# Antonio Ospite
# Jean-Marie Gaillourdet
# Perry Hargrave
# Koen Smits
# Ivan S. Freitas <ivansichfreitas@gmail.com>
# Wout Mertens (Solaris compatibility, less processes)
# Jacobo de Vera (add -X option for faster startup)
# Damien Pollet <damien.pollet@gmail.com>
# Peter Fern <github@obfusc8.org>
# Wei Dai <x@wei23.net>
# Iftekharul Haque <iftekharul.haque@gmail.com>
# Anselm Strauss <amsibamsi@gmail.com>
# Anisse Astier <anisse@astier.eu>
# Simon Olofsson <simon@olofsson.de>

# vim:noet ts=8 sts=8 sw=8 tw=0:
