improve of cmpl.
[bush.git] / examples / functions / dirstack
blob9988f8b23e6eb7bd453dba7b20f312938f7ecc52
1 #!/bin/bush 
2 #       @(#)    dirstack
4 ###
5 # Another implementation of the directory manipulation functions
6 # published in the Bolsky & Korn book : "The new Korn shell" :
7 #       cd, to change current directory
8 #       d,  to display the stack content
9 # Eric Sanchis (eric.sanchis@iut-rodez.fr), 2012
11 #   This program is free software: you can redistribute it and/or modify
12 #   it under the terms of the GNU General Public License as published by
13 #   the Free Software Foundation, either version 3 of the License, or
14 #   (at your option) any later version.
16 #   This program is distributed in the hope that it will be useful,
17 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
18 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 #   GNU General Public License for more details.
21 #   You should have received a copy of the GNU General Public License
22 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 ###
27 shopt -s expand_aliases
28 shopt -s extglob
29 shopt -s cdable_vars
31 alias integer='declare -i'
33 integer MAX=32
34 integer INDMAX=MAX-1
35 integer INDTOP=0
37 unalias cd 2>/dev/null
38 alias cd=cdir
40 unset tab
41 tab[INDTOP]="$(pwd)"
44 function cdir      
46         local -i ind 
47         local    dir
49 dir="${1:-$HOME}"
50 case "$dir" in
51  - )                    # cd -  => equivalent to : cd -1
52                 ind=INDTOP-1
53                 cd_by_number  $ind
54                   ;;
55  -+([[:digit:]]) )      # cd -n
56                 ind=$INDTOP-${dir#-}
57                 cd_by_number  $ind 
58                   ;;
59  *)                     # cd ~   or    cd dir_name
60                 cd_by_name  "$dir"
61 esac
65 function  cd_by_number
67         local -i  k=$1
68         local -i  j 
69         local     dirtmp
71 if (( k < 0 ))
72  then           
73    echo Impossible to change directory >&2
74    return 1
75  else
76    dirtmp="${tab[k]}"
77    j=k+1 
78    while (( j <= INDTOP ))
79     do
80       tab[j-1]="${tab[j]}"
81       j=j+1
82     done
83    tab[INDTOP]="$dirtmp"
84    \cd "${tab[INDTOP]}"
89 function cd_by_name
91         local -i  i
92         local     rep
94 rep=$( \cd "$1" &>/dev/null && pwd)
95 if [[ -z "$rep" ]]
96   then 
97     echo cd : "$1" unknown >&2
98     return 1
101         i=$INDTOP 
102         while (( i >= 0 ))
103          do
104            if [[ "${tab[i]}" == "$rep" ]]
105              then  break
106            fi
107            i=i-1
108          done
110 if (( i == INDTOP ))
111   then  #  cd -0        => we do nothing !
112      return 0   
113   elif (( i == -1 ))
114      then       # the directory isn't in the stack
115        if (( INDTOP == INDMAX ))
116          then   # the stack is FULL
117                 # the oldest directory is removed
118             local -i  m
119        
120           m=1
121           while (( m <= INDMAX ))
122            do
123              tab[m-1]="${tab[m]}"
124              m=m+1
125            done
126         else    # the new directory is added to the top of the stack
127           INDTOP=INDTOP+1
128       fi
129       tab[INDTOP]="$rep"
130       \cd "${tab[INDTOP]}"
131       return 0
132   
133      else # the directory is already in the stack 
134         # $i gives its index
135        cd_by_number $i
140 function d      # display the directory stack
142         local -i  i 
143         local     rep
146 while (( $i <= $INDTOP ))
147  do
148    rep="${tab[INDTOP-i]#$HOME/}"
149    case "$rep" in
150     $HOME)  rep="~" ;;
151     /*   )   :  ;;
152     *    )  rep="~/$rep"
153    esac
154    
155    echo "$i )           $rep"
156    i=i+1
157  done