/
githubmirror
/
bash-completion
Обзор
Документация
Войти
/
githubmirror
/
bash-completion
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
completions-core/make.bash
188 строк
7 KB
Daksh Mamodiya
fix(make): offer phony targets as-is instead of collapsing them
21 июл 2026, 21:23
21 июл 2026, 21:23
b29d4ea
Код
Авторство
О чём код?
# bash completion for GNU make # Extract the valid target names starting with PREFIX from the output of # `make -npq' # @param mode If this is `-d', the directory names already specified in # PREFIX are omitted in the output # @param prefix Prefix of the target names _comp_cmd_make__extract_targets() { local mode=$1 local -x prefix=$2 # display mode, only output current path component to the next slash local -x prefix_replace=$prefix [[ $mode == -d && $prefix == */* ]] && prefix_replace=${prefix##*/} _comp_awk -f "${BASH_SOURCE[0]%/*}/../helpers-core/make-extract-targets.awk" } # Truncate the non-unique filepaths in the "targets" array to only generate # phony targets, unique directories, or files in the COMPREPLY array. This # function discards the files under subdirectories unless the path is unique # under each subdirectory and instead generate the subdirectory path. For # example, when there are two candidates, "abc/def" and "abc/xyz", we generate # "abc/" instead of generating both candidates directly. When there is only # one candidate "abc/def", we generate the full path "abc/def". # # The phony targets (prefixed by "phony:") are offered as-is: a `/' in a phony # name is a naming convention (e.g. CMake's `install', `install/local'), not a # directory boundary, so they are never collapsed. Only the non-phony targets # (prefixed by "file:"), which are real filepaths, go through the path # collapse. # # @var[in] cur # @var[in] mode # @var[in] targets - Array containing the target names. This array is supposed # to contain at least one element for the Bash-4.2 nounset bug. # @var[out] COMPREPLY _comp_cmd_make__truncate_non_unique_paths() { local prefix=$cur [[ $mode == -d ]] && prefix= COMPREPLY=() local nreply=0 # collect the possible completions including the directory names in # `paths' and count the number of children of each subdirectory in # `nchild'. local -A paths nchild local target for target in "${targets[@]}"; do if [[ $target == phony:* ]]; then # The phony targets are directly added to COMPREPLY without # considering the pathname structures with slashes. COMPREPLY[nreply++]=${target#phony:} continue fi local path=${target#file:} path=${path%/} while [[ ! ${paths[$path]+set} ]] && paths[$path]=set && [[ $path == "$prefix"*/* ]]; do path=${path%/*} nchild[$path]=$((${nchild[$path]-0} + 1)) done done for target in "${!paths[@]}"; do # generate only the paths that do not have a unique child and whose # all parent and ancestor directories have a unique child. ((${nchild[$target]-0} == 1)) && continue local path=$target while [[ $path == "$prefix"*/* ]]; do path=${path%/*} ((${nchild[$path]-0} == 1)) || continue 2 done # suffix `/' when the target path is a subdiretory, which has # at least one child. COMPREPLY[nreply++]=$target${nchild[$target]+/} done } _comp_cmd_make() { local cur prev words cword was_split comp_args _comp_initialize -s -- "$@" || return local makef makef_dir=("-C" ".") i local noargopts='!(-*|*[foWICmEDVxj]*)' # shellcheck disable=SC2254 case $prev in --file | --makefile | --old-file | --assume-old | --what-if | --new-file | \ --assume-new | -${noargopts}[foW]) _comp_compgen_filedir return ;; --include-dir | --directory | -${noargopts}[ICm]) _comp_compgen_filedir -d return ;; -${noargopts}E) _comp_compgen -- -v return ;; --eval | -${noargopts}[DVx]) return ;; --jobs | -${noargopts}j) local REPLY _comp_get_ncpus _comp_compgen -- -W "{1..$((REPLY * 2))}" return ;; esac [[ $was_split ]] && return if [[ $cur == -* ]]; then _comp_compgen_help || _comp_compgen_usage [[ ${COMPREPLY-} == *= ]] && compopt -o nospace elif [[ $cur == *=* ]]; then prev=${cur%%=*} cur=${cur#*=} local diropt="" [[ ${prev,,} == *dir?(ectory) ]] && diropt=-d _comp_compgen_filedir ${diropt:+"$diropt"} else # before we check for makefiles, see if a path was specified # with -C/--directory for ((i = 1; i < ${#words[@]}; i++)); do if [[ ${words[i]} == @(-${noargopts}C|--directory) ]]; then # Expand tilde expansion local REPLY _comp_dequote "${words[i + 1]-}" && [[ -d $REPLY ]] && makef_dir=(-C "$REPLY") break fi done # before we scan for targets, see if a Makefile name was # specified with -f/--file/--makefile for ((i = 1; i < ${#words[@]}; i++)); do if [[ ${words[i]} == @(-${noargopts}f|--?(make)file) ]]; then # Expand tilde expansion local REPLY _comp_dequote "${words[i + 1]-}" && [[ -f $REPLY ]] && makef=(-f "$REPLY") break fi done # recognise that possible completions are only going to be displayed so # only the base name is shown. # # Note: This is currently turned off because the test suite of # bash-completion conflicts with it; it uses "set show-all-if-ambiguous # on" (causing COMP_TYPE == 37) to retrieve the action completion # results, and also the compact form with only the basenames is not # essentially needed. To re-enable it, please uncomment the following # if-statement. local mode=-- # if ((COMP_TYPE != 9 && COMP_TYPE != 37 && COMP_TYPE != 42)); then # mode=-d # display-only mode # fi local targets _comp_split targets "$(LC_ALL=C \ $1 -npq __BASH_MAKE_COMPLETION__=1 \ ${makef+"${makef[@]}"} "${makef_dir[@]}" .DEFAULT 2>/dev/null | _comp_cmd_make__extract_targets "$mode" "$cur")" && _comp_cmd_make__truncate_non_unique_paths if [[ $mode != -d ]]; then # Completion will occur if there is only one suggestion # so set options for completion based on the first one [[ ${COMPREPLY-} == */ ]] && compopt -o nospace fi fi } && complete -F _comp_cmd_make make gmake gnumake pmake colormake bmake