########################################################################
#                                                                      #
#               This software is part of the ast package               #
#          Copyright (c) 1982-2012 AT&T Intellectual Property          #
#          Copyright (c) 2020-2023 Contributors to ksh 93u+m           #
#                      and is licensed under the                       #
#                 Eclipse Public License, Version 2.0                  #
#                                                                      #
#                A copy of the License is available at                 #
#      https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html      #
#         (with md5 checksum 84283fa8859daf213bdda5a9f8d1be1d)         #
#                                                                      #
#                  David Korn <dgk@research.att.com>                   #
#                  Martijn Dekker <martijn@inlv.org>                   #
#                                                                      #
########################################################################
#
# pushd: push the current directory onto the directory stack
# and change to the given new directory.
# For use in conjunction with 'cd', 'dirs', 'mcd', 'popd'.

# Use cd wrapper from .../fun/cd
autoload cd

# Non-destructively initialize global parameters for directory stack.
# Default stack size is 32, or $CDSTACK if set before init.
integer _push_max=${_push_max:-${CDSTACK:-32}}
integer _push_top=${_push_top:-${CDSTACK:-32}}
typeset -a _push_stack

# Change directory and put directory on front of stack
function pushd
{
	typeset dir= type=0
	integer i
	case $1 in
	"")	# pushd
		if	((_push_top >= _push_max))
		then	print -u2 "$0: No other directory."
			return 1
		fi
		type=1
		dir=${_push_stack[_push_top]}
		;;
	+[1-9]|+[1-9][0-9])
		# pushd +n
		integer i=_push_top$1-1
		if	((i >= _push_max))
		then	print -u2 "$0: Directory stack not that deep."
			return 1
		fi
		type=2
		dir=${_push_stack[i]}
		;;
	*)	if	((_push_top <= 0))
		then	print -u2 "$0: Directory stack overflow."
			return 1
		fi
		;;
	esac
	# change ~ to $HOME
	case $dir in
	\~*)	dir=$HOME${dir#\~} ;;
	esac
	\command cd -- "${dir:-$1}" > /dev/null || return
	# change $HOME to ~
	dir=${OLDPWD#"$HOME/"}
	case $dir in
	"$HOME")dir=\~ ;;
	/*)	;;
	*)	dir=\~/$dir ;;
	esac
	case $type in
	0)	# pushd name
		_push_stack[_push_top=_push_top-1]=$dir
		;;
	1)	# pushd
		_push_stack[_push_top]=$dir
		;;
	2)	# push +n
		type=${1#+}
		i=_push_top-1
		set -- "${_push_stack[@]}" "$dir" "${_push_stack[@]}"
		shift "$type"
		for dir
		do	(((i=i+1) < _push_max)) || break
			_push_stack[i]=$dir
		done
		;;
	esac
	dirs
}
