#!/usr/bin/env ksh
# Change directory and put directory on front of stack
function pushd {
    typeset dir=''
    typeset type=0
    integer i
    case $1 in
    "") # pushd
        # shellcheck disable=SC2154
        if ((_push_top >= _push_max))
        then
            print pushd: 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))
        if ((i >= _push_max))
        then
            print pushd: Directory stack not that deep.
            return 1
        fi
        type=2
        dir=${_push_stack[i]}
        ;;
    *)  if ((_push_top <= 0))
        then
            print pushd: Directory stack overflow.
            return 1
        fi
    esac
    case $dir in
    \~*)   dir=$HOME${dir#\~}
    esac
    cd "${dir:-$1}" > /dev/null || return 1
    dir=${OLDPWD#$HOME/}
    case $dir in
    $HOME)
        dir=\~
        ;;
    /*) ;;
    *)  dir=\~/$dir
    esac
    case $type in
    0)  # pushd name
        _push_top=$((_push_top - 1))
        _push_stack[_push_top]=$dir
        ;;
    1)  # pushd
        _push_stack[_push_top]=$dir
        ;;
    2)  # push +n
        type=${1#+}
        set -- "${_push_stack[@]}" "$dir" "${_push_stack[@]}"
        shift "$type"
        integer i=$(( _push_top - 1 ))
        for dir
        do
            (( (i = i + 1) < _push_max )) || break
            _push_stack[i]=$dir
        done
    esac
    dirs
}
