mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-02 22:11:54 +02:00
79 lines
2.9 KiB
Text
79 lines
2.9 KiB
Text
#compdef cd pushd
|
|
|
|
# Handling of cd.
|
|
# - Normally just completes directories. Uses cdpath if that's set
|
|
# and the string doesn't begin with ~, /, ./ or ../.
|
|
# - In the second argument to cd for the form `cd old new', completes
|
|
# possible `new' strings by examining `old' and $PWD.
|
|
# - After - or +, completes numbers, but the listing
|
|
# gives you the list of directories to complete. This turns on
|
|
# menu-completion and lists the possibilities automatically, otherwise
|
|
# it's not a lot of use. If you don't type the + or - it will
|
|
# complete directories as normal.
|
|
|
|
emulate -L zsh
|
|
setopt extendedglob nonomatch
|
|
|
|
local expl
|
|
|
|
if [[ CURRENT -eq 3 ]]; then
|
|
# cd old new: look for old in $PWD and see what can replace it
|
|
local rep
|
|
# Get possible completions using word in position 2
|
|
rep=(${~PWD/$words[2]/*}~$PWD(-/N))
|
|
# Now remove all the common parts of $PWD and the completions from this
|
|
rep=(${${rep#${PWD%%$words[2]*}}%${PWD#*$words[2]}})
|
|
_description expl replacement
|
|
(( ! $#rep )) || compadd "$expl[@]" $rep
|
|
elif [[ $PREFIX = [-+]* ]]; then
|
|
# pushd: just complete the numbers, but show the full directory list with
|
|
# numbers.
|
|
# For - we do the same thing, but reverse the numbering (other
|
|
# way round if pushdminus is set).
|
|
# The test is for pu* because I have an alias pu since I'm too
|
|
# lazy to type pushd.
|
|
IPREFIX=$PREFIX[1]
|
|
PREFIX=$PREFIX[2,-1]
|
|
local list lines ret=1
|
|
|
|
# get the list of directories with their canonical number
|
|
# and turn the lines into an array, removing the current directory
|
|
lines=( ${${(f)"$(dirs -v)"}##0*} )
|
|
if [[ ( $IPREFIX = - && ! -o pushdminus ) ||
|
|
( $IPREFIX = + && -o pushdminus ) ]]; then
|
|
# reverse the numbering: it counts the last one as -0, which
|
|
# is a little strange.
|
|
integer tot i
|
|
for (( i = 1, tot = $#lines-1; i <= $#lines; i++, tot-- )); do
|
|
lines[$i]="$tot -- ${lines[$i]##[0-9]#[ ]#}"
|
|
done
|
|
else
|
|
for (( i = 1, tot = 1; i <= $#lines; i++, tot++ )); do
|
|
lines[$i]="$tot -- ${lines[$i]##[0-9]#[ ]#}"
|
|
done
|
|
fi
|
|
# get the array of numbers only
|
|
list=(${lines%% *})
|
|
_description expl 'directory stack index'
|
|
compadd "$expl[@]" -ld lines -Q - "$list[@]" && ret=0
|
|
[[ -z $compstate[list] ]] && compstate[list]=list && ret=0
|
|
[[ -n $compstate[insert] ]] && compstate[insert]=menu && ret=0
|
|
|
|
return ret
|
|
elif [[ $PREFIX != (\~|/|./|../)* && $#cdpath -ne 0 ]]; then
|
|
local tdir tdir2
|
|
# With cdablevars, we can convert foo/bar/... to ~foo/bar/... if
|
|
# there is no directory foo. In that case we could also complete
|
|
# variable names, but it hardly seems worth it.
|
|
# Note we need a tilde because cdablevars also allows user home
|
|
# directories, hence we also need nonomatch to suppress error messages.
|
|
if [[ -o cdablevars && -n "$PREFIX" && ! -d ${tdir::=${PREFIX%%/*}} &&
|
|
-d ${~tdir2::="~$tdir"} ]]; then
|
|
PREFIX="~$PREFIX"
|
|
_path_files -/
|
|
else
|
|
_path_files -W "(. $cdpath)" -/
|
|
fi
|
|
else
|
|
_path_files -/
|
|
fi
|