fzfで快適bash生活

# fzfで快適bash生活

Advent Calendar も最終日です ㊗
OSSソリューションセンタ 神山 がトリを取りたく。

## CUI だと覚えておかないと不便なことが多くてつらい…

私はとある社内システムの設計、構築、運用、etc …ゆりかごから墓場まで面倒を見ています。
愛用するシェルはbashです。

基本的に記憶するのが苦手なので…よく使う作業はシェルスクリプトにまとめたりするのですが…そのシェルスクリプトの名前を忘れるという事態に悩まされていました…。

色々試した所、fzf というインクリメンタル検索ができるOSSを利用するととっても便利でした。今回はそのTipsを載せていきます。

なお今回は次のバージョンを前提にしています。

* bash: 5.0.18
* fzf: 0.24.4


## fzf ?

Go製のツールで、リストを与えると、そのリストをインクリメンタル検索して選択することができます (VSCode や IntelliJ など開発環境ではお馴染みの機能)。

### 公式サイト

入手方法や詳しい使い方は [(GitHub) junegunn/fzf](https://github.com/junegunn/fzf) を参照してください。

### 利用イメージ

fzf の利用イメージは次のような形です。

```bash
cat `find . -name "*.md" | fzf`
```

![fzfを利用する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316550/1337576c-2771-27a7-f908-3695846921d3.png)


このようにリストアップされて、選択できるようになります。ファイルを選択すると、`cat` コマンドの引数として選択したファイル名が指定され、中身が表示されます。
(注: この指定方法だと、ファイルが選択されなかった場合に引数が空白となりcatが無限に標準入力を待つことになります。実際に利用する際は、後述のTipsのように fzfの戻りのチェックすべきです。）

さらに… `--preview` オプションを付けると…

```bash
cat `find . -name "*.md" | fzf --preview "cat {}"`
```

![fzfをpreviewオプションを付けて利用する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316550/276f7c5c-2eb2-1b2d-4dc7-8375870704fd.png)


項目選択時に、--preview で指定したコマンドを実行して、その結果を表示してくれます (`{}`が選択された文字列に置換され実行される)。
これは使いどころによっては非常に便利です。

## Tips

「覚えるのがつらい」と感じたら、fzf を使って選べるようにすると、覚える量を最小化できます。
ここでは、個人的に特に効果のあった、`ssh` と `make` の例をご紹介します。

### SSHで接続先をインタラクティブに指定する

SSHの接続先なんて覚えたくない…そんな時はこう。`.ssh/config` を読み込み、設定を選べるようにします。選ぶ際に、Host から次の空白行までをpreview で表示させます。

```bash
function sshs {
  t=$(cat ~/.ssh/config | grep 'Host ' | cut -f2 -d' ' | fzf --preview "cat ~/.ssh/config | sed -ne '/^Host {}$/,/^\s*$/p'")
  if [ -n "$t" ]; then
    ssh "$t"
  fi
}
```

こちらを `~/.bashrc` 等起動時に読み込まれるスクリプトに書いておくと、`sshs` で呼び出せるようになります。

例えば、次のような設定が `~/.ssh/config` に書かれていたとすると…

```text
Host sugoi-saba
# 凄いサーバー
HostName 192.168.123.123
User admin
PORT 22

Host tuyotuyo-machine
# 高性能なマシン
HostName 192.168.244.133
User maint
PORT 10022

Host tuyotuyo-machine2
# 高性能なマシンその2
HostName 192.168.244.134
User maint
PORT 10022
```

![fzfをsshで使う](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316550/e5d3261f-a914-d943-71ec-4f0f9b5dc626.png)

このように、それぞれの設定を確認しながら接続先を選べるのでとっても便利です。当然、選択すると、選択したホストへ接続されます。

### Makeのターゲットをインタラクティブに指定する

どこでも使えるタスクランナーとして、`make` が便利なので、意味のあるタスクは (シェルスクリプトではなく) `Makefile` で書くようにしています。

しかし…久しぶりにMakeを叩く時はいつも、`cat Makefile` でターゲットを思い出すところから開始でした。この作業はとっても無駄なので、fzfで便利にしてみました。

```bash
function makes {
  t=$(cat Makefile | grep '.PHONY: ' | cut -f2- -d' ' | tr ' ' '\n' | fzf --preview "cat Makefile | sed -ne '/^{}:$/,/^\s*$/p'")
  if [ -n "$t" ]; then
    make "$t"
  fi
}
```

こちらを ~/.bashrc 等起動時に読み込まれるスクリプトに書いておくと、makes で呼び出せるようになります。

例えば、次のような設定が ./Makefile に書かれていたとすると…

```Makefile
.PHONY: hello-make
hello-make:
        echo "Hello Make"

.PHONY: hello-fzf
hello-fzf:
        echo "Hello fzf"
```

![fzfをmakeで使う](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316550/370ac9a9-b354-44f4-70f2-45f9d9f38a3d.png)

このように、ターゲットで実行されるコマンドを確認しながら選べるのでとっても便利です。

### もっと便利に

fzf-tmux や fzf.vim あたりを利用していくと、fzf はもっと便利になります！

* [fzf.vim](https://github.com/junegunn/fzf.vim)
* [fzf-tmux(fzfリポジトリの一部)](https://github.com/junegunn/fzf/blob/master/bin/fzf-tmux)

## さいごに

fzf を使えば、覚えておかなくてはいけないことを大幅に削減できます。
今回は、`ssh` や `make` を利用する際の接続先・ターゲットを選べるようにしましたが、似たような設定を書けば、どんなツールにも対応できます！ 
どんどん鍛えて、fzf で快適なbash生活を送りましょう！


## さいごのさいごに

このメッセージが投稿されているということは、今年の `日立グループ OSS Advent Calendar 2020` も無事に走り終えたということでしょう。執筆いただいた方お疲れ様です ＆ 読んでいただいた方有難うございます！

社内でも活動が認知されはじめ、エンジニアな方々から積極的に参加したいという声が集まりました（今年は1枚目は11月中には埋まり、[2枚目](https://qiita.com/advent-calendar/2020/hitachi-oss2)を作りました）。
この流れを強めて、来年はもっと楽しく盛り上げたいと思います。どうかよろしくお願いします！

…

Qiita x HITACHI として、コラボサイトもあります。是非こちらもご覧になってください！ https://qiita.com/official-campaigns/hitachi-2020