fish + fzfの --previewオプション を使ってgitのブランチのコミットログを見つつチェックアウトしたり、dockerのlogsを見ながらコンテナを選んだりする

## この投稿で使用しているツールのバージョン

* [fish](https://fishshell.com/) v3.3.1
* [fzf](https://github.com/junegunn/fzf) v0.29.0

## fzf の --preview オプションがすごい

最近、インタラクティブフィルタをfzfに乗り換えました。

乗り換えた理由としては、fzfには `--preview` というオプションがあったからです。

この `--preview` オプションは以下のように指定します。

`$ find * -type f | fzf --preview "echo {}"`

`{}`に現在選択している行が渡されます。

基本的なプレビューのデモです。

プレビューウィンドウを右側に表示するようにしています。(設定で変更可能)

![preview-demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16039/4f86fce0-ea4e-57ed-7080-fff03c8c4795.gif)

公式が用意している [preview.sh](https://raw.githubusercontent.com/junegunn/fzf.vim/master/bin/preview.sh)　と [bat](https://github.com/sharkdp/bat)をインストールしておき、`--preview` オプションを以下のように指定すると、ファイルだった場合は`bat`でプレビューし、ディレクトリだった場合は`ls`でプレビューできます。

`$ find * | fzf --preview "preview.sh {} 2> /dev/null || ls {}"`

![preview-demo2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16039/10e5d8de-1ac1-5131-66ce-7f1827852a38.gif)

この`--preview`をgitとdockerそれぞれと組み合わせた例を紹介したいと思います。

fish向けの設定です。

## Gitで各ブランチのgit logをプレビューとして見つつcheckoutする

fzfでブランチをフィルタしつつ、プレビューとして選択しているブランチのgit logを直近20件表示します。

エンターキー押下でそのブランチをローカルのブランチとしてcheckoutします。

`fco` というgitのサブコマンドとして使えるようにしています。

```shell:.config.fish
function fzf-checkout-branch
    set -l branchname (
        env FZF_DEFAULT_COMMAND='git --no-pager branch -a | grep -v HEAD | sed -e "s/^.* //g"' \
            fzf --height 70% --prompt "BRANCH NAME>" \
                --preview "git --no-pager log -20 --color=always {}"
    )
    if test -n "$branchname"
        git checkout (echo "$branchname"| sed "s#remotes/[^/]*/##")
    end
end
```

```shell:.gitconfig
[alias]
    fco = !fish -c "fzf-checkout-branch"
```

デモとしてreactのリポジトリでcheckoutしてみます。

![demo-git.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16039/70685c36-641e-dcd5-3065-b5f427ae84b0.gif)

## dockerのコンテナのlogを見つつコンテナ名を選ぶ

開発をしていると `docker exec -it コンテナ名 /bin/bash` でコンテナの中に入りたくなったりします。

その時に `docker exec -it ` まで入力して、「あれ、コンテナ名なんだっけ・・・」と思うことがよくあります。

そんな時に `Ctrl+D` で fzf を起動してdocker コンテナの一覧を表示してコンテナ名を表示するスクリプトです。

プレビューとして選択中のコンテナの`docker logs`の結果を画面下側に表示します。

エンターキーを押下すると、選択したコンテナ名をターミナルの現在のカーソルの位置に入力します。

```shell:.config.fish
function fzf-docker-continer-name-select
    commandline -i (env FZF_DEFAULT_COMMAND="docker ps -a --format 'table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Command}}\t{{.RunningFor}}\t{{.Ports}}\t{{.Networks}}'" \
        fzf --no-sort --height 80% --bind='p:toggle-preview' --preview-window=down:70% \
            --preview '
                set -l containername (echo {} | awk -F " " \'{print $2}\');
                if test "$containername" != "ID"
                    docker logs --tail 300 $containername
                end
            ' | \
        awk -F " " '{print $2}')
end
```

```shell:fish_user_key_bindings.fish
function fish_user_key_bindings
  bind \cd fzf-docker-continer-name-select
  fzf_key_bindings
end
```

NginxとPostgreSQLのコンテナが動いている状態のデモです。

![demo-docker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16039/006f1d83-113c-18ac-dba2-533251c9e067.gif)


## まとめ

fzfの`--preview`がすごく便利だったので、gitやdockerと組み合わせて使う方法を紹介しました。

公式Githubのwikiにコミュニティベースでfzfといろんなツールとの組み合わせを集めているページがあるので、fzfに興味が湧いた方はこちらも見てみると良いと思います。

https://github.com/junegunn/fzf/wiki/examples