diff options
Diffstat (limited to 'examples/functions/dirstack')
-rw-r--r-- | examples/functions/dirstack | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/examples/functions/dirstack b/examples/functions/dirstack new file mode 100644 index 0000000..d68e619 --- /dev/null +++ b/examples/functions/dirstack @@ -0,0 +1,160 @@ +#!/bin/bash +# @(#) dirstack + +### +# Another implementation of the directory manipulation functions +# published in the Bolsky & Korn book : "The new Korn shell" : +# cd, to change current directory +# d, to display the stack content +# Eric Sanchis (eric.sanchis@iut-rodez.fr), 2012 +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +### + + +shopt -s expand_aliases +shopt -s extglob +shopt -s cdable_vars + +alias integer='declare -i' + +integer MAX=32 +integer INDMAX=MAX-1 +integer INDTOP=0 + +unalias cd 2>/dev/null +alias cd=cdir + +unset tab +tab[INDTOP]="$(pwd)" + + +function cdir +{ + local -i ind + local dir + +dir="${1:-$HOME}" +case "$dir" in + - ) # cd - => equivalent to : cd -1 + ind=INDTOP-1 + cd_by_number $ind + ;; + -+([[:digit:]]) ) # cd -n + ind=$INDTOP-${dir#-} + cd_by_number $ind + ;; + *) # cd ~ or cd dir_name + cd_by_name "$dir" +esac +} + + +function cd_by_number +{ + local -i k=$1 + local -i j + local dirtmp + +if (( k < 0 )) + then + echo Impossible to change directory >&2 + return 1 + else + dirtmp="${tab[k]}" + j=k+1 + while (( j <= INDTOP )) + do + tab[j-1]="${tab[j]}" + j=j+1 + done + tab[INDTOP]="$dirtmp" + \cd "${tab[INDTOP]}" +fi +} + + +function cd_by_name +{ + local -i i + local rep + +rep=$( \cd "$1" &>/dev/null && pwd) +if [[ -z "$rep" ]] + then + echo cd : "$1" unknown >&2 + return 1 +fi + + i=$INDTOP + while (( i >= 0 )) + do + if [[ "${tab[i]}" == "$rep" ]] + then break + fi + i=i-1 + done + +if (( i == INDTOP )) + then # cd -0 => we do nothing ! + return 0 + elif (( i == -1 )) + then # the directory isn't in the stack + if (( INDTOP == INDMAX )) + then # the stack is FULL + # the oldest directory is removed + local -i m + + m=1 + while (( m <= INDMAX )) + do + tab[m-1]="${tab[m]}" + m=m+1 + done + else # the new directory is added to the top of the stack + INDTOP=INDTOP+1 + fi + tab[INDTOP]="$rep" + \cd "${tab[INDTOP]}" + return 0 + + else # the directory is already in the stack + # $i gives its index + cd_by_number $i +fi +} + + +function d # display the directory stack +{ + local -i i + local rep + +i=0 +while (( $i <= $INDTOP )) + do + rep="${tab[INDTOP-i]#$HOME/}" + case "$rep" in + $HOME) rep="~" ;; + /* ) : ;; + * ) rep="~/$rep" + esac + + echo "$i ) $rep" + i=i+1 + done +} + + |