Skip to content

Commit ed0ae10

Browse files
committed
refactor(cd): factorize generator for CDPATH
To apply the adjustment of suffixing "/" only to the completions generated based on CDPATH, we isolate the CDPATH completion code in a separate generator. This is needed because we want to generate cdable_vars completions into COMPREPLY, but we do not want to apply sufixing to the cdable_vars completions.
1 parent b6503ba commit ed0ae10

File tree

1 file changed

+41
-37
lines changed
  • completions

1 file changed

+41
-37
lines changed

completions/cd

Lines changed: 41 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,60 @@
11
# cd(1) completion -*- shell-script -*-
22

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()
66
{
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
158

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 /,
2110
# ./ 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
2616

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=()
3018

3119
# we have a CDPATH, so loop on its contents
32-
local paths dirs
20+
local paths dirs _d
3321
_comp_split -F : paths "$CDPATH"
34-
for i in "${paths[@]}"; do
22+
for _p in "${paths[@]}"; do
3523
# 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+="/"
4128
fi
42-
COMPREPLY[k++]=${j#"$i/"}
29+
_cdpaths+=("${_d#"$_p/"}")
4330
done
4431
done
32+
_comp_unlocal paths dirs
4533

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/
5238
fi
5339
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
5458
}
5559
if shopt -q cdable_vars; then
5660
complete -v -F _comp_cmd_cd -o nospace cd pushd

0 commit comments

Comments
 (0)