创建 bash 补全脚本以在等号后自动补全路径?

创建 bash 补全脚本以在等号后自动补全路径?

我想创建一个 bash 完成脚本,它可以识别--arg和形式的参数--some-arg=file

看完之后本教程以及 中的一些示例/usr/share/bash_completion/completions/,我编写了以下脚本(以节省使用 Chromium 输入一些标志的时间):

_chromium() 
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    # Some interesting options
    opts="
--disable-web-security
--easy-off-store-extension-install
--incognito
--load-extension=
--pack-extension=
--pack-extension-key=
--user-data-dir=
"
    # Handle --xxxxxx=file
    if [[ ${cur} == "--"*"=" ]] ; then
        # Removed failures (is my logic OK?)
        return 0
    fi

    # Handle other options
    if [[ ${cur} == -* ]] ; then
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        return 0
    fi
}
complete -F _chromium chromium

我将其保存到~/bash_completions/chromium,并使用 创建了一个符号链接sudo ln -s ~/bash_completions/chromium /usr/share/bash_completion/completions/chromium
然后我使用加载它. /usr/share/bash_completions/completions/chromium

现在,我遇到两个问题:

  • chromium --u<TAB>扩展到chromium --user-data-dir=<SPACE>(我不想要这个空间)。
  • 路径(目录和文件)不再完整。

我该如何解决这些问题?

答案1

我已经找到了解决这两个问题的方法!

  1. 要不附加空格,请使用该nospace选项。这可以通过两种方式完成:

    • 将其传递给complete
      complete -o nospace -F _chromium chromium
    • 使用compopt内置:(
      compopt -o nospace启用该选项)
      compopt +o nospace(禁用该选项)

    我在 gnu.org 的 Bash 文档中找到了它,8.7 可编程完成内置函数

  2. 完成文件。
    • 彼得夫建议-f将标志与 一起使用compgen。我遵循了该建议,并将其实施为COMPREPLY=( $(compgen -f "$cur") ).这工作得很好,直到我尝试完成包含空格的路径。
      在 Stack Overflow 上,我发现这个答案建议手动创建完成列表(不使用compgen)。这种方法效果很好。
    • 使用该filenames选项告诉 Readline compspec 生成文件名,因此它可以:
      • 执行任何特定于文件名的处理(例如向目录名称添加斜杠、引用特殊字符或抑制尾随空格)
      • 使用不同的颜色来指示文件类型(colored-stats启用)

借助...的帮助Bash 的字符串操作(为了扩展~和处理空格),我构建了一个 bash 完成脚本,它满足问题中所述的所有标准。

_chromium() 
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    # Some interesting options
    opts="
--disable-web-security
--easy-off-store-extension-install
--incognito
--load-extension=
--pack-extension=
--pack-extension-key=
--user-data-dir=
"
    # Handle --xxxxxx=
    if [[ ${prev} == "--"* && ${cur} == "=" ]] ; then
        compopt -o filenames
        COMPREPLY=(*)
        return 0
    fi
    # Handle --xxxxx=path
    if [[ ${prev} == '=' ]] ; then
        # Unescape space
        cur=${cur//\\ / }
        # Expand tilder to $HOME
        [[ ${cur} == "~/"* ]] && cur=${cur/\~/$HOME}
        # Show completion if path exist (and escape spaces)
        compopt -o filenames
        local files=("${cur}"*)
        [[ -e ${files[0]} ]] && COMPREPLY=( "${files[@]// /\ }" )
        return 0
    fi

    # Handle other options
    COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
    if [[ ${#COMPREPLY[@]} == 1 && ${COMPREPLY[0]} != "--"*"=" ]] ; then
        # If there's only one option, without =, then allow a space
        compopt +o nospace
    fi
    return 0
}
complete -o nospace -F _chromium chromium

答案2

要完成文件名,请尝试传递-fcompgen.

恐怕您将无法删除选项后面的空格,因为这就是完成的工作原理 - 一旦找到唯一的匹配项,它就会完全完成它。

相关内容