目的を達成するために、コマンドを別のコマンドとして扱います。

目的を達成するために、コマンドを別のコマンドとして扱います。

私のzshrcには、ディレクトリを作成して入力するための次の機能が含まれています。

function mcd () {
    mkdir -p "$*" && cd "$*"
}

関数自体はうまく機能しますが、完了後に奇妙な動作が発生します。たとえば、入力を開始しmcd ~/てからを押すとTabメッセージが表示されます。

_mtools_drives:3: command not found: mtoolstest

挿入ポイントに挿入され、何もしません。私が望むのは、コマンドが次のように完了することですmkdir。 zshは私に既存のディレクトリの名前を与える必要があります。

mcd完了目的のためにzshを同じように処理する必要があることをどのように指示しますかmkdir

答え1

次のコードスニペットはmcd次のように完了しますmkdir

compdefas () {
  if (($+_comps[$1])); then
    compdef $_comps[$1] ${^@[2,-1]}=$1
  fi
}
compdefas mkdir mcd

仕組みは、現在の完了設定を見つけることですmkdir。関数の完成コード(通常は完成関数の名前)は連想配列に格納されます_comps。したがって、ステートメントはcompdef $_comps[mkdir] mcd今完成したのとmcd同じ方法で完成する必要があります。mkdir

上記の関数はいくつかの詳細を追加します。

  • テストでは、完了方法が指定されていない(($+_comps[$1]))場合、$1他のパラメータに対して完了方法が設定されていないことを確認します。
  • ${@[2,-1]}は2番目の引数で始まる関数引数のリストなので、複数のコマンド名を指定して補完を定義できます。実際には${^@[a,-1]}これです各配列要素の配列拡張の周囲のテキストをコピーします。
  • =$1設定使用するサービス名。これは、補完機能が密接に関連する複数のコマンドを処理するいくつかのコマンドにのみ重要です。たとえば、補完関数は and だけでなく、while のデフォルトの動作を使用して完了のための動作を使用_gzipできます。gzipgunzippigzunpigzcompdef _gzip foofoo_gzipcompdef _gzip foo=pigzfoo_gzippigz

特定のケースに戻ると、デフォルトの補完はディレクトリをmkdir提供するだけでなく、関数がサポートしないオプションも提供します。したがって、実際にmcd既存のディレクトリを完成させるように定義する方がよいでしょう。 Zshにはヘルパー機能(非文書化ラッパー)が付属しています。_files)。

compdef _directories mcd

このように奇妙に見える完成が現れるのは、mcdそれがかつてかなり広範なコマンドの集まりだったコマンドの名前だったからです。ツールボックス

答え2

compdef次のフォームを使用してください。

compdef [ -ane ] function name

したがって、1つのアイデアは、以下を介して関数をname指すことです。mcd_mkdir

compdef _mkdir mcd

ただし、これは多少不正確です。mkdir完了には提供しないさまざまなフラグが提供されるためですcd。より直接的な方法は、ディレクトリで行うことです。

compdef _directories mcd

関連情報