【问题标题】:Executing a second completion when pressing tab twice when tab is bound to menu-complete in bash在BASH中绑定到菜单时按住Tab Tab键时执行第二个完成
【发布时间】:2014-05-15 16:40:26
【问题描述】:

设置

标题可能有点迟钝,但我想不出更好的方式来描述它。 我有一个 bash 函数,可以向上导航任意数量的目录,因此:up 2 会将 cd 向上导航 2 级目录结构。

如果您输入up 2<TAB>,它会自动完成并打印出完整路径。

想象一下这个文件结构:

└── demos/
    ├── audio/
    │   ├── assets/
    │   └── index.html
    └── video/
        ├── assets/
        └── index.html

我的当前目录是/demos/video/assets。 如果我按up 2,那么它将把我转到/demos,如果我按up 2<TAB>,它将自动完成到up /demos

补全还有另一个方面,就是如果我输入:up 2/au<TAB>,它会自动补全到up /demos/au<CURSOR>

问题

但是,因为我的 bash_profile 中有:bind 'TAB:menu-complete',然后在它自动完成到 up /demos/au<CURSOR> 之后,就好像 tab 键被困住了,并且没有进一步完成。 我可以让它进一步完成的唯一方法是如果我按另一个键(按目录名称的另一个字母,或者按一次箭头键,然后按 Tab 等)。

有什么方法可以告诉 bash 完成响应第二次按 Tab 键,或者在完成函数返回后以某种方式不捕获 Tab 键?

如果我没有将选项卡绑定到菜单完成,那么第二个选项卡不会被吞没,但是,我宁愿不禁用菜单完成,因为它在所有其他完成中都很有用。

代码

为了让你能看到我在做什么,这是我的完成代码(我只粘贴有趣的部分,但你可以在这里看到整个函数:https://gist.github.com/natecavanaugh/10104c3408bc2bc8d733):

function _complete_up {
    COMPREPLY=()

    local curToken=${COMP_WORDS[COMP_CWORD]}

    curToken=${curToken//'\'}

    if [[ $curToken =~ ^[0-9]+/? ]]; then

        local strpath=$( printf "%${curToken%%/*}s" )
        local upDirSpec=${strpath// /../}

        local trailingpath="${curToken#*/}"

        if [[ $trailingpath =~ ^[0-9]+$ ]]; then
            trailingpath=""
        fi

        local dir=$(cd "$upDirSpec"; echo -n "$PWD/")

        if [[ "$dir" == '//' ]]; then dir='/'; fi

        if [[ -n $trailingpath ]]; then
            if [[ "${trailingpath:0:1}" != "/" && "${dir: -1}" != "/" ]]; then
                trailingpath="/$trailingpath"
            fi

            dir="${dir}${trailingpath}"
        fi

        COMPREPLY=("$dir")
    fi

    return 0
}

complete -o plusdirs -o nospace -o filenames -F _complete_up up

感谢你们提供的任何帮助:)

【问题讨论】:

    标签: bash tab-completion


    【解决方案1】:

    menu-complete 导致 tab 键循环选择选项,但您的完整功能仅提供一种选择。所以没有什么可循环的。

    据我所知,没有办法根据键入的上下文有条件地重新绑定键; readline 作为一个库将允许这样的回调,但 bash 并没有利用该功能,而且我认为并非只有我一个人认为 bash/readline 接口已经过于复杂(“BUGS:它太大了而且太慢了”,正如man bash 多年来所说的那样,并不是专门针对readline)。

    您是否尝试通过将完成函数中外部if 的最后一行更改为类似以下内容来显式添加默认完成:

    COMPREPLY=("$dir" ${dir}*)
    

    (显然,有很多极端情况导致上述内容不够稳健,首先是 ${dir}* 扩展为 $dir 后跟 *,因为它与任何文件名都不匹配。)

    【讨论】:

    • 实际上,这让我非常接近,但它让我重新分析了我所需要的(并澄清了我在使用相同解决方案时遇到的早期问题)。我将代码更改为使用 compgen 返回该目录中可能匹配的列表,如果存在,则直接传递 compgen。早些时候它引起了问题,因为它被引用了,但取消引用它解决了它,所以我将把你的标记为接受的答案。非常感谢!
    猜你喜欢
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    • 2019-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多