ghq管理外でもfzfで快適にcdしたい

# モチベーション
[ghq](https://github.com/x-motemen/ghq)を[fzf](https://github.com/junegunn/fzf)(または[peco](https://github.com/peco/peco)等)と組み合わせる工夫をしている方は多いのではないでしょうか。

私も下記のような設定でghq管理下のリポジトリへの快適な移動を実現していました。

```zsh:.zshrc
function cd_ghq_list() {
  local destination_dir="$(ghq list | fzf)"
  if [ -n "$destination_dir" ]; then
    BUFFER="cd $destination_dir"
    zle accept-line
  fi
  zle clear-screen
}
zle -N cd_ghq_list
bindkey '^]' cd_ghq_list
```
ここでは具体的に`shift+]`で 「`ghq list`コマンドの出力結果をfzfでフィルタリングしcdコマンドに渡す」ことをしています。

この便利設定にハマりきった私は😌『もはやこの方法でしかcdしたくない』と思うようになりました。

普段の私は`~/memo/`に適当なメモを書いて置いています。
また `docker-compose.yml` などたまに使う設定ファイルを `~/Dev/`に置いています。
移動は毎回`cd ~/memo` `cd ~/Dev`しています。これは面倒です。
解決策として「特定ディクレトリへのcdコマンドをエイリアスにしておく」「すべて`ghq/`に置いてgit initしておく」といった方法が考えられますが、エイリアスは覚えておくのが面倒だし、ghq配下はリモートリポジトリと合わせたいのです。

それならばとシェルスクリプトを書くことにしました。

# 『Starting-Directory-List』
シンプルなシェルスクリプトを用意しました。
<a href="https://github.com/jiroshin/Starting-Directory-List"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/jiroshin/Starting-Directory-List.png" width="460px"></a>
ついでに、ちょっとカッコよく『Starting-Directory-List』という名前をつけて`sdl`というコマンドにしました。


## コンセプト
やっていることは管理したいディレクトリ群へのパス一覧を出力することだけです。

管理対象のディレクトリ群は環境変数`SDL_ROOT`で指定したディレクトリ配下におくことを想定しています。

たとえば以下のようなディレクトリ構造があるとします。ここでは`$SDL_ROOT="~/sdl-root/`と設定しています。

```terminal
$ tree ~/sdl-root/
~/sdl-root/
├── category1
│   ├── child-category1-1
│   │   ├── child-category-1-1-1
│   │   │   └── avocado.text
│   │   ├── mango.text
│   │   └── melon.text
│   ├── child-category1-2
│   │   └── cherry.text
│   └── orange.text
└── category2
    ├── apple.text
    └── child-category2-1
        └── peach.text
```

ここでコマンドを実行すると以下のようにディレクトリ群へのパス一覧がが出力がされます。

```
$ sdl
~/sdl-root/category1/
~/sdl-root/category2/
~/sdl-root/category1/child-category1-1/
~/sdl-root/category1/child-category1-2/
~/sdl-root/category2/child-category2-1/
```

出力対象は`SDL_ROOT`直下の`category1` `category2`、さらにその下の`child-category1-1` `child-category1-2` `child-category2-1`までです。
`SDL_ROOT`直下の2階層はネームスペースとして利用すると便利です。

## fzfと組み合わせて快適にcdする
ghq listと同じ要領でfzfと組み合わせます。
一番シンプルな例は以下のようなエイリアスを設定しておくことです。

```zsh:.zshrc(パターン①)
 export SDL_ROOT=$HOME/Dev
 alias dev='cd $(sdl | fzf)'
```

ghqと合わせて使いたい場合は以下のような設定が便利です。

```zsh:.zshrc(パターン②)
function cd_ghq_and_sdl() {
  local destination_dir=$(echo "$(ghq list --full-path) $(sdl)" | fzf)
  if [ -n "$destination_dir" ]; then
    BUFFER="cd $destination_dir"
    zle accept-line
  fi
  zle clear-screen
}
zle -N cd_ghq_and_sdl
bindkey '^]' cd_ghq_and_sdl
```


😔「毎回コマンドを実行したくないなあ」という場合は以下のようにsdlの実行をシェルログイン時だけにしても良いかもしれません。

```zsh:.zprofile(パターン③)
export ENV_CACHE_SDL=$(sdl)
```
```zsh:.zshrc(パターン③)

function cd_ghq_and_sdl() {
  local destination_dir=$(echo "$(ghq list --full-path) $ENV_CACHE_SDL" | fzf)
  if [ -n "$destination_dir" ]; then
    BUFFER="cd $destination_dir"
    zle accept-line
  fi
  zle clear-screen
}
zle -N cd_ghq_and_sdl
bindkey '^]' cd_ghq_and_sdl
```

# まとめ
シェルスクリプトを書くことでghq管理外のディレクトリへも快適にcdできるようになりました。
[![Image from Gyazo](https://i.gyazo.com/3c7621e448d42d3c6bff472beb01fd7f.gif)](https://gyazo.com/3c7621e448d42d3c6bff472beb01fd7f)
とりあえず`shift+]`しておけば大体の目的地へたどり着けるようになり私は満足です😌


---

### お知らせ

この記事を読んで「面白かった」「学びがあった」と思っていただけた方、よろしければ Twitter や facebook、はてなブックマークにてコメントをお願いします！
また [DeNA 公式 Twitter アカウント @DeNAxTech](https://twitter.com/DeNAxTech) では、 Blog記事だけでなく色々な勉強会での登壇資料も発信してます。ぜひフォローして下さい！
<a href="https://twitter.com/DeNAxTech?ref_src=twsrc%5Etfw" class="twitter-follow-button" data-size="large" data-lang="ja" data-show-count="false">Follow @DeNAxTech</a><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>