他のシェルが入っているディレクトリ名を完成させる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
}