poiとfzf（peco）でプロジェクトに爆速で移動できるっぽい〜

## ことのはじまり

普段のお仕事でも趣味でも、僕は頻繁にプロジェクトを `cd` コマンドで移動します。Androidのプロジェクトは `~/AndroidProjects` に置いてますし、Goのプロジェクトは `~/go/src` に置いてあります。
業務はWindowsで、パスの長さ回避のためにCドライブ直下に顧客ごとにディレクトリを切ったりしてその中にプロジェクトがたくさんあったりします。OSSコードを読んだりプルリクエストを送るために別の人のプロジェクトをcloneすることもたくさんあります。

そんなこんなでいろいろなディレクトリでソースコードを管理していると移動が大変面倒なわけです。

そこで[ghq](https://github.com/motemen/ghq)と言うツールがあります。
ghqはGo製のコマンドツールで、リモートリポジトリを一元管理するためのツールです（ネーミングセンスやばくない？
ghqを使うことによって所定のディレクトリでプロジェクトを管理するようになり、またfzfやpecoなどのツールと連携することで爆速で移動もできるようになると言うものです。

僕もこれを最初使おうと思ったのですが。。。
ghqはあくまでリポジトリの管理が主目的のツール。僕はプロジェクトのディレクトリ配置は今のままが気に入っています。Androidは `~/AndroidProjects` におきたいし、WindowsではCドライブ直下におきたいこともあります。そしてGoはやっぱり `~/go/src` で管理したいです。

そうなると欲しいのはプロジェクトの一元管理ではなく、たくさんあるプロジェクトに一発で「ぽい」っと移動できるGo製のツール「[poi](https://github.com/yasukotelin/poi)」でした。

## What is poi

poiは `ghq list` に着想を得たツールです。poiは `poi.yml` ファイルで指定されたディレクトリを探索して、Gitプロジェクトのフルパスを列挙します。ただそれだけです。

```yml
# projects - you can specify the directories had projects managed by git.
projects:
  - ~/AndroidStudioProjects
  - ~/IdeaProjects
  - ~/source
  - ~/go/src
```

このような感じのymlファイルを `~/.config/poi.yml` として配置します。そして `poi` コマンドをどこでもいいので実行すると、こんな感じで指定ディレクトリ配下にあるGitプロジェクトが一瞬で全部出てきます。ファンタスティック！

![poi.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166629/204d597a-f8fb-c5aa-125a-e2a8b65d0a6e.gif)

しかしこれだけだと何にもできません。poiはぽいっとプロジェクトを出力してくれるだけです。そこで、[fzf](https://github.com/junegunn/fzf)や[peco](https://github.com/peco/peco)などのfuzzy-finderツールを使います。

fzfなどのfuzzy-finderツールは、標準出力で受け取ったリストを対話的に絞り込みできるツールです。これにpoiから取得したプロジェクトを渡してあげて、cdで移動すれば爆速で移動できるようになります。

```bash
cd "$(poi | fzf)"
```

![poi-fzf.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166629/99d79a5f-74c1-d9f8-50bc-77f358004565.gif)

もういっちょ。aliasにも登録してあげましょう！

```bash
alias po = 'cd "$(poi | fzf)"'
```

![po.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166629/9dd97a32-2cbf-7516-6a66-71eaef5c6272.gif)

**はやい**
もはやポイッとする間も無く「ぽ」でプロジェクトに移動できちゃいます。

## poiを使ってみよう！

<a href="https://github.com/yasukotelin/poi"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/yasukotelin/poi.png" width="460px"></a>

poiのインストールはとっても簡単。最新のGo言語をインストールしてgo getしたらもう使えます。

```bash
go get -u github.com/yasukotelin/poi
```

これでインストールは完了です。

`poi` と打つともう動くはずです。まだ設定ファイルがない場合は、見つからないよエラーが出ると思います。下の手順で設定ファイルを配置してください。
`poi` コマンドがないよエラーが発生した場合は、Go getしたバイナリへのパスが通ってないと思います。`~/go/bin` をパスに通して実行してみてください。

poiは `poi.yml` ファイルで指定されたディレクトリを対象にGitプロジェクトを探索します。まず、 `~/.config/poi/poi.yml` を作成します。Windowsの場合も同じ場所です（`%HOME%\.config\poi\poi.yml`）。

記載の仕方はこんな感じ。とってもシンプル。

```yml
# projects
projects:
  - ~/AndroidStudioProjects
  - ~/IdeaProjects
  - ~/source
  - ~/go/src

# others
others:
  - ~/.config/nvim
  - ~/.config/poi
```

`projects:` に好きなだけディレクトリを指定してください。とは言え探索量が増えると困るけど。指定されたディレクトリをルートとしてGitプロジェクトを探索します。ちなみに、 `.git` ディレクトリを見つけてもさらに配下を見るので、サブプロジェクトも見つかる。はずです。

さらに、Gitのプロジェクトじゃないし、なんなら何のプロジェクトでもないんだけど、よく頻繁に移動するディレクトリにもpoiっと移動したいという場合むけに `others:` があります。
例えば、 `~/.config/nvim` ディレクトリはNeoVimの設定ディレクトリでよくアクセスしますし、他にもブログ記事を管理しているディレクトリとか、直接飛びたいディレクトリって結構あります。そう言うものをここに指定してください。プロジェクトに混ぜてそれらもフルパスを返してくれます。なので、 poi+fzfでプロジェクト以外のところにも飛んで行けるようになりますよ🛩

## Windowsでも動くよ！

poi自体はWindowsのコマンドプロンプトでもPowerShellでも、git bashでもしっかりと動きます。

肝心のfzfやpecoとの連携の部分ですが、powershellの場合は `cd "$(poi | fzf)"` もバッチリです。コマンドプロンプトの場合はfzfの結果をcdに渡すやり方が分からず。。あと、git bashでの連携のやり方もちょっと分からなかったので知っている方いましたら教えてください🙇‍♂️

また、Macだと高速に動作するのですが、Windowsだとかなり遅い感じになってしまいました。
それでは意味がないので色々調べてると、ghqへの速度改善のプルリクエストのツイートをたまたま発見しました。探索の関数をGo言語標準のものではなくライブラリを使用するように変更するもので、poiもこちらの[saracen/walker](https://github.com/saracen/walker)を使用するように変更した結果、Macでは一瞬、Windowsでもなかなかに速くなりました。一瞬とは行かないまでも、快適だと思います。

`poi.yml` ファイルにフルパスで指定する場合は、バックスラッシュをエスケープして指定してください。
~から相対パスの場合は/指定でも大丈夫です。

```yml
# projects
projects:
  - ~/AndroidStudioProjects
  - ~/IdeaProjects
  - ~/source
  - ~/go/src
  # Cドライブから指定はこんな感じ
  - C:\\Work

# others
others:
  - ~/.config/nvim
  - ~/.config/poi
```

## 終わりに

poi自体は非常にシンプルなコマンドです。ただ標準出力するだけなので、移動だけじゃなくて直接エディタで開いたり、色々できるかもしれません。
また、僕は探索処理のど素人です。おそらく非常にあれな実装になっていると思います。より一瞬で移動できるように改善していきたいと思ってます😇

では、良きpoiライフを！