Last active
December 18, 2018 19:12
-
-
Save todd-a-jacobs/1081c384cdbdcf6d6f0b6f4df5053063 to your computer and use it in GitHub Desktop.
Change directory with CDPATH support.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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