1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
#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 pushd - or pushd +, 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.
local pushdminus
[[ -o pushdminus ]] && pushdminus=1
emulate -LR zsh
setopt extendedglob
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]}})
(( ! $#rep )) || compadd $rep
elif [[ $words[1] = pu* && $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
lines="$(dirs -v)"
# turn the lines into an array, removing the current directory
list=(${${(f)lines}##0*})
if [[ ( $IPREFIX = - && -z $pushdminus ) ||
( $IPREFIX = + && -n $pushdminus ) ]]; then
# reverse the numbering: it counts the last one as -0, which
# is a little strange.
integer tot i
for (( i = 1, tot = $#list-1; tot >= 0; i++, tot-- )); do
list[$i]="$tot${list[$i]##[0-9]#}"
done
fi
# make sure -y treats this as a single string
lines="${(F)list}"
# get the array of numbers only
list=(${list%%[ ]*})
compgen -y '$lines' -Q -k 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
_path_files -W "(. $cdpath)" -/
else
_path_files -/
fi
|