xref: /titanic_41/usr/src/lib/libshell/common/fun/pushd (revision 7c2fbfb345896881c631598ee3852ce9ce33fb07)
1#
2# DIRECTORY MANIPULATION FUNCTIONS PUSHD, POPD AND DIRS
3#
4# Uses global parameters _push_max _push_top _push_stack
5integer _push_max=100 _push_top=100
6# Display directory stack -- $HOME displayed as ~
7function dirs
8{
9    typeset dir="${PWD#$HOME/}"
10    case $dir in
11    $HOME)
12        dir=\~
13        ;;
14    /*) ;;
15    *)  dir=\~/$dir
16    esac
17    print -r - "$dir ${_push_stack[@]}"
18}
19
20# Change directory and put directory on front of stack
21function pushd
22{
23    typeset dir= type=0
24    integer i
25    case $1 in
26    "") # pushd
27        if    ((_push_top >= _push_max))
28        then  print pushd: No other directory.
29              return 1
30        fi
31        type=1 dir=${_push_stack[_push_top]}
32        ;;
33    +[1-9]|+[1-9][0-9]) # pushd +n
34        integer i=_push_top$1-1
35        if    ((i >= _push_max))
36        then  print pushd: Directory stack not that deep.
37              return 1
38        fi
39        type=2 dir=${_push_stack[i]}
40        ;;
41    *)  if    ((_push_top <= 0))
42        then  print pushd: Directory stack overflow.
43              return 1
44        fi
45    esac
46    case $dir in
47    \~*)   dir=$HOME${dir#\~}
48    esac
49    cd "${dir:-$1}" > /dev/null || return 1
50    dir=${OLDPWD#$HOME/}
51    case $dir in
52    $HOME)
53        dir=\~
54        ;;
55    /*) ;;
56    *)  dir=\~/$dir
57    esac
58    case $type in
59    0)  # pushd name
60        _push_stack[_push_top=_push_top-1]=$dir
61        ;;
62    1)  # pushd
63        _push_stack[_push_top]=$dir
64        ;;
65    2)  # push +n
66        type=${1#+} i=_push_top-1
67        set -- "${_push_stack[@]}" "$dir" "${_push_stack[@]}"
68        shift $type
69        for dir
70        do  (((i=i+1) < _push_max)) || break
71            _push_stack[i]=$dir
72        done
73    esac
74    dirs
75}
76
77# Pops the top directory
78function popd
79{
80    typeset dir
81    if    ((_push_top >= _push_max))
82    then  print popd: Nothing to pop.
83          return 1
84    fi
85    case $1 in
86    "")
87        dir=${_push_stack[_push_top]}
88        case $dir in
89        \~*)   dir=$HOME${dir#\~}
90        esac
91        cd "$dir" || return 1
92        ;;
93    +[1-9]|+[1-9][0-9])
94        typeset savedir
95        integer i=_push_top$1-1
96        if    ((i >= _push_max))
97        then  print pushd: Directory stack not that deep.
98              return 1
99        fi
100        while ((i > _push_top))
101        do _push_stack[i]=${_push_stack[i-1]}
102              i=i-1
103        done
104        ;;
105    *)  print pushd: Bad directory.
106        return 1
107    esac
108    unset '_push_stack[_push_top]'
109    _push_top=_push_top+1
110    dirs
111}
112