Bash 完成使 'cd' 命令从其他正在运行的 shell 完成工作目录?

标签 bash cd completion

我正在尝试编写一个 bash 补全,它可以让我补全其他 shell 所在的目录名称。

例如,假设我在 /very/long/path/name 中打开了另一个 shell ,我目前在一个包含子目录的目录中 foobar .当我输入 cd <Tab> ,我想看看:

$ cd <Tab>
foo/  bar/  /very/long/path/name

我有这个命令来生成可能完成的列表:

ps -Cbash -opid= | xargs pwdx | cut -d" " -f2 | sort -u | while read; do echo ${REPLY#$PWD/}; done | grep -v "^$"

为简洁起见,我将其写为 ...pipeline... .

在我的系统上有一个 _cd产生常规补全的函数:

$ complete -p cd
complete -o nospace -F _cd cd

我想重复使用这个 _cd函数,因为它很重要(~30 行代码,根据 type _cd )。如果解决方案重用已定义的任何完成,则奖励积分,无论它是否基于名为 _cd 的函数.

我以为 -C complete 的选项听起来很有希望,但我无法让它工作:

$ complete -C '...pipeline...' cd
$ cd <Tab>grep: cd: No such file or directory
grep: : No such file or directory
grep: cd: No such file or directory

-F 编写我自己的包装函数, 它附加到 COMPREPLY数组,也不太管用:

$ function _cd2() { _cd; COMPREPLY=( ${COMPREPLY[@]} $(...pipeline...) ); }
$ cd <Tab>
foo/  bar/  name/

它去除除最后一个以外的所有路径组件。我认为它一定是由 _cd 设置的这样做,但我不确定如何抵消它。

如果我删除 _cd来自 _cd2 的电话,我确实看到了完成,但它们没有正确完成部分目录名称。如果我输入 cd /ve<Tab> ,它仍然显示完整路径,但没有真正完成我的命令行。

我怎样才能让它做我想做的事?


附录:_cd的完整定义:

$ type _cd
_cd is a function
_cd () 
{ 
    local cur prev words cword;
    _init_completion || return;
    local IFS='
' i j k;
    compopt -o filenames;
    if [[ -z "${CDPATH:-}" || "$cur" == ?(.)?(.)/* ]]; then
        _filedir -d;
        return 0;
    fi;
    local -r mark_dirs=$(_rl_enabled mark-directories && echo y);
    local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y);
    for i in ${CDPATH//:/'
'};
    do
        k="${#COMPREPLY[@]}";
        for j in $( compgen -d $i/$cur );
        do
            if [[ ( -n $mark_symdirs && -h $j || -n $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then
                j+="/";
            fi;
            COMPREPLY[k++]=${j#$i/};
        done;
    done;
    _filedir -d;
    if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
        i=${COMPREPLY[0]};
        if [[ "$i" == "$cur" && $i != "*/" ]]; then
            COMPREPLY[0]="${i}/";
        fi;
    fi;
    return 0
}

最佳答案

您需要根据组合选项列表评估当前匹配项。这是一个说明移动部件的测试脚本:

#!/bin/bash

mkdir -p {my,other}/path/to/{a,b,c}

function _cd() {
    COMPREPLY=( my/path/to/a my/path/to/b );
}
complete -o nospace -F _cd cd

function _cd2() {
    local cur opts;
    cur="${COMP_WORDS[COMP_CWORD]}";
    _cd;
    opts="${COMPREPLY[@]} other/path/to/c";        # here we combine options
    COMPREPLY=($(compgen -W "${opts}" -- ${cur})); # here is the secret sauce
}
complete -F _cd2 cd

complete -p cd

最重要的点在 _cd2compgen 部分:从组合的选择集中选择最合适的选项(在 $opts).

关于Bash 完成使 'cd' 命令从其他正在运行的 shell 完成工作目录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26550327/

相关文章:

bash - 基于公共(public)字段(IP 地址)连接两个文本文件

linux - 通过 ssh 传递 $PS1

ruby - shell 脚本中的 cd 命令是否将 rvmrc 加载到目标目录中?

c - 使用 C-if 条件实现 cd 系统调用

elasticsearch - 如何完成建议Elasticsearch 5.x

小部件只能在 ZLE 处于事件状态时调用

c - bash 使用什么来打开/执行 argv[0]?

linux - 如何使用 shell 迭代 Linux cpuset?

rust - "cd"执行一系列命令时没有效果

emacs - 在 elisp 的扩展文件名中使用通配符?