如何在bash中启用默认文件完成 [英] How to enable default file completion in bash

查看:51
本文介绍了如何在bash中启用默认文件完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有一个名为"foo"的命令,该命令带有一个参数("encrypt"或"decrypt"),然后是一个文件列表.我想编写一个bash完成脚本,该脚本有助于第一个参数,然后为其他参数启用标准文件完成.我能找到的最接近的是:

Say I have a command named "foo" that takes one argument (either "encrypt" or "decrypt") and then a list of files. I want to write a bash completion script that helps with the first argument and then enables standard file completion for the others. The closest I've been able to come is this:

complete -F _foo foo

function _foo()
{
    local cmds cur
    if [ $COMP_CWORD -eq 1 ]
    then
        cur="${COMP_WORDS[1]}"
        cmds=("encrypt decrypt")
        COMPREPLY=($(compgen -W "${cmds}" -- ${cur}) )
    else
        COMPREPLY=($(compgen -f ${COMP_WORDS[${COMP_CWORD}]} ) )
    fi
}

这正确地执行了第一个参数,并且将从当前目录中选择一个文件名作为后续文件名.但是说当前目录包含一个子目录栏,其中包含文件baz.txt.键入ba-TAB-TAB后,完成结果显示为"bar"("r"后的空格),并准备选择下一个参数.我想要的是标准的bash补全,其结果是"bar/"(斜杠后没有空格),可以在子目录中选择一个文件.有什么办法吗?

This does the first argument correctly and will chose a filename from the current directory for the subsequent ones. But say the current directory contains a subdirectory bar that contains a file baz.txt. After typing ba-TAB-TAB, completion results in "bar " (space after the "r") and is ready to choose the next argument. What I want is the standard bash completion, where the result is "bar/" (no space after the slash), ready to choose a file in the subdirectory. Is there any way to get that?

推荐答案

bash文档可能有点神秘.最简单的解决方案是更改完成功能绑定:

The bash documentation can be a little enigmatic. The simplest solution is to alter the completion function binding:

complete -o filenames -F _foo foo

这意味着该函数返回文件名(包括目录),并对结果进行特殊处理.

This means the function returns filenames (including directories), and special handling of the results is enabled.

(恕我直言,文档中并未明确说明这会有效地对您的完成函数设置的 COMPREPLY [] 进行后处理;并且某些 -o 选项,包括在内,当应用于 compgen 时似乎无效.)

(IMHO the documentation doesn't make it clear that this effectively post-processes COMPREPLY[] as set by your completion function; and that some of the -o options, that one included, when applied to compgen appear to have no effect.)

您可以通过以下方式更接近正常的bash行为:

You can get closer to normal bash behaviour by using:

 complete -o filenames -o bashdefault -F _foo foo

使您〜"完成.

但是上述内容有两个问题:

There are two problems with the above however:

  • 如果您有一个名为"encrypt"或"decrypt"的目录,则关键字的扩展将以结尾的"/"结尾
  • $ VARIABLE 扩展将不起作用, $ 将变为 \ $ ,以更好地将文件名与 $ .同样, @host 扩展将无法正常工作.
  • if you have a directory named "encrypt" or "decrypt" then the expansion of your keywords will grow a trailing "/"
  • $VARIABLE expansion won't work, $ will become \$ to better match a filename with a $. Similarly @host expansion won't work.

我发现处理此问题的唯一方法是处理 compgen 输出,而不是依赖于文件名"后处理:

The only way that I have found to deal with this is to process the compgen output, and not rely on the "filenames" post-processing:

_foo()
{
    local cmds cur ff
    if (($COMP_CWORD == 1))
    then
        cur="${COMP_WORDS[1]}"
        cmds="encrypt decrypt"
        COMPREPLY=($(compgen -W "$cmds" -- "$cur"))
        COMPREPLY=( "${COMPREPLY[@]/%/ }" )   # add trailing space to each
    else
        # get all matching files and directories
        COMPREPLY=($(compgen -f  -- "${COMP_WORDS[$COMP_CWORD]}"))

        for ((ff=0; ff<${#COMPREPLY[@]}; ff++)); do
            [[ -d ${COMPREPLY[$ff]} ]] && COMPREPLY[$ff]+='/'
            [[ -f ${COMPREPLY[$ff]} ]] && COMPREPLY[$ff]+=' '
        done
    fi
}

complete -o bashdefault -o default -o nospace -F _foo foo

(我在上面还删除了 cmd 的多余数组,并使 compgen 更健壮并可以处理文件名中的空格或前导破折号.)

(I also removed the superfluous array for cmd in the above, and made compgen more robust and handle spaces or leading dashes in filenames.)

现在的缺点是,当您获得中间完成列表(即当您两次按下 tab 来显示多个匹配项)时,您将不会在目录上看到尾随/,并且由于启用了nospace 〜$ @ 扩展不会增加空间以使它们被接受.

The downsides now are that when you get the intermediate completion list (i.e. when you hit tab twice to show multiple matches) you won't see a trailing / on directories, and since nospace is enabled the ~ $ @ expansions won't grow a space to cause them to be accepted.

简而言之,我不相信您可以琐碎地混合并匹配自己的完成和完整的bash完成行为.

In short, I do not believe you can trivially mix-and-match your own completion and the full bash completion behaviour.

这篇关于如何在bash中启用默认文件完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆