创建 bash 完成脚本以在等号后自动完成路径?

Rob*_*b W 12 bash chrome autocomplete

我想创建一个 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
Run Code Online (Sandbox Code Playgroud)

我将它保存到~/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>(我不想要空间)。
  • 路径(目录和文件)不再完整。

我该如何解决这些问题?

Rob*_*b W 13

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

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

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

    我在 gnu.org 的 Bash 文档8.7 Programmable Completion Builtins 中找到了它。

  2. 完成文件。
    • peterph 建议-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
Run Code Online (Sandbox Code Playgroud)