无论如何,是否可以将 COMPREPLY 输出为垂直单词列表而不是单行?

无论如何,是否可以将 COMPREPLY 输出为垂直单词列表而不是单行?

COMPREPLY 默认情况下返回一个空格分隔的单词列表,但我想让它每行返回一个单词。我尝试在单词末尾添加换行符,并浏览了 compgen 和complete 的文档,但找不到任何内容。

这可能吗?

编辑:

抱歉我真的解释得很糟糕。我有一个通过complete -F 绑定到自动完成函数的脚本。当用户运行脚本时,按两次 Tab 键将通过 compgen 显示可能的选项列表。现在该函数具有如下代码行:

COMPREPLY=( $(compgen -W '$( ls ~/work/dev/jobs/ | cat )' -- $curword ) )

当用户点击选项卡时,这些目录将显示如下:

directory0 directory1 directory2 directory3

但我希望它们显示为:

directory0
directory1
directory2
directory3

我向 /r/bash 发布了一个类似的帖子,有人建议这样做

bind 'set completion-display-width 0'

这是有效的,然后我可以取消它

bind 'set completion-display-width -1'

现在的问题是,如果我在完整函数返回之前取消设置它,它不会产生任何效果,因此我在用户按 Enter 后在脚本中取消设置它。这工作正常,但如果用户开始使用自动完成功能,然后改变主意并删除他们输入的内容并返回到 shell,completion-display-width 仍将设置为 0。

还有其他方法可以解决这个问题吗?

答案1

completion-display-width我是建议更改readline 变量的人/r/bash,但是您没有指定您只想让它在这一个完成功能上工作。

无论如何,在完成函数中,您可以检测它是由TAB(COMP_TYPE == 9) 还是由TABTAB(COMP_TYPE == 63) 触发,如果是后者,您可以用空格填充结果,以便它们填充整个宽度终端的。这是我能想到的最不黑客的事情。它看起来像这样:

_foo_complete() {
    local i file files
    files=( ~/work/dev/jobs/"$2"* )
    [[ -e ${files[0]} || -L ${files[0]} ]] || return 0
    if (( COMP_TYPE == 63 )); then
        for file in "${files[@]}"; do
            printf -v 'COMPREPLY[i++]' '%*s' "-$COLUMNS" "${file##*/}"
        done
    else
        COMPREPLY=( "${files[@]##*/}" )
    fi
}
complete -F _foo_complete foo

顺便说一句,你真的不应该解析 ls 输出

答案2

要仅为特定完成函数修改 readline 变量,您可以在函数执行期间设置 readline 变量,然后将$PROMPT_COMMAND其更改回来。

_foo_complete() {
    # retrieve the original value
    local width=$(bind -v | sed -n 's/^set completion-display-width //p')

    if [[ $width -ne 0 ]]; then
        # change the readline variable
        bind "set completion-display-width 0"

        # set up PROMPT_COMMAND to reset itself to its current value
        PROMPT_COMMAND="PROMPT_COMMAND=$(printf %q "$PROMPT_COMMAND")"

        # set up PROMPT_COMMAND to reset the readline variable
        PROMPT_COMMAND+="; bind 'set completion-display-width $width'"
    fi

    # whatever the function normally does follows
    COMPREPLY=(aa bb)
}
complete -F _foo_complete foo

相关内容