我正在为一个共享文件上传语法卷曲的工具构建一个bash完成脚本.
卷曲,你可以做:
curl -F var = @ file
我的应用程序有类似的语义,我希望能够在按下“@”后显示可能的文件.不幸的是,这证明是困难的:
cur="${COMP_WORDS[COMP_CWORD]}" prev="${COMP_WORDS[COMP_CWORD-1]}" if [[ "$cur" == @* && "$prev" == '=' ]]; then COMPREPLY=( $(compgen -f ${cur:1}) ) return 0 fi
所以如果一个命令(到目前为止)以:
abc=@
var=@/usr/ /usr/bin /usr/games
问题是如果我真的打标签来完成,’@’消失!
var=/usr/bin
所以看起来像bash用标签的COMPREPLY替换整个当前单词.
避免这种情况的唯一方法是这样做:
COMPREPLY=( $(compgen -f ${cur:1}) ) for (( i=0; i<${#COMPREPLY[@]}; i++ )); do COMPREPLY[$i]='@'${COMPREPLY[$i]} done
但现在标签完成看起来很奇怪,至少说:
@/usr/bin @/usr/games
所以,这让我感兴趣,所以我一直在阅读bash完成源(可在/ etc / bash_completion).
我遇到这个变量:${COMP_WORDBREAKS},这似乎允许控制用于分隔字词的字符.
我也遇到这个函数_get_cword和互补的_get_pword,分别推荐使用${COMP_WORDS [COMP_CWORD]}和${COMP_WORDS [COMP_CWORD-1]}.
所以,把所有这一切放在一起,我做了一些测试,这里是我想出来的:这似乎对我来说,至少,希望它也会为你:
# maintain the old value,so that we only affect ourselves with this OLD_COMP_WORDBREAKS=${COMP_WORDBREAKS} COMP_WORDBREAKS="${COMP_WORDBREAKS}@" cur="$(_get_cword)" prev="$(_get_pword)" if [[ "$cur" == '=@' ]]; then COMPREPLY=( $(compgen -f ${cur:2}) ) # restore the old value COMP_WORDBREAKS=${OLD_COMP_WORDBREAKS} return 0 fi if [[ "$prev" == '=@' ]]; then COMPREPLY=( $(compgen -f ${cur}) ) # restore the old value COMP_WORDBREAKS=${OLD_COMP_WORDBREAKS} return 0 fi
现在我承认,如果病例有点脏,那么绝对有更好的办法,但是我需要更多的咖啡因.
此外,无论你是值得的,我还发现了P< prefix> compgen的参数,这将阻止您在调用compgen之后循环使用$COMPREPLY [*]}数组,像这样
COMPREPLY=( $(compgen -P @ -f ${cur:1}) )
但是,面对完整的解决方案,这有点多余.