about summary refs log tree commit diff
path: root/Completion/Builtins/_cd
blob: 05d5e6f8893a84878f02b0a67d0fad60d993278c (plain) (blame)
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
#compdef cd chdir 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.

setopt localoptions nonomatch

local expl ret=1

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(-/))
  # Now remove all the common parts of $PWD and the completions from this
  rep=(${${rep#${PWD%%$words[2]*}}%${PWD#*$words[2]}})
  (( $#rep )) && _wanted -C replacement strings expl replacement compadd -a rep
else
  _popd && ret=0

  if [[ $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"
      _wanted directories expl directory _path_files -/ && ret=0
    else
      local tmpcdpath

      tmpcdpath=(${${(@)cdpath:#.}:#$PWD})
      _alternative \
          'local-directories:local directories:_path_files -/' \
	  "path-directories:directories in cdpath:_path_files -W tmpcdpath -/" && ret=0
    fi
  else
    _wanted directories expl directory _path_files -/ && ret=0
  fi

  return ret
fi