当我的单词包含冒号时如何给出正确的选项卡完成建议
How to give correct suggestions to tab complete when my words contains colons
我正在为一个实用程序编写一个 bash 制表符完成文件,有时需要完整的 URL 表格:protocol://host:port
。这包含两个冒号,已被证明对制表符完成有问题。这是因为冒号被视为分词符。我读到我不应该直接更改 COMP_WORDBREAKS
,所以我想按照此处的建议使用 _get_comp_words_by_ref
和 __ltrim_colon_completions
:How to reset COMP_WORDBREAKS without effecting other completion script?
这适用于单个冒号,但第二个冒号会导致一个小问题,如这个最小示例所示:
这个例子说明了问题。它出现在建议中的任意数量的冒号上。
[root@2e3e8853cc0c /]# cat /etc/bash_completion.d/foo
_foo()
{
local cur
COMPREPLY=()
_get_comp_words_by_ref -n : -c cur
COMPREPLY=( $(compgen -W "http://host:1234/aaa http://host:1234/bbb http://host:1234/ccc" -- ${cur}) )
__ltrim_colon_completions "$cur"
return 0
}
complete -F _foo foo
在 foo
成功完成公共部分后点击 Tab。之后点击 Tab 键两次,会产生以下建议:
[root@2e3e8853cc0c /]# foo http://host:1234/
1234/aaa 1234/bbb 1234/ccc
想要的结果当然是:
[root@2e3e8853cc0c /]# foo http://host:1234/
http://host:1234/aaa http://host:1234/bbb http://host:1234/ccc
之后,按 a、b 或 c 加 tab 按预期工作,它完成了完整 URL。
对如何生成正确的输出有什么建议吗?我需要手动更改 COMPREPLY
变量,还是我只是使用了错误的函数?
基于我一直使用的一个技巧,我想出了一个解决方案。希望对你有帮助。
_bar()
{
local CUR=
local cur
local -a compreply=()
local -a urls=(ftp://gnu.org \
http://host1:1234/aaa \
http://host2:1234/bbb \
http://host2:1234/ccc)
_get_comp_words_by_ref -n : -c cur
compreply=( $(compgen -W "${urls[*]}" -- "$cur") )
COMPREPLY=( "${compreply[@]}" )
__ltrim_colon_completions "$cur"
if [[ ${#COMPREPLY[@]} -gt 1 ]]; then
local common_prefix
common_prefix=$( printf '%s\n' "${COMPREPLY[@]}" \
| sed '$q;N;s/^\(.*\).*\n.*$//;h;G;D' )
if [[ $common_prefix == "$CUR" ]]; then
COMPREPLY=( "${compreply[@]}" " " )
fi
fi
return 0
}
complete -F _bar bar
下面是它的样子(使用 Bash 4.3.33
测试):
[STEP 101] $ bar <TAB><TAB>
http://host1:1234/aaa http://host2:1234/ccc
ftp://gnu.org http://host2:1234/bbb
[STEP 101] $ bar f<TAB>
[STEP 101] $ bar ftp://gnu.org␣
[STEP 101] $ bar ftp://gnu.org <ENTER>
bash: bar: command not found
[STEP 102] $ bar h<TAB>
[STEP 102] $ bar http://host
[STEP 102] $ bar http://host<TAB><TAB>
http://host2:1234/bbb
http://host1:1234/aaa http://host2:1234/ccc
[STEP 102] $ bar http://host2<TAB>
[STEP 102] $ bar http://host2:1234/
[STEP 102] $ bar http://host2:1234/<TAB><TAB>
http://host2:1234/bbb http://host2:1234/ccc
[STEP 102] $ bar http://host2:1234/b<TAB>
[STEP 102] $ bar http://host2:1234/bbb␣
[STEP 102] $ bar http://host2:1234/bbb <ENTER>
bash: bar: command not found
[STEP 103] $
实际上这个问题并不特定于两个或多个冒号。一个冒号也有类似的问题。
我正在为一个实用程序编写一个 bash 制表符完成文件,有时需要完整的 URL 表格:protocol://host:port
。这包含两个冒号,已被证明对制表符完成有问题。这是因为冒号被视为分词符。我读到我不应该直接更改 COMP_WORDBREAKS
,所以我想按照此处的建议使用 _get_comp_words_by_ref
和 __ltrim_colon_completions
:How to reset COMP_WORDBREAKS without effecting other completion script?
这适用于单个冒号,但第二个冒号会导致一个小问题,如这个最小示例所示:
这个例子说明了问题。它出现在建议中的任意数量的冒号上。
[root@2e3e8853cc0c /]# cat /etc/bash_completion.d/foo
_foo()
{
local cur
COMPREPLY=()
_get_comp_words_by_ref -n : -c cur
COMPREPLY=( $(compgen -W "http://host:1234/aaa http://host:1234/bbb http://host:1234/ccc" -- ${cur}) )
__ltrim_colon_completions "$cur"
return 0
}
complete -F _foo foo
在 foo
成功完成公共部分后点击 Tab。之后点击 Tab 键两次,会产生以下建议:
[root@2e3e8853cc0c /]# foo http://host:1234/
1234/aaa 1234/bbb 1234/ccc
想要的结果当然是:
[root@2e3e8853cc0c /]# foo http://host:1234/
http://host:1234/aaa http://host:1234/bbb http://host:1234/ccc
之后,按 a、b 或 c 加 tab 按预期工作,它完成了完整 URL。
对如何生成正确的输出有什么建议吗?我需要手动更改 COMPREPLY
变量,还是我只是使用了错误的函数?
基于我一直使用的一个技巧,我想出了一个解决方案。希望对你有帮助。
_bar()
{
local CUR=
local cur
local -a compreply=()
local -a urls=(ftp://gnu.org \
http://host1:1234/aaa \
http://host2:1234/bbb \
http://host2:1234/ccc)
_get_comp_words_by_ref -n : -c cur
compreply=( $(compgen -W "${urls[*]}" -- "$cur") )
COMPREPLY=( "${compreply[@]}" )
__ltrim_colon_completions "$cur"
if [[ ${#COMPREPLY[@]} -gt 1 ]]; then
local common_prefix
common_prefix=$( printf '%s\n' "${COMPREPLY[@]}" \
| sed '$q;N;s/^\(.*\).*\n.*$//;h;G;D' )
if [[ $common_prefix == "$CUR" ]]; then
COMPREPLY=( "${compreply[@]}" " " )
fi
fi
return 0
}
complete -F _bar bar
下面是它的样子(使用 Bash 4.3.33
测试):
[STEP 101] $ bar <TAB><TAB>
http://host1:1234/aaa http://host2:1234/ccc
ftp://gnu.org http://host2:1234/bbb
[STEP 101] $ bar f<TAB>
[STEP 101] $ bar ftp://gnu.org␣
[STEP 101] $ bar ftp://gnu.org <ENTER>
bash: bar: command not found
[STEP 102] $ bar h<TAB>
[STEP 102] $ bar http://host
[STEP 102] $ bar http://host<TAB><TAB>
http://host2:1234/bbb
http://host1:1234/aaa http://host2:1234/ccc
[STEP 102] $ bar http://host2<TAB>
[STEP 102] $ bar http://host2:1234/
[STEP 102] $ bar http://host2:1234/<TAB><TAB>
http://host2:1234/bbb http://host2:1234/ccc
[STEP 102] $ bar http://host2:1234/b<TAB>
[STEP 102] $ bar http://host2:1234/bbb␣
[STEP 102] $ bar http://host2:1234/bbb <ENTER>
bash: bar: command not found
[STEP 103] $
实际上这个问题并不特定于两个或多个冒号。一个冒号也有类似的问题。