防止bash完成两次打印答复

时间:2018-07-13 12:21:00

标签: bash bash-completion

我在使bash完成脚本的行为符合预期方面遇到困难。

下面是我正在尝试做的最简化的版本,以及该问题的屏幕截图。

一切正常,除了一种情况:

当仅在完成项中有一个匹配项时,当我按两次T​​ab键时,它将打印两次相同的命令,这不是预期的效果。

在我的完成情况下,我只对完成第一个参数(即“子命令”)感兴趣。我认为下面的if [ "$#" -gt "2" ]行本可以防止这种情况的发生,但事实并非如此-因为COMP_LINE在第一个选项卡之后仍未更新。

#!/usr/bin/env bash

send_completions() {
  if [[ -z "$COMP_LINE" ]]; then
    return
  fi

  set $COMP_LINE

  if [ "$#" -gt "2" ]; then
    return
  fi

  compgen -W "one two test" "$2"
}

send_completions

通过运行以下命令启用完成:

$ complete -C './complete.sh' asd

然后键入asd o<tab><tab>来查看问题。

screencast

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

此刻检查COMP_LINE的值:

$ asd one <TAB>

您会注意到该值为:

declare -x COMP_LINE="asd one "

发出set后,这将导致两个位置参数,并且不会触发条件。尝试输入其他字符:$ asd one o<TAB>,您会看到您的条件将被正确触发并且什么也不会完成。


我见过的大多数完成都是使用函数完成的。实际上,现在检查系统上定义的所有完成(大多数都是默认设置),其中的是使用脚本完成的。

使用函数有一些好处,例如,尊重引用的COMP_WORDS数组。您的脚本可以大致这样重写:

_asd_comp() {
    (( COMP_CWORD > 1 )) && return
    local cur=${COMP_WORDS[COMP_CWORD]} IFS=$' \t\n'
    COMPREPLY=( $(compgen -W "one two three" -- "$cur") )    
}

complete -o bashdefault -o default -F _asd_comp asd

我添加了-o选项,以便在第一个参数之后执行默认补全。您可以在manual中了解更多相关信息。


我唯一想到的就是如何更改脚本,我想您可能会添加一些不干净的条件,例如:

(( $# > 1 )) && [[ ${COMP_LINE: -1} = " " ]] && return