summaryrefslogtreecommitdiffstats
path: root/examples/functions/dirstack
blob: d68e6198fbae11bab93c0a4efa28c61e41968fb1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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
}