よく実行するコマンドをfzf使ったスクリプトにしたら捗って最高な1年になった話

# こんにちは
LITALICOでWebエンジニアをしている @tom-ock です。
この記事は『[LITALICO Advent Calendar 2020](https://qiita.com/advent-calendar/2020/litalico)』3日目の記事です。

皆さんエイリアスや自作スクリプト使ってますか？
毎日の開発で使ってるけど、毎回打ち込むには長いコマンドはエイリアスや自作スクリプトにしてしまうと便利です。

コードを書いて効率化するって意味で、自作スクリプトって個人的にはプログラミングの本質な気がして好きなんですよね。
あくまで自分用なので気軽に作れるのもいいんです。

という訳で自作して普段よく使ってる2つのスクリプトを紹介します。

# `that`

前提自分の普段の開発環境の概要を説明すると、
サーバーサイドは`Rails`を`docker-compose`で動かし、
フロントエンドは`React`を`webpack-dev-server`で動かしてます。

それで開発で使ってるコマンドは大体こんな感じです。

- `yarn dev`
- `yarn user_dev`
- `yarn client_dev`
- `yarn admin_dev`
- `yarn storybook`
- `yarn build-storybook`
- `yarn test start`
- `docker-compose up -d`
- `docker-compose logs -f app`
- `docker-compose down`
- `docker-compose build`
- `docker-compose run --rm app bash`
- `docker-compose run --rm app bundle exec rails c`
- `docker-compose run --rm app bundle exec rails setup:reindex_all`
- `docker-compose run --rm app bundle exec rails db:migrate RAILS_ENV=development`
- `docker-compose run --rm app bundle exec rails db:migrate RAILS_ENV=test`
- `docker-compose run --rm app bundle exec rails c`

他のチームでも同じかと思いますが`docker-compose`系のコマンドって結構長くなりがちですよね。
特にチームにジョインした当初は前に実行したことあるのに、「あれしたいんだけど、あのコマンドなんだっけ」となりがちでした。

そこで当初はよく使いそうなコマンドはメモして、メモ見ながらコマンドを実行してました。
でもそもそもメモ使ってコマンド実行すればいいじゃないかと思いついたのが`that`コマンドです。

[![asciicast](https://asciinema.org/a/zQSAUnOaaXNUPxtTJfhqZQm9H.svg)](https://asciinema.org/a/zQSAUnOaaXNUPxtTJfhqZQm9H)

`that`

```bash
#!/bin/bash

git_root=$(git rev-parse --show-toplevel)

if [ $? -ne 0 ]; then
  echo 'gitリポジトリ内で実行してください'
  exit 1
fi

those_path="${git_root}/.those"

if [ ! -f $those_path ]; then
  echo "${those_path}が存在しません"
  exit 1
fi

cd $git_root && \
  eval $(cd $git_root && cat $those_path | fzf)
```

やってることはこんな感じです。

- 前提、`that`コマンドを使う前によく使うコマンドを`.those`というテキストファイルにメモしておく
- `.those`の中身を`fzf`で絞り込み、実行したいコマンドを選択
- 選択したコマンドを実行

`fzf`使うといい感じに絞り込めて最高ですね。
`history`使ってコマンドを検索してもいいんですが、あまり使わないけどたまに使うコマンドって`history`だと埋もれちゃうので、`.those`のテキストファイルとしてメモしています。

テキストファイルとして残していることで、チームに新しいメンバーがジョインした時にコマンド聞かれた時に`.those`を見てさっと出せるのもよいですね。

# `git-create-pr`

自分のチームは基本Issueに紐付ける形でブランチを作成しており、
以下のようにブランチの命名規則が存在します。
`feature/{Issue番号}-{実装内容}`

毎回issue番号調べてブランチを作成してもいいんですが、[Github CLI](https://cli.github.com/)でIssueの一覧が取得できると知り、ブランチ作成を1コマンドで対話的に作成できるようにしました。

[![asciicast](https://asciinema.org/a/UQcPNLSGjH8pPDw1pMb2Olmh8.svg)](https://asciinema.org/a/UQcPNLSGjH8pPDw1pMb2Olmh8)

`git-create-pr`

```bash
#!/bin/bash

IFS=$'\n'

while : ; do
  selected_issue=$(gh issue list --state open --limit 1000 | fzf)

  echo ''
  echo 'Selected Issue is'
  echo ''
  echo $selected_issue
  echo ''
  echo 'Is it OK?[y/N/q]'

  read input

  if [ -z $input ]; then
    continue
  fi

  if   [ $input = 'Q' ] \
    || [ $input = 'q' ] \
    || [ $input = 'Quit' ] \
    || [ $input = 'quit' ]; then
    exit 1
  elif [ $input  = 'Y' ] \
    || [ $input  = 'y' ] \
    || [ $input  = 'Yes' ] \
    || [ $input  = 'yes' ]; then
    break
  fi
done


number=$(echo $selected_issue | awk -F ' ' '{ print $1 }')


while : ; do
  echo ''
  echo 'Input feature title.'
  echo "  e.g) feature-#${number}-TITLE"

  read title

  if [ -z $title ]; then
    continue
  fi

  branch_name="feature/#${number}-${title}"

  echo ''
  echo 'Branch name will be'
  echo ''
  echo $branch_name
  echo ''
  echo 'Is it OK?[y/N/q]'

  read input

  if [ -z $input ]; then
    continue
  fi

  if   [ $input = 'Q' ] \
    || [ $input = 'q' ] \
    || [ $input = 'Quit' ] \
    || [ $input = 'quit' ]; then
    exit 1
  elif [ $input  = 'Y' ] \
    || [ $input  = 'y' ] \
    || [ $input  = 'Yes' ] \
    || [ $input  = 'yes' ]; then
    break
  else
    continue
  fi
done

git checkout -b $branch_name
```
やってることはこんな感じです。

- `gh issue list`の出力結果を`fzf`で選択しissue番号を取得
- 対話形式で「実装内容の文字列」を取得
- 「issue番号」と「実装内容の文字列」から、新しいブランチを作成してチェックアウト

CLI上でIssueタイトルからIssue番号を`fzf`で簡単に絞り込めて最高です。

結論、自作スクリプトは`fzf`を使うといい感じになりますね。
`fzf`はそのままでも便利ですが自作コマンドの中で使うと捗ります。
また「[GitHub CLIで始める快適GitHub生活 - Qiita](https://qiita.com/ryo2132/items/2a29dd7b1627af064d7b
)」でも紹介されている通り[Github CLI](https://cli.github.com/)は便利ですね。
そのままでも便利ですが、自作スクリプトの中で使っても応用が効きそうなので色々遊んでみようと思います。

# おわりに
自作コマンドを作る中で「これ実現するにはどんなコマンド使えばいいんだろう？」と、シェルスクリプトのいい勉強になっています。

スクリプト作成も自分用であればハードルが低いので、あまりシェルスクリプト触らない方は練習がてら是非自作してみてください！

既に何かしら便利なスクリプトを自作している方は是非コメント欄で教えて下さい！

明日は @taro-hiroi さんの記事です！
お楽しみに！

# 参考
- [便利な「git-サブコマンド」を作成する](https://qiita.com/b4b4r07/items/6b76a5f969231e5e9748)
- [おい、peco もいいけど fzf 使えよ](https://qiita.com/b4b4r07/items/9e1bbffb1be70b6ce033)
- [GitHub CLIで始める快適GitHub生活 - Qiita](https://qiita.com/ryo2132/items/2a29dd7b1627af064d7b
)
- [Github CLI](https://cli.github.com/)