[net.sources] Another set of ksh functions for directory tracking

pph@hocsj.UUCP (10/14/84)

[]

Here is another set of ksh functions to keep track of past directories.
These functions manipulate a stack of the past 32 directories visited.
Cut below the dashed line.  

dirs [N]
	Prints the past N directories (default 10) in the following 
	format:

	0:	/gaz/games
	1:	/usr/src/cmd
	2:	/ja/pph
	3:	/gaz/games
	4:	/ja/pph/rje

	Directory 0 is $PWD.  Directory 1 was visited just before
	directory 0, etc.

fd pattern
	Prints out the past directories matching pattern in the above
	format.  Pattern is of the same form as patterns for file name
	generation.

cd [- | -N | dir]
	Connects to a directory and then pushes that directory on the
	stack if it is different from $PWD.

	-	Connects to directory 1, switches directories 0 and 1,
		and prints the directory.

	-N	When N is 1, this is identical with cd -.  Otherwise 
		connects to directory N, pushes it on the stack (if
		it is different from directory 0), and prints the
		directory.

	dir	Connects to dir and pushes it on the stack if it is
		different from directory 0.

	With no arguments, cd is equivalent to cd $HOME.

				Phil Heisler
				ihnp4!hocsj!pph

------------------------ Cut Here --------------------------------------
if test "`whence cd`" = 'cd'
then
	# cd is not predefined and it is ok to redefine it

integer _NEXTCD _DIRSDEF=${_DIRSDEF:-10} _CDSIZE=${_CDSIZE:-32}
_CDSTACK[0]=${PWD:-$HOME}
_NEXTCD=1
# _NEXTCD is the next place in _CDSTACK for a new directory to go

_pushd ()
# pushes directories on _CDSTACK
{
	if test $# -gt 1 
	then
		print - "Usage: cd [ - | -N | directory ]" '\n' \
			"\tchoices were: $@" 1>&2
		return
	fi
	if test $# -eq 0
	then
		_pushd $HOME
		return
	fi
	typeset err="cd: nowhere to go" tmp
	integer first second
	case "$1" in
	-0)
		# print current directory
		print - $PWD
		return
		;;

	-|-1)
		# switch top and 2nd elements
		(( second = (_NEXTCD + _CDSIZE -2) % _CDSIZE ))
		if test "${_CDSTACK[$second]:-}" = ""
		then
			print - $err 1>&2
			return
		fi
		(( first = (second + 1) % _CDSIZE ))
		tmp=${_CDSTACK[$second]}
		cd $tmp
		_CDSTACK[$second]=${_CDSTACK[$first]}
		_CDSTACK[$first]=$tmp
		print - $tmp
		;;

	-*)
		# go to a prior directory
		(( first = (_NEXTCD + _CDSIZE + $1 - 1) % _CDSIZE ))
		if test $first -lt 0
		then
			print - $err 1>&2
			return
		fi
		tmp=${_CDSTACK[$first]:-}
		if test "$tmp" = ""
		then
			print - $err 1>&2
			return
		fi
		if test "$tmp" != "$PWD"
		then
			# don't put two of same directories in a row
			cd $tmp
			_CDSTACK[$_NEXTCD]=$tmp
			(( _NEXTCD = (_NEXTCD + 1) % _CDSIZE ))
		fi
		print - $tmp
		;;

	*)
		# go to a new directory
		cd $1
		(( first = (_NEXTCD + _CDSIZE - 1) % _CDSIZE ))
		if test "${_CDSTACK[$first]:-}" != "$PWD"
		then
			# don't put two of same directories in a row
			_CDSTACK[$_NEXTCD]=$PWD
			(( _NEXTCD = (_NEXTCD + 1) % _CDSIZE ))
		fi
		;;
	esac
}
alias cd=_pushd

dirs ()
{
	# prints out _CDSTACK
	typeset err='Usage: dirs [past_length]\n\tprints past directories\n
\tpast_length cannot be less than 1'

	if test $# -gt 1
	then
		print - $err 1>&2
		return
	fi
	integer srch_len=${1:-$_DIRSDEF}
	if test "$srch_len" -lt 1
	then
		print - $err 1>&2
		return
	fi

	integer i=0 j=$_NEXTCD
	typeset tmp
	while test $i -lt $srch_len  -a  $i -lt $_CDSIZE
	do
		(( j = ( j + _CDSIZE - 1) % _CDSIZE ))
		tmp=${_CDSTACK[$j]:-}
		if test "$tmp" = ""
		then
			return
		else
			print - "$i:	$tmp"
		fi

		(( i = i + 1 ))
	done
}

fd ()
{
	typeset err='Usage: fd pattern\n
\tsearches for pattern in the past directories'

	if test $# -ne 1
	then
		print - $err 1>&2
		return
	fi

	integer i=0 j=$_NEXTCD
	typeset tmp
	while test $i -lt $_CDSIZE
	do
		(( j = ( j + _CDSIZE - 1) % _CDSIZE ))
		tmp=${_CDSTACK[$j]:-}
		if test "$tmp" = ""
		then
			return
		elif test "${tmp%$1*}" != "$tmp"
		then
			print - "$i:	$tmp"
		fi

		(( i = i + 1 ))
	done
}

fi #end if cd is not already redefined