|
1 | 1 | # cd(1) completion -*- shell-script -*-
|
2 | 2 |
|
3 |
| -# This meta-cd function observes the CDPATH variable, so that `cd` |
4 |
| -# additionally completes on directories under those specified in CDPATH. |
5 |
| -_comp_cmd_cd() |
| 3 | +# This generator function observes the CDPATH variable, to additionally |
| 4 | +# complete directories under those specified in CDPATH. |
| 5 | +_comp_cmd_cd__compgen_cdpath() |
6 | 6 | {
|
7 |
| - local cur prev words cword comp_args |
8 |
| - _comp_initialize -- "$@" || return |
9 |
| - |
10 |
| - if [[ $cur == -* ]]; then |
11 |
| - _comp_compgen_help -c help "$1" |
12 |
| - compopt +o nospace |
13 |
| - return |
14 |
| - fi |
| 7 | + local _p |
15 | 8 |
|
16 |
| - local i j k |
17 |
| - |
18 |
| - compopt -o filenames |
19 |
| - |
20 |
| - # Use standard dir completion if no CDPATH or parameter starts with /, |
| 9 | + # Generate CDPATH completions when the parameter does not start with /, |
21 | 10 | # ./ or ../
|
22 |
| - if [[ ! ${CDPATH-} || $cur == ?(.)?(.)/* ]]; then |
23 |
| - _comp_compgen_filedir -d |
24 |
| - return |
25 |
| - fi |
| 11 | + [[ ! ${CDPATH-} || $cur == ?(.)?(.)/* ]] && return 1 |
| 12 | + |
| 13 | + local _mark_dirs="" _mark_symdirs="" |
| 14 | + _comp_readline_variable_on mark-directories && _mark_dirs=set |
| 15 | + _comp_readline_variable_on mark-symlinked-directories && _mark_symdirs=set |
26 | 16 |
|
27 |
| - local mark_dirs="" mark_symdirs="" |
28 |
| - _comp_readline_variable_on mark-directories && mark_dirs=set |
29 |
| - _comp_readline_variable_on mark-symlinked-directories && mark_symdirs=set |
| 17 | + local -a _cdpaths=() |
30 | 18 |
|
31 | 19 | # we have a CDPATH, so loop on its contents
|
32 |
| - local paths dirs |
| 20 | + local paths dirs _d |
33 | 21 | _comp_split -F : paths "$CDPATH"
|
34 |
| - for i in "${paths[@]}"; do |
| 22 | + for _p in "${paths[@]}"; do |
35 | 23 | # create an array of matched subdirs
|
36 |
| - k=${#COMPREPLY[@]} |
37 |
| - _comp_compgen -v dirs -c "$i/$cur" -- -d |
38 |
| - for j in "${dirs[@]}"; do |
39 |
| - if [[ ($mark_symdirs && -L $j || $mark_dirs && ! -L $j) && ! -d ${j#"$i/"} ]]; then |
40 |
| - j+="/" |
| 24 | + _comp_compgen -v dirs -c "$_p/$cur" -- -d |
| 25 | + for _d in "${dirs[@]}"; do |
| 26 | + if [[ ($_mark_symdirs && -L $_d || $_mark_dirs && ! -L $_d) && ! -d ${_d#"$_p/"} ]]; then |
| 27 | + _d+="/" |
41 | 28 | fi
|
42 |
| - COMPREPLY[k++]=${j#"$i/"} |
| 29 | + _cdpaths+=("${_d#"$_p/"}") |
43 | 30 | done
|
44 | 31 | done
|
| 32 | + _comp_unlocal paths dirs |
45 | 33 |
|
46 |
| - _comp_compgen -a filedir -d |
47 |
| - |
48 |
| - if ((${#COMPREPLY[@]} == 1)); then |
49 |
| - i=${COMPREPLY[0]} |
50 |
| - if [[ $i == "$cur" && $i != */ ]]; then |
51 |
| - COMPREPLY[0]="${i}/" |
| 34 | + if ((${#_cdpaths[@]} == 1)); then |
| 35 | + _p=${_cdpaths[0]} |
| 36 | + if [[ $_p == "$cur" && $_p != */ ]]; then |
| 37 | + _cdpaths[0]=$_p/ |
52 | 38 | fi
|
53 | 39 | fi
|
| 40 | + |
| 41 | + _comp_compgen_set "${_cdpaths[@]}" |
| 42 | +} |
| 43 | + |
| 44 | +_comp_cmd_cd() |
| 45 | +{ |
| 46 | + local cur prev words cword comp_args |
| 47 | + _comp_initialize -- "$@" || return |
| 48 | + |
| 49 | + if [[ $cur == -* ]]; then |
| 50 | + _comp_compgen_help -c help "$1" |
| 51 | + compopt +o nospace |
| 52 | + return |
| 53 | + fi |
| 54 | + |
| 55 | + compopt -o filenames |
| 56 | + _comp_cmd_cd__compgen_cdpath |
| 57 | + _comp_compgen -a filedir -d |
54 | 58 | }
|
55 | 59 | if shopt -q cdable_vars; then
|
56 | 60 | complete -v -F _comp_cmd_cd -o nospace cd pushd
|
|
0 commit comments