Skip to content

Instantly share code, notes, and snippets.

@wd5gnr
Last active May 3, 2024 11:21
Show Gist options
  • Save wd5gnr/390de82ad8656d01218e107cd7e4bb2d to your computer and use it in GitHub Desktop.
Save wd5gnr/390de82ad8656d01218e107cd7e4bb2d to your computer and use it in GitHub Desktop.
cdfunc.sh
# This function defines a 'cd' replacement function capable of keeping,
# displaying and accessing history of visited directories, up to 10 entries.
# To use it, uncomment it, source this file and try 'cd --'.
# acd_func 1.0.5, 10-nov-2004
# Petar Marinov, http:/geocities.com/h2428, this is public domain
xcd_func ()
{
local x2 the_new_dir adir index
local -i cnt
if [[ $1 == "--" ]]; then
dirs -v
return 0
fi
the_new_dir=$1
[[ -z $1 ]] && the_new_dir=$HOME
if [[ ${the_new_dir:0:1} == '-' ]]; then
#
# Extract dir N from dirs
index=${the_new_dir:1}
[[ -z $index ]] && index=1
adir=$(dirs +$index)
[[ -z $adir ]] && return 1
the_new_dir=$adir
fi
#
# '~' has to be substituted by ${HOME}
[[ ${the_new_dir:0:1} == '~' ]] && the_new_dir="${HOME}${the_new_dir:1}"
#
# Now change to the new dir and add to the top of the stack
pushd "${the_new_dir}" > /dev/null
[[ $? -ne 0 ]] && return 1
the_new_dir=$(pwd)
#
# Trim down everything beyond 11th entry
popd -n +11 2>/dev/null 1>/dev/null
#
# Remove any other occurence of this dir, skipping the top of the stack
for ((cnt=1; cnt <= 10; cnt++)); do
x2=$(dirs +${cnt} 2>/dev/null)
[[ $? -ne 0 ]] && return 0
[[ ${x2:0:1} == '~' ]] && x2="${HOME}${x2:1}"
if [[ "${x2}" == "${the_new_dir}" ]]; then
popd -n +$cnt 2>/dev/null 1>/dev/null
cnt=cnt-1
fi
done
return 0
}
# wrapper for .env.sh functionality -- Al Williams
# Note: it would be nice check for a successful cd so you don't
# leave and then enter but with CDPATH and shopt cdable_vars/cdspell, it is tricky to know cd
# will work before it does
# also shopt autocd is not compatible with this
# Note, you could catch any other way to get to the directory (e.g. popd, etc)
# by running this as part of the project and testing for PWD!=LASTPWD
# if so, run any exit you find in OLDPWD or ../OLDPWD and then run any
# entry you find in $PWD and set LASTPWD to PWD
# see cd_prompt below (lightly tested)
cd_func()
{
# this is relatively wasteful to see if it is going to work
( builtin cd "$@" >/dev/null 2>&1 )
badcd=$?
dir="$1"
# see if we are really changing
if [ -z "$1" ] ; then # special case: no argument
dir=~
fi
if [[ "$1" == "-" ]] ; then # special case: cd -
dir="$OLDPWD"
fi
if [[ "$1" == "--" ]]; then # special case: cd -- (list dirs)
xcd_func --
return $?
fi
if [ $badcd == 0 ] # if we have a real place to go, find its inode
then
pwdid=`ls -id .| cut -d ' ' -f 1`
newid=`ls -id "$dir" 2>/dev/null |cut -d ' ' -f 1`
fi
# if no place to go or we are going to the same place, just execute it and be done
if [[ $badcd == 1 || $pwdid == $newid ]]; then xcd_func "$@" ; return $? ; fi
# if .env.sh in current directory or .., call it
if [ -f .env.sh ]
then source .env.sh leave dir "$PWD"
elif [ -f ../.env.sh ]
then source ../.env.sh leave child "$PWD"
fi
# switch
xcd_func "$@"
rv=$?
# if .env.sh in new directory or .., call it
if [ -f .env.sh ]
then source .env.sh enter dir "$PWD"
elif [ -f ../.env.sh ]
then source ../.env.sh enter child "$PWD"
fi
return $rv
}
# Set this to run using PROMPT_COMMAND
# it assumes $PWD will be set correctly.
# This handles things like changing directories using non-cd sources.
#
# Note: You do NOT need to use both functions
# if you alias cd=cd_func, you are done
# if you set PROMPT_COMMAND to cd_prompt, you are also done
# If you do both you will get scripts running twice
cd_prompt()
{
if [ -z "$LASTPWD" -o "$PWD" != "$LASTPWD" ]
then
if [ -f "$OLDPWD/.env.sh" ]
then source "$OLDPWD/.env.sh" leave dir "$OLDPWD"
elif [ -f "$OLDPWD/../.env.sh" ]
then source "$OLDPWD/../.env.sh" leave child "$PWD"
fi
if [ -f .env.sh ]
then source .env.sh enter dir "$PWD"
elif [ -f ../.env.sh ]
then source ../.env.sh enter child "$PWD"
fi
LASTPWD="$PWD"
fi
}
# setup
alias cd=cd_func
#or
# PROMPT_COMMAND=cd_prompt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment