17

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

$ javaProgram -Dproperty=foo option1 option2

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

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

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

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

4

6 回答 6

7

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

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

自动完成现在将在option1and之后插入一个空格option2,但在之后不插入一个空格Dproperty=

于 2016-09-29T19:32:05.297 回答
6

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

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

local IFS=$'\t\n'
COMPREPLY=( $(compgen -W "$options" -- $cur) )
于 2012-08-29T12:41:12.170 回答
1

It would be helpful to see the code you have so far.

However, look at the completion code for scp in /etc/bash_completion.d/ssh if you have that. It puts spaces after local filenames but not after hostnames.

于 2010-02-26T06:42:22.667 回答
1

丹尼斯是对的,在你引用的函数中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/[^\/]$/& /g')这是增加空间的最后一个。在这种情况下,仅当最后一个参数不以斜杠结尾(这将是一个目录并且具有要自动完成的文件)时才添加。

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

于 2010-02-26T08:20:14.437 回答
1

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

_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

但是,我只需要在短选项之后的空间。=要对比多头和空头选项,您可以检查建议中是否有 a 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
于 2021-02-11T08:21:20.923 回答
1

正如海报所提到的,无法将-o nospace选项传递给compgen. 一种可能性是定义两个函数,其中一个在调用compopt -o nospace之前插入调用compgen (另一个函数不会)。

例子:

__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_") )
}

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

于 2020-12-21T14:03:05.557 回答