在某些 Bash 自动完成选项的末尾添加空格,而不是在其他选项的末尾?

Posted

技术标签:

【中文标题】在某些 Bash 自动完成选项的末尾添加空格,而不是在其他选项的末尾?【英文标题】:Add spaces to the end of some Bash autocomplete options, but not to others? 【发布时间】:2011-01-21 07:22:42 【问题描述】:

我正在尝试为 Java 程序创建一个 Bash 完成脚本。该程序的典型调用可能如下所示:

$ javaProgram -Dproperty=foo option1 option2

我的脚本的一部分将建议该程序可用的各种 Java 属性(即,当用户键入 -D 时,脚本会建议,例如,property=,然后允许用户键入值)。

我希望完成后不要在等号后插入空格。但是,当用户键入程序的各种选项时(上例中的option1option2),我希望脚本完成,并在完成时插入一个空格。

我是 Bash 补全脚本的新手,但我知道 complete shell 内置函数的 nospace 选项。不过,它似乎不适用于 compgen 内置函数,这似乎是我想要的。我已经尝试过使用nospace,然后在适当的选项结束时明确地包括空格,但它们似乎没有通过它。

有谁知道如何在某些选项的末尾获取空格,但在其他选项的末尾没有空格?

【问题讨论】:

最小回答here 【参考方案1】:

您实际上可以使用compopt 更改complete 选项。这对我有用:

_javaProgram()
  # The completion will not add a space by default. We will alter
  # this behavior by calling `compopt +o nospace` to neutralize this.

  # In completion, '$2' is the current word, and '$3' is the previous
  case "$3" in
    -D) 
        # No space by default.
        COMPREPLY=( $(compgen -W "property=" -- "$2") )
    ;;
    *)  
        # The `case` default:
        COMPREPLY=( $(compgen -W "your default word list" -- "$2") )
        
        # append a space by calling:
        compopt +o nospace
    ;;
  esac


complete -F _javaProgram -o nospace javaProgram

但是,我只需要简短选项后的空间。要对比多头和空头选项,您可以检查COMPREPLY 建议中是否有=

_javaProgram()
  # The completion will not add a space by default. We will alter
  # this behavior by calling `compopt +o nospace` to neutralize this.

  # In completion, '$2' is the current word, and '$3' is the previous
  case "$3" in
    -D) 
        # Do not worry about appending spaces here ... .
        COMPREPLY=( $(compgen -W "property=" -- "$2") )
    ;;
    *)  
        # Do not worry about appending spaces here ... .
        COMPREPLY=( $(compgen -W "your default word list" -- "$2") )
    ;;
  esac

if [[ ! "$COMPREPLY[@]" =~ "=" ]]; then
  # Add space if there is not a '=' in suggestions
  compopt +o nospace
fi


complete -F _javaProgram -o nospace javaProgram

【讨论】:

【参考方案2】:

正如发帖者所说,不能将-o nospace 选项传递给compgen。一种可能性是定义两个函数,其中一个在调用compgen 之前插入对compopt -o nospace 的调用(另一个函数不会)。

例子:

__my_complete_no_space() 
    local IFS=$' \t\n' cur_="$3-$cur"
    [[ $cur_ == *:* ]] && cur_="$cur#*:"
    compopt -o nospace
    COMPREPLY=( $(compgen -P "$2-" -W "$1" -S "$4-" -- "$cur_") )

当添加(或不添加)空间取决于需要完成的内容时,这很有用。

【讨论】:

可以使用compopt 将选项传递给complete。看看这个answer。【参考方案3】:

您可以通过使用相应选项删除空格,然后手动将它们添加回您想要的选项,所有这些都使用简单的-W(“wordlist”)完成:

complete -o nospace -W 'Dproperty= "option1 " "option2 "' javaProgram

自动补全现在将在option1option2 之后插入一个空格,但在Dproperty= 之后不插入一个空格。

【讨论】:

【参考方案4】:

Dennis 是对的,在你用complete -F _your_func 引用的函数中,你想要这样的东西(取自 /etc/bash_completion):

    # escape spaces; remove executables, aliases, pipes and sockets;
    # add space at end of file names
    COMPREPLY=( $( ssh -o 'Batchmode yes' $userhost \
               command ls -aF1d "$path*" 2>/dev/null | \
               sed -e "s/[][()<>\",:;^&!$&=?\`|\\ ']/\\\\\\\\\\\\&/g" \
               -e 's/[*@|=]$//g' -e 's/[^\/]$/& /g' ) )
    return 0

此特定示例使用-o nospace 选项,但手动添加空间。这是添加空间的最后一个-e ('s/[^\/]$/&amp; /g')。在这种情况下,仅当最后一个参数不以斜杠结尾(这将是一个目录并且具有要自动完成的文件)时才添加。

关键区别似乎是在空格前添加一个 & 符号。试试看它是否有效。

【讨论】:

【参考方案5】:

C4H5As 提到的 scp 的 bash 补全中保留添加空格的功能不是 & 符号,它只是“替换为匹配”的 sed 语法。

您必须更改 IFS,以便 compgen 不会将输入拆分为空格,而是拆分为换行符或制表符:

local IFS=$'\t\n'
COMPREPLY=( $(compgen -W "$options" -- $cur) )

【讨论】:

【参考方案6】:

看看你目前拥有的代码会很有帮助。

但是,如果有的话,请查看 /etc/bash_completion.d/sshscp 的完成代码。它在本地文件名之后放置空格,但不在主机名之后。

【讨论】:

以上是关于在某些 Bash 自动完成选项的末尾添加空格,而不是在其他选项的末尾?的主要内容,如果未能解决你的问题,请参考以下文章

Bash:在行尾查找带有尾随空格的文件

如何在嵌入视频的末尾添加缩略图?

Bash Heredoc 格式在 ) 末尾添加新行;

从 excel/文本文件中读取而不跳过空格,除非由选项卡制作

.sh 文件的 Git bash 选项卡完成

如何添加空格和标点符号以使用正则表达式捕获第一组?如何在 LibreOffice 中停止某些选项卡分为两列?