这不是完美的,但是再次完成bash还是一件棘手的事...
最简单的方法是在每个命令的基础上,它比FIGNORE
可以执行的灵活得多:
complete -f -X "/myproject/data/*" vi
这指示自动完成功能的完成vi
是针对文件的,并删除与-X
过滤器匹配的模式。不利之处在于该模式未标准化,因此../data
变体将不匹配。
接下来最好的事情可能是自定义PROMPT_COMMAND
函数:
# associative arrays of non-autocomplete directories
declare -A noacdirs=([/myproject/data]=1 )
function _myprompt {
[[ -n "${noacdirs[$PWD]}" ]] && {
echo autocomplete off
bind 'set disable-completion on'
} || {
echo autocomplete on
bind 'set disable-completion off'
}
}
PROMPT_COMMAND=_myprompt
当您在目录中时,这将完全禁用(但无法完成),但对每个路径(而不只是该目录中的文件)都将禁用它。
通常,对于定义的路径有选择地禁用它会更有用,但是我相信唯一的方法是使用默认的完成功能(bash-4.1和更高版本的complete -D
)以及很多麻烦。
这应该为您工作,但是它可能会有意想不到的副作用(例如,在某些情况下会更改预期的完成时间):
declare -A noacdirs=([/myproject/data]=1 )
_xcomplete() {
local cur=${COMP_WORDS[COMP_CWORD]} # the current token
name=$(readlink -f "${cur:-./}") # poor man's path canonify
dirname=$(dirname "$name/.")
[[ -n "${noacdirs[$dirname]}" ]] && {
COMPREPLY=( "" ) # dummy to prevent completion
return
}
# let default kick in
COMPREPLY=()
}
complete -o bashdefault -o default -F _xcomplete vi
这可以完成vi
,可以根据需要添加其他命令。无论路径或工作目录如何,它都应停止命名目录中文件的完成。
我相信一般的方法complete -D
是为遇到的每个命令动态添加完成功能。一个可能还需要添加complete -E
(输入缓冲区为空时命令名称的完成)。
更新
这是PROMPT_COMMAND
和完成功能解决方案的混合版本,我认为它更容易理解和破解:
declare -A noacdirs=([/myproject/data]=1 [/project2/bigdata]=1)
_xcomplete() {
local cmd=${COMP_WORDS[0]}
local cur=${COMP_WORDS[COMP_CWORD]} # the current token
[[ -z "$cur" && -n "$nocomplete" ]] && {
printf "\n(restricted completion for $cmd in $nocomplete)\n"
printf "$PS2 $COMP_LINE"
COMPREPLY=( "" ) # dummy to prevent completion
return
}
COMPREPLY=() # let default kick in
}
function _myprompt {
nocomplete=
# uncomment next line for hard-coded list of directories
[[ -n "${noacdirs[$PWD]}" ]] && nocomplete=$PWD
# uncomment next line for per-directory ".noautocomplete"
# [[ -f ./.noautocomplete ]] && nocomplete=$PWD
# uncomment next line for size-based guessing of large directories
# [[ $(stat -c %s .) -gt 512*1024 ]] && nocomplete=$PWD
}
PROMPT_COMMAND=_myprompt
complete -o bashdefault -o default -F _xcomplete vi cp scp diff
nocomplete
当您输入已配置的目录之一时,此提示功能将设置变量。仅当该变量为非空白时,并且仅当您尝试从空字符串完成时,才会启动修改后的完成行为,从而允许部分名称的完成(删除-z "$cur"
条件以完全防止完成)。注释掉这两printf
行以进行静默操作。
其他选项包括每个目录的.noautocomplete
标志文件,您可以touch
根据需要在目录中;和使用GNU猜测目录大小stat
。您可以使用这三个选项中的任何一个或全部。
(该stat
方法只是一种猜测,报告的目录大小会随其内容的增长而增加,这是一个“高水位线”,通常在没有进行任何管理干预的情况下删除文件时,它就不会缩小。它比确定潜在的大目录的实际内容便宜目录。精确的行为和每个文件的增量取决于基础文件系统。我发现它至少在linux ext2 / 3/4系统上是一个可靠的指示器。)
即使返回空的补全,bash也会添加额外的空间(仅在行尾补全时才会发生)。您可以添加-o nospace
到complete
命令中以防止这种情况。
剩下的一个小问题是,如果您将光标备份到令牌的开头并单击选项卡,则默认补全将再次出现。认为它是一个功能;-)
(或者,${COMP_LINE:$COMP_POINT-1:1}
如果您喜欢过度设计,也可以大惊小怪,但是我发现bash本身在备份并尝试在命令中间完成操作时无法可靠地设置完成变量。)