6歳娘｢パパ、プロジェクトフォルダを見つけるのに何時間かけるの？｣【ghq+fzf+zsh】

# はじめに


娘(6歳)｢パパ、いま私のためのブログつくってるんでしょ?｣
娘｢ブログってどういうふうにつくるの?｣

ワイ｢コードっていうのを元に動くんや｣
ワイ｢ちょっと待ってな。いまホームディレクトリやから…｣
ワイ｢たしか `projects/myproject01` みたいな名前やったかな…｣
ワイ｢`cd projects/myproject01`...あれ、ないな｣
ワイ｢lsしてみよ。｣ (ポチッ

```bash
$ ls
. .. myproj
myproj1 myproj001 myproject1
myproj2 myproject2 myproject3
yabai-proj sugoi-project
```

ワイ(…クソみたいな構造してるやん)
ワイ｢ごめん。娘ちゃん、もうちょい待ってな｣

娘｢部屋も汚い上に、ディレクトリも整理されてないんだね｣

# どうするか

ghq と fzf(Fuzzy Finder)を利用すると、必要なプロジェクトに一瞬で移動できるようになります。自分の環境だとこのように動作します。

![s_3896E6C037CE9ED82D9670B9936234A086B7E6CFC631FF6046D68838AB31DB88_1573759326033_ghq-fzf.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14275/4f25d94e-7a3c-0898-deb3-8f53c4d9f11e.gif)


## ghqとは

GitHubなどでホストされているレポジトリをクローンする際に、ディレクトリを指定してリポジトリを管理をシンプルにするためのツールです。

https://github.com/motemen/ghq

```
$ ghq get https://github.com/motemen/ghq
 clone https://github.com/motemen/ghq -> /Users/amachi/src/github.com/motemen/ghq
 git clone https://github.com/motemen/ghq /Users/amachi/src/github.com/motemen/ghq
```

`git clone`の代わりに`ghq get`で実行すると、カレントディレクトリに関係なく、指定されたルールで`git clone`できるのが分かります。

## fzfとは

fzf(Fuzzy Finder)は、インタラクティブでインクリメンタルな検索フィルターツールです。
コマンドラインでfzfコマンドを渡して検索をかけると、それに対応する結果をインタラクティブに返します。簡単に言うと、Googleの検索機能と似たような動きをコマンドライン上で出来ます。

https://github.com/junegunn/fzf



# 導入の準備

macであれば、homebrew経由でインストールできます。

```console
$ brew install ghq fzf
```

インストール後、ghqでどこを起点のディレクトリとするかを、gitの設定ファイルを追加します。


```shell-session
$ git config --global ghq.root $HOME/src

↓
$ less ~/.gitconfig
--- 追加された部分  ---
[ghq]
    root = /Users/amachi/src
--------------------
```

# ghq, fzfを組み合わせる

まず `ghq list` で `ghq root` 以下に存在するプロジェクトの一覧を取得することができます。ここからfzfでインクリメンタルに検索をかけることができます。

またfzfでは、`--preview`オプションで、右半分の画面をプレビューに利用できるので、ここにプロジェクトを選択するのに便利な情報を表示していきます。

これまで試したのは以下の3パターンですが、自分は `3. プロジェクトルートのファイルリスト` が好きです。


### preview : README ファイル

```
ghq list | fzf --preview "bat --color=always --style=header,grid --line-range :80 $(ghq root)/{}/README.*"
```

![](https://paper-attachments.dropbox.com/s_3896E6C037CE9ED82D9670B9936234A086B7E6CFC631FF6046D68838AB31DB88_1573759617666_image.png)


### preview : git log情報

```
ghq list | fzf --preview "git --git-dir $(ghq root)/{}/.git log --date=short --pretty=format:'-%C(yellow)%d%Creset %s %Cgreen(%cd) %C(bold blue)<%an>%Creset' --color"
```

![](https://paper-attachments.dropbox.com/s_3896E6C037CE9ED82D9670B9936234A086B7E6CFC631FF6046D68838AB31DB88_1573759715185_image.png)

### preview : プロジェクトルートのファイルリスト

```
ghq list | fzf --preview "ls -laTp $(ghq root)/{} | tail -n+4 | awk '{print \$9\"/\"\$6\"/\"\$7 \" \" \$10}'"
```

![](https://paper-attachments.dropbox.com/s_3896E6C037CE9ED82D9670B9936234A086B7E6CFC631FF6046D68838AB31DB88_1573759767549_image.png)

# さらに使いやすく : zshのキーバインディング

さらにzshのキーバインディングに登録することで、プロジェクトを選択後にプロジェクト直下に移動できます。
以下の場合、 `Ctrl+]` を押すと、プロジェクト選択画面が開きます。

```zsh
function ghq-fzf() {
  local src=$(ghq list | fzf --preview "ls -laTp $(ghq root)/{} | tail -n+4 | awk '{print \$9\"/\"\$6\"/\"\$7 \" \" \$10}'")
  if [ -n "$src" ]; then
    BUFFER="cd $(ghq root)/$src"
    zle accept-line
  fi
  zle -R -c
}
zle -N ghq-fzf
bindkey '^]' ghq-fzf
```

# まとめ

娘｢パパ、 @Yametaro さんみたいな記事にするの早めに諦めたね｣
ワイ｢あの形式でまとめるって大変なんやな｣

娘｢あと、ノリでつくってた[tomoyamachiで埋めるアドベントカレンダー](https://qiita.com/advent-calendar/2019/tomoyamachi)…｣
娘｢初日から休んだよね…｣
ワイ｢初日が日曜日なのはつらかったな｣

娘｢…｣