Skip to content

Commit dabec2e

Browse files
committed
fix(make): show unique targets in subdirs
1 parent 58ad8de commit dabec2e

1 file changed

Lines changed: 48 additions & 1 deletion

File tree

completions/make

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ _make_target_extract_script()
4646
/^$/ { # end of target block
4747
x; # unhold target
4848
/^$/d; # dont print blanks
49-
s|^${dirname_re-}\(.\{${#basename}\}[^:/]*/\{0,1\}\)[^:]*:.*$|${output}|p;
49+
s|^${dirname_re-}\(.\{${#basename}\}[^:]*\):.*$|${output}|p;
5050
d; # hide any bugs
5151
}
5252
@@ -172,6 +172,53 @@ _make()
172172
${makef+"${makef[@]}"} "${makef_dir[@]}" .DEFAULT 2>/dev/null |
173173
command sed -ne "$script"))
174174

175+
# discard the files under subdirectories unless the path is unique
176+
# under each subdirectory and instead generate the subdirectory path.
177+
# For example, when there are two candidates, "abc/def" and "abc/xyz",
178+
# we generate "abc/" instead of generating both candidates directly.
179+
# When there is only one candidate "abc/def", we generate the full path
180+
# "abc/def".
181+
local prefix=$cur
182+
[[ $mode == -d ]] && prefix=
183+
if ((${#COMPREPLY[@]} > 0)); then
184+
# collect the possible completions including the directory names in
185+
# `paths' and count the number of children of each subdirectory in
186+
# `nchild'.
187+
local -A paths nchild
188+
local target
189+
for target in "${COMPREPLY[@]}"; do
190+
local path=${target%/}
191+
while [[ ! ${paths[$path]+set} ]] &&
192+
paths[$path]=1 &&
193+
[[ $path == "$prefix"*/* ]]; do
194+
path=${path%/*}
195+
if [[ ! ${nchild[$path]+set} ]]; then
196+
((nchild[\$path] = 1))
197+
else
198+
((nchild[\$path]++))
199+
fi
200+
done
201+
done
202+
203+
COMPREPLY=()
204+
local nreply=0
205+
for target in "${!paths[@]}"; do
206+
# generate only the paths that do not have a unique child and
207+
# whose all parent and ancestor directories have a unique
208+
# child.
209+
((${nchild[$target]-0} == 1)) && continue
210+
local path=$target
211+
while [[ $path == "$prefix"*/* ]]; do
212+
path=${path%/*}
213+
((${nchild[$path]-0} == 1)) || continue 2
214+
done
215+
216+
# suffix `/' when the target path is a subdiretory, which has
217+
# at least one child.
218+
COMPREPLY[nreply++]=$target${nchild[$target]+/}
219+
done
220+
fi
221+
175222
if [[ $mode != -d ]]; then
176223
# Completion will occur if there is only one suggestion
177224
# so set options for completion based on the first one

0 commit comments

Comments
 (0)