zshエイリアス関数をパイプに渡す方法

zshエイリアス関数をパイプに渡す方法

zsh エイリアスがあります。

gitbs() {
    git branch | grep -- $1
}

次のように結果をgit checkoutに渡したいと思います。 git checkout | gitbs state どうすればこれを行うことができますか?

ベストアンサー1

シェルパイプは、あるコマンドの出力を別のコマンドの入力に渡します。ここでは役に立ちません。コマンドの出力をコマンドライン引数として別のコマンドに渡そうとします。これを行うツールは次のとおりです。コマンドの置き換え。だから基本的なアイデアは

git checkout "$(gitbs state)"

(これはパイプですが、パイプの読み取り端はシェル自体です。出力を読み取ってから、その出力を含むコマンドラインを設定します。)

ただし、出力はgitbs state渡すのに正しい形式ではありませんgit checkout。ブランチ名と同じ行に追加のスペースがあり、時には句読点があります。 (色の書式設定コードもありますが、出力が端末に渡された場合、またはgitが自動的にポケットベルを呼び出す場合にのみ適用され、出力がパイプである場合はありません)。情報のエラーgit checkout

gitbsこの問題を解決するには、元のブランチ名を出力として生成するように変更できます。以下は、出力が端末の場合は人のためのきれいな形式を維持し、それ以外の場合は1行に分岐名を印刷するバージョンです。それを使うgit for-each-ref支店名を列挙します。これ条件式 -t 1標準出力が端末かどうかをテストします。

gitbs () {
  if [[ -t 1 ]]; then
    git branch
  else
    git for-each-ref --format='%(refname:lstrip=2)' 'refs/heads/*'
  fi | grep -- "$1"
}

この定義でgitbsそれはgit checkout "$(gitbs state)"すべてです。

コマンド置換の周りに二重引用符があります。二重引用符(git checkout $(gitbs state))がない場合、出力はスペースから別の引数に分割されるため、複数のブランチが一致すると、結果コマンドはチェックアウトするのではなく、ファイルの現在のバージョンをgit checkout foobar1 foobar2ifのバージョンで上書きします。名前のファイルが存在します。foobar1foobar2foobar1foobar2

gitbsこれらのトラップを回避するには、一致する単一のブランチが必要な別のバージョンを定義することをお勧めします。一致するブランチがゼロを超える場合、現在のブランチに関する追加メッセージは引き続き表示されますが、より明確なエラーメッセージが表示されますgit checkout。この関数は一致する分岐のリストを大量に

gitbs1 () {
  local branches
  branches=($(git for-each-ref --format='%(refname:lstrip=2)' 'refs/heads/*' | grep "$1"))
  if ((#branches == 0)); then
    echo "No branch contains '$1'" >&2
    return 3
  fi
  if ((#branches > 1)); then
    echo "Multiple branches match '$1':" >&2
    print -lr $branches >&2
    return 3
  fi
  echo $branches
}

これで自信を持って書くことができますgit checkout $(gitbs1 state)


このオプションをオンにするとglob_complete(つまりsetopt glob_complete.zshrc)次に入力できます。

子ブランチ *foo*Tab

*foo*一致するブランチの名前(存在する場合)に置き換えられます。一致するブランチが複数ある場合は、一般(プレフィックス)完了と同じ種類のメニューまたはループ動作が発生します。

おすすめ記事