ghq listをfzf vimから選択するコマンドを書いてみた

この記事は [Vim Advent Calendar 2018 その2](https://qiita.com/advent-calendar/2018/vim2) 12日目の記事です。
その2と名のつく通りこのアドベントカレンダーの表には[その1](https://qiita.com/advent-calendar/2018/vim)があり、そちらでは [@deresmos](https://qiita.com/deresmos)さんが記事を書いていらっしゃると思います。

先日11日目の記事は [@yasuo-ozu](https://qiita.com/yasuo-ozu)さんによる [[VIM] まだインデントで消耗してるの? 〜スペースインデントでもタブインデントでもない新しいインデント手法〜 - Qiita](https://qiita.com/yasuo-ozu/items/cc0d3cc80d5e49a89189)です。
Vimその1の記事は[@aiya000](https://qiita.com/aiya000)さんによる[fキーをnoremap可能にするfmap.vim - Qiita](https://qiita.com/aiya000/items/365b98a3c550c98cf286)です。

## 概要

最近fzfを使うようになって.vimrcの設定をいじり始めたのですが、fzf.vimからghqのコマンドを叩くスクリプトの参考例を探してみていて意外とありませんでした。
ちょうどいいブログ記事のネタになりそうだと思いましたので、fzfを使ったvimのコマンドを作成する例を紹介します。

fzf.vimについては他にも先行するまとまった記事がありますので、本記事では実際にコマンドを書くところを中心にやってみたいと思います。

* [候補絞り込み型インターフェースを提供するプラグインについて - koturnの日記](http://koturn.hatenablog.com/entry/2015/12/16/000000)
* [fzfを活用してTerminalの作業効率を高める - Qiita](https://qiita.com/kamykn/items/aa9920f07487559c0c7e)

## fzf
[fzf](https://github.com/junegunn/fzf)はfuzzy検索が可能なgolang製のコマンドラインツールです。
類似ツールでは[peco](https://github.com/peco/peco), [percol](https://github.com/mooz/percol)といったものがあります。
vimとの連携が可能で一旦インストールしておけばvimでもすぐ使えるようになります。
dein.vimでプラグインを管理しているのであれば、

``` vim
call dein#add('junegunn/fzf', { 'build': './install --all', 'merged': 0 })
call dein#add('junegunn/fzf.vim', { 'depends': 'fzf' })
```

のように書くと実行することができます。

[![Image from Gyazo](https://i.gyazo.com/e2c377c4c3bdca25d540ce1660c2881f.gif)](https://gyazo.com/e2c377c4c3bdca25d540ce1660c2881f)

## fzf.vim
[fzf.vim](https://github.com/junegunn/fzf.vim) はVim scriptにあまり慣れていない人でもすぐ使えるようにfzfを使ったコマンドのプリセットを一揃い提供するプラグインです。
汎用的なCommand名が着くのが嫌う場合は、`g:fzf_command_prefix` を設定することでprefixを設定できます。
例: `let g:fzf_command_prefix = 'Fzf'`と設定すると `:Files` のコマンド名が `:FzfFiles` になる

## Vim scriptのチュートリアル

[Examples (vim) · junegunn/fzf Wiki](https://github.com/junegunn/fzf/wiki/Examples-(vim))
公式wikiにあるチュートリアルを一部紹介します。

fzfのVim連携は `fzf#run`関数が中核となります。この関数はディクショナリ型の単一の引数をとります。ここでは少なくとも `sink` オプションを指示する必要があります。

``` vim
:call fzf#run({'sink': 'e'})
```

この引数に `source` オプションがない場合、カレントディレクトリにあるファイルを一覧するのにfindコマンドを使います。
一覧の中からひとつファイルを選択するとそのファイルをsinkで指定した `:e` を使って開きます。
findコマンドを使う代わりに、`source` を指示することで任意のシェルコマンドを実行することができます。
記事の例はgit管理下にあるファイル一覧を表示することです:

``` vim
call fzf#run({'source': 'git ls-files', 'sink': 'e'})
```

なお、この操作はfzf.vimでは`:GFiles` としてプリセットされています。

[![Image from Gyazo](https://i.gyazo.com/c728c675e2b303855d2b8f1a01fd5367.gif)](https://gyazo.com/c728c675e2b303855d2b8f1a01fd5367)

他にもオプションは多くあって、tmuxと連携してウインドウを分割して右ペインに一覧を表示するだとか、選択をひとつではなく二個以上選択するなど色々できます。
興味があればチュートリアルの方にまとまっていますのでご参照ください。

## ghqの一覧をとって任意のリポジトリディレクトリにcdする

さて、上記の内容からコマンドを自作してみます。
* 単純に一覧のタネとなるsourceに `ghq list` を、sinkにcdを指定します。

``` vim
call fzf#run(fzf#wrap({'source': 'ghq list --full-path', 'sink': 'cd' }))
```

今回は `:Fq<CR>` で実行できるようにしたいため、以下のように書くと完成です。

``` vim
command! -nargs=0 Fq call fzf#run({
\ 'source': 'ghq list --full-path',
\ 'sink': 'cd'
\ })
```

これで、動くようになりました。

[![Image from Gyazo](https://i.gyazo.com/ffbdbaa601aa3beb3876c258c8eee920.gif)](https://gyazo.com/ffbdbaa601aa3beb3876c258c8eee920)

## その他参考記事

この記事には直接関係しませんが、fzf.vimに関する記事を探した際に見かけたサイトをリンクします。

* [fzf（fuzzy finder）の便利な使い方をREADME, Wikiを読んで学ぶ - もた日記](https://wonderwall.hatenablog.com/entry/2017/10/06/063000)
* [15年目のVim | POSTD](https://postd.cc/vim3/)
* [fzf.vimがいい感じ あとvim-plugも - Qiita](https://qiita.com/acro5piano/items/074f33553dd169ef8099)

## 終わり

以上、fzfを利用して `ghq list` の中から選択するコマンドの書き方を紹介しました。
明日の記事の担当は、 Vimその2 [@chesscommands](https://qiita.com/chesscommands)さん、その1 [@daisuzu](https://qiita.com/daisuzu)さんです。