关键是在返回应该表现得像目录完成的单词的完成之前添加这一行:[[ $COMPREPLY == */ ]] && compopt -o nospace
通过在 compgen 之后运行它,COMPREPLY 数组中的唯一建议与正在完成的当前单词匹配。如果有多个建议,则只会部分完成,不会添加空格(标准行为)。如果只有一个建议,则用于决定是否添加空格。
现在,如果您修剪 zibble/ 下的所有文件名,当它发现 zibble/ 是正在完成的单词的唯一匹配时,bash 将不会添加空格分隔符。
这是一个针对 debian http://anonscm.debian.org/gitweb/?p=bash-completion/bash-completion.git的 bash 完成的补丁- 所以补丁上下文中有一些奇怪的东西。
它使用“git”版本控制程序的 git apply 命令完全适用于该版本:http ://anonscm.debian.org/gitweb/?p=bash-completion/bash-completion.git;a=commit;h =2897e62fe7e535eb048f7e08f03ac3fbc3a84fa5
diff --git a/completions/make b/completions/make
index aa19b24..345deea 100644
--- a/completions/make
+++ b/completions/make
@@ -1,11 +1,66 @@
# bash completion for GNU make -*- shell-script -*-
+function _make_target_extract_script()
+{
+ local prefix=$(printf "%s\n" "$1" | sed 's/[][\.*^$(){}?+|/]/\\&/g')
+
+ cat <<EOF
+ /^# Make data base/,/^# Files/d # skip until files section
+ /^# Not a target/,/^$/ d # skip not target blocks
+ /^${prefix}/,/^$/! d # skip anything user dont want
+
+ # The stuff above here describes lines that are not
+ # explicit targets or not targets other than special ones
+ # The stuff below here decides whether an explicit target
+ # should be output.
+
+ /^# File is an intermediate prerequisite/ {
+ s/^.*$//;x # unhold target
+ d # delete line
+ }
+
+ /^$/ { # end of target block
+ x # unhold target
+ s/^(${prefix}[^:/]*\/).*:.*$/\1/p # write targets for subdirs
+ s/:.*$/ /p # write complete targets
+ d # hide any bugs
+ }
+
+ /^[^#\t:%]+:/ { # found target block
+
+ /^\.PHONY/ d # special target
+ /^\.SUFFIXES/ d # special target
+ /^\.DEFAULT/ d # special target
+ /^\.PRECIOUS/ d # special target
+ /^\.INTERMEDIATE/ d # special target
+ /^\.SECONDARY/ d # special target
+ /^\.SECONDEXPANSION/ d # special target
+ /^\.DELETE_ON_ERROR/ d # special target
+ /^\.IGNORE/ d # special target
+ /^\.LOW_RESOLUTION_TIME/ d # special target
+ /^\.SILENT/ d # special target
+ /^\.EXPORT_ALL_VARIABLES/ d # special target
+ /^\.NOTPARALLEL/ d # special target
+ /^\.ONESHELL/ d # special target
+ /^\.POSIX/ d # special target
+ /^\.NOEXPORT/ d # special target
+ /^\.MAKE/ d # special target
+
+ /^[^a-zA-Z0-9]/ d # convention for hidden tgt
+
+ h # hold target
+ d # delete line
+ }
+
+EOF
+}
+
_make()
{
local cur prev words cword split
_init_completion -s || return
- local file makef makef_dir="." makef_inc i
+ local file makef makef_dir=( "-C" "." ) makef_inc i
case $prev in
-f|--file|--makefile|-o|--old-file|--assume-old|-W|--what-if|\
@@ -49,7 +104,7 @@ _make()
for (( i=0; i < ${#words[@]}; i++ )); do
if [[ ${words[i]} == -@(C|-directory) ]]; then
# eval for tilde expansion
- eval makef_dir=${words[i+1]}
+ eval makef_dir=( -C "${words[i+1]}" )
break
fi
done
@@ -59,18 +114,17 @@ _make()
for (( i=0; i < ${#words[@]}; i++ )); do
if [[ ${words[i]} == -@(f|-?(make)file) ]]; then
# eval for tilde expansion
- eval makef=${words[i+1]}
+ eval makef=( -f "${words[i+1]}" )
break
fi
done
- [[ -n $makef ]] && makef="-f ${makef}"
- [[ -n $makef_dir ]] && makef_dir="-C ${makef_dir}"
+ COMPREPLY=( $( compgen -W "$(
+ make -npq "${makef[@]}" "${makef_dir[@]}" .DEFAULT 2>/dev/null | \
+ sed -n -r -f <(_make_target_extract_script "$cur")
+ )" -- "$cur" ) )
- COMPREPLY=( $( compgen -W "$( make -qp $makef $makef_dir 2>/dev/null | \
- awk -F':' '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$)/ \
- {split($1,A,/ /);for(i in A)print A[i]}' )" \
- -- "$cur" ) )
+ [[ $COMPREPLY == */ ]] && compopt -o nospace
fi
} &&