Bash 补全覆盖当前单词

Bash 补全覆盖当前单词

我正在尝试为我的命令创建一个 bash 完成脚本。ls有我想要的行为。我需要从我的命令中得到同样的行为。

这就是我得到的ls

$ ls /home/tux/<Tab><Tab>
Downloads  Documents  Pictures
$ ls /home/tux/Do<Tab><Tab>
Downloads  Documents

即 bash 仅显示相对的下一个路径,而不是绝对的(即它确实添加Downloads到完成列表中,但不是/home/tux/Downloads

我想编写一个以相同方式工作的完成脚本。这是我尝试过的。

_testcommand ()
{
    local IFS=$'\n'
    local cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=( $(compgen -o bashdefault -d -- "$cur") )
    if [ "${#COMPREPLY[@]}" -ne 1 ]
    then
        # remove prefix "$cur", so the preview of paths gets shorter
        local cur_len=$(echo $cur | sed 's|/[^/]*$||' | wc -c)
        for i in ${!COMPREPLY[@]}
        do
            COMPREPLY[$i]="${COMPREPLY[i]:$cur_len}"
        done
    fi
    return 0
}

complete -o nospace -F _testcommand testcommand

然而结果是这样的:

$ testcommand /home/tux/<Tab><Tab>
Downloads  Documents  Pictures
$ testcommand /home/tux/Do<Tab>
Downloads  Documents
$ testcommand Do

我怎样才能完成我的工作不是/home/tux/从命令行中删除?

注意:我想我不能在complete底部的调用中添加“-f”或“-d”等。实际上,在某些情况下,完成还必须完成单词而不是路径。

答案1

您可以通过“ls”检查使用哪个补全函数:complete -p | grep ls。您可以使用以下命令检查该函数:(type _longopt上一个命令的结果)。在_longopt函数中你可以找到该_filedir函数。

最后是一篇关于完成的有趣文章:https://spin.atomicobject.com/2016/02/14/bash-programmable-completion/

答案2

bash 完成目录 ( pkg-config --variable=completionsdir bash-completion) 中的大多数程序都使用_filedirbash-completion 本身提供的功能。重用似乎是合法的_filedir- 无需担心您自己的实现!

微量元素:

_testcommand()
{
    # init bash-completion's stuff
    _init_completion || return

    # fill COMPREPLY using bash-completion's routine
    # in this case, accept only MarkDown and C files
    _filedir '@(md|c)'
}
complete -F _testcommand testcommand

当然,您仍然可以在完成非文件时使用它:

if ...
then
    # any custom extensions, e.g. words, numbers etc
    COMPREPLY=( $(compgen ...) )
else
    # fill COMPREPLY using bash-completion's routine
    _filedir '@(md|c)'
fi

我是怎么找到它的?

谢谢@csm:使用他们的答案,检查type _longopt,哪个调用_filedir

相关内容