Skip to content

Instantly share code, notes, and snippets.

@todd-a-jacobs
Last active December 18, 2018 19:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save todd-a-jacobs/1081c384cdbdcf6d6f0b6f4df5053063 to your computer and use it in GitHub Desktop.
Save todd-a-jacobs/1081c384cdbdcf6d6f0b6f4df5053063 to your computer and use it in GitHub Desktop.
Change directory with CDPATH support.
# Change directory with CDPATH support. Culled from the bash-completion package.
_compopt_o_filenames ()
{
type compopt &> /dev/null && compopt -o filenames 2> /dev/null || compgen -f /non-existing-dir/ > /dev/null
}
_filedir ()
{
local i IFS='
' xspec;
_tilde "$cur" || return 0;
local -a toks;
local quoted tmp;
_quote_readline_by_ref "$cur" quoted;
toks=(${toks[@]-} $(
compgen -d -- "$cur" | {
while read -r tmp; do
# TODO: I have removed a "[ -n $tmp ] &&" before 'printf ..',
# and everything works again. If this bug suddenly
# appears again (i.e. "cd /b<TAB>" becomes "cd /"),
# remember to check for other similar conditionals (here
# and _filedir_xspec()). --David
printf '%s\n' $tmp
done
}
));
if [[ "$1" != -d ]]; then
[[ ${BASH_VERSINFO[0]} -ge 4 ]] && xspec=${1:+"!*.@($1|${1^^})"} || xspec=${1:+"!*.@($1|$(printf %s $1 | tr '[:lower:]' '[:upper:]'))"};
toks=(${toks[@]-} $( compgen -f -X "$xspec" -- $quoted));
fi;
[ ${#toks[@]} -ne 0 ] && _compopt_o_filenames;
COMPREPLY=("${COMPREPLY[@]}" "${toks[@]}")
}
_cd ()
{
local cur IFS='
' i j k;
_get_comp_words_by_ref cur;
if [[ "$cur" == ?(\\)\$* ]]; then
COMPREPLY=($( compgen -v -P '$' -- "${cur#?(\\)$}" ));
return 0;
fi;
_compopt_o_filenames;
if [[ -z "${CDPATH:-}" || "$cur" == ?(.)?(.)/* ]]; then
_filedir -d;
return 0;
fi;
local -r mark_dirs=$(_rl_enabled mark-directories && echo y);
local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y);
for i in ${CDPATH//:/'
'};
do
k="${#COMPREPLY[@]}";
for j in $( compgen -d $i/$cur );
do
if [[ ( -n $mark_symdirs && -h $j || -n $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then
j="${j}/";
fi;
COMPREPLY[k++]=${j#$i/};
done;
done;
_filedir -d;
if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
i=${COMPREPLY[0]};
if [[ "$i" == "$cur" && $i != "*/" ]]; then
COMPREPLY[0]="${i}/";
fi;
fi;
return 0
}
_quote_readline_by_ref ()
{
if [[ ${1:0:1} == "'" ]]; then
if [[ ${BASH_VERSINFO[0]} -ge 4 ]]; then
printf -v $2 %s "${1:1}";
else
printf -v $2 %q "${1:1}";
printf -v $2 %q ${!2};
fi;
else
if [[ ${BASH_VERSINFO[0]} -le 3 && ${1:0:1} == '"' ]]; then
printf -v $2 %q "${1:1}";
else
printf -v $2 %q "$1";
fi;
fi;
[[ ${!2:0:1} == '$' ]] && eval $2=${!2}
}
_rl_enabled ()
{
[[ "$( bind -v )" = *$1+([[:space:]])on* ]]
}
_tilde ()
{
local result=0;
if [[ ${1:0:1} == "~" && $1 == ${1//\/} ]]; then
_compopt_o_filenames;
COMPREPLY=($( compgen -P '~' -u "${1#\~}" ));
result=${#COMPREPLY[@]};
fi;
return $result
}
complete -o nospace -F _cd cd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment