summaryrefslogtreecommitdiff
path: root/examples/scripts.v2/cdhist.bash
blob: df8aea785f77ed7de615bd68c7500e4911efd38e (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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#! /bin/bash
#
# cdhist - cd replacement with a directory stack like pushd/popd
#
# usage: cd [-l] [-n] [-] [dir]
#
# options:
#	-l	print the cd directory stack, one entry per line
#	-	equivalent to $OLDPWD
#	-n	cd to nth directory in cd directory stack
#	-s	cd to first directory in stack matching (substring) `s'
#
# arguments:
#	dir	cd to dir and push dir onto the cd directory stack
#
# If the new directory is a directory in the stack and the options selected
# it (-n, -s), the new working directory is printed
#
# If the variable CDHISTFILE is set, the cd directory stack is loaded from
# and written to $CDHISTFILE every time `cd' is executed.
#
# Note: I got this off the net somewhere; I don't know the original author
#
# Chet Ramey
# chet@po.cwru.edu	

_cd_print()
{
	echo -e "$@"
}

cd()
{
	typeset -i cdlen i
	typeset t
	
	if [ $# -eq 0 ]
	then
		set -- $HOME
	fi
	
	if [ "$CDHISTFILE" ] && [ -r "$CDHISTFILE" ] # if directory history exists
	then
		typeset CDHIST
		i=-1
		while read -r t			# read directory history file
		do
			CDHIST[i=i+1]=$t
		done <$CDHISTFILE
	fi
	
	if [ "${CDHIST[0]}" != "$PWD" ] && [ -n "$PWD" ]
	then
		_cdins				# insert $PWD into cd history
	fi
	
	cdlen=${#CDHIST[*]}			# number of elements in history
	
	case "$@" in
	-)					# cd to new dir
		if [ "$OLDPWD" = "" ] && ((cdlen>1))
		then
			'_cdprint' ${CDHIST[1]}
			builtin cd ${CDHIST[1]}
			pwd
		else
			builtin cd "$@"
			# pwd
		fi
		;;
	-l)					# _cdprint directory list
		((i=cdlen))
		while (((i=i-1)>=0))
		do
			num=$i
			'_cdprint' "$num ${CDHIST[i]}"
		done
		return
		;;
	-[0-9]|-[0-9][0-9])			# cd to dir in list
		if (((i=${1#-})<cdlen))
		then
			'_cdprint' ${CDHIST[i]}
			builtin cd ${CDHIST[i]}
			pwd
		else
			builtin cd $@
			# pwd
		fi
		;;
	-*)					# cd to matched dir in list
		t=${1#-}
		i=1
		while ((i<cdlen))
		do
			case ${CDHIST[i]} in
			*$t*)
				'_cdprint' ${CDHIST[i]}
				builtin cd ${CDHIST[i]}
				pwd
				break
				;;
			esac
			((i=i+1))
		done
		if ((i>=cdlen))
		then
			builtin cd $@
			# pwd
		fi
		;;
	*)					# cd to new dir
		builtin cd $@
		# pwd
		;;
	esac

	_cdins					# insert $PWD into cd history
	
	if [ "$CDHISTFILE" ]
	then
		cdlen=${#CDHIST[*]}		# number of elements in history

		i=0
		while ((i<cdlen))
		do
			echo ${CDHIST[i]}	# update directory history
			((i=i+1))
		done >$CDHISTFILE
	fi
}
	
_cdins()					# insert $PWD into cd history
{						# meant to be called only by cd
	typeset -i i

	i=0

	while (( i < ${#CDHIST[*]} ))		# see if dir is already in list
	do
		if [ "${CDHIST[$i]}" = "$PWD" ]
		then
			break
		fi
		((i=i+1))
	done

	if (( i>22 ))				# limit max size of list
	then
		i=22
	fi

	while (((i=i-1)>=0))			# bump old dirs in list
	do
		CDHIST[i+1]=${CDHIST[i]}
	done

	CDHIST[0]=$PWD				# insert new directory in list
}
	
# examples
shopt -s expand_aliases

# go to known place before doing anything
cd /

echo CDHIST: "${CDHIST[@]}"
for dir in /tmp /bin - -2 -l
do
	cd $dir
	echo CDHIST: "${CDHIST[@]}"
	echo PWD: $PWD

done

exit 0