5

他のシェルが入っているディレクトリ名を完成させるbash補完を書こうとしています。

たとえば、別のシェルを で開いていて/very/long/path/name、現在、サブディレクトリと を含むディレクトリにいるfooとしbarます。と入力すると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配列に追加する独自のラッパー関数 forを作成して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
}
4

1 に答える 1

1

組み合わせたオプションのリストに対して現在の一致を評価する必要があります。可動部分を示すテスト スクリプトを次に示します。

#!/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

最も重要なポイントは、組み合わせた選択肢のセットから最適なオプションを選択する :のcompgen部分です( )。_cd2$opts

于 2014-10-24T15:05:17.333 に答える