在某些 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=
,然后允许用户键入值)。
我希望完成后不要在等号后插入空格。但是,当用户键入程序的各种选项时(上例中的option1
和option2
),我希望脚本完成,并在完成时插入一个空格。
我是 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
自动补全现在将在option1
和option2
之后插入一个空格,但在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/[^\/]$/& /g')
。在这种情况下,仅当最后一个参数不以斜杠结尾(这将是一个目录并且具有要自动完成的文件)时才添加。
关键区别似乎是在空格前添加一个 & 符号。试试看它是否有效。
【讨论】:
【参考方案5】:C4H5As 提到的 scp 的 bash 补全中保留添加空格的功能不是 & 符号,它只是“替换为匹配”的 sed 语法。
您必须更改 IFS,以便 compgen 不会将输入拆分为空格,而是拆分为换行符或制表符:
local IFS=$'\t\n'
COMPREPLY=( $(compgen -W "$options" -- $cur) )
【讨论】:
【参考方案6】:看看你目前拥有的代码会很有帮助。
但是,如果有的话,请查看 /etc/bash_completion.d/ssh
中 scp
的完成代码。它在本地文件名之后放置空格,但不在主机名之后。
【讨论】:
以上是关于在某些 Bash 自动完成选项的末尾添加空格,而不是在其他选项的末尾?的主要内容,如果未能解决你的问题,请参考以下文章