OmniSharp-Vim と fzf を連携させる メンバーのリスト表示編

以前、[OmniSharp-Vim と fzf を連携させる](https://qiita.com/lx-sasabo/items/b2226eb3594a2acaeafb) という記事を書きました。
この記事を書いたときには `OmniSharpFindUsages` （使っている場所を調べるコマンド） の場合について書いたのですが、 `OmniSharpFindMembers` （開いたファイルのメンバー一覧を表示するコマンド）の場合について書きたいと思います。

## きっかけ

VisualStudio だとメンバー一覧が表示できて良いなーと思っていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/e1a81d1d-032b-ad8f-8ca8-4dfab7db1956.png)
Omnisharp-Vim にもきっと同様の機能があるだろうと思って調べるとありました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/d15632c1-cae1-4a90-9df4-e55d745fe7aa.png)

https://github.com/OmniSharp/omnisharp-vim/blob/f9c5d3e3375e8b5688a4506e813cb21bdc7329b1/doc/omnisharp-vim.txt#L569-L574

`OmniSharpFindMembers` というコマンドで実行できるようです。

## OmniSharpFindMembers を使ってみる

実行してみました。Quickfix リストが表示されて開いているファイルのメンバー一覧が取れました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/5fdaa77d-ac7b-2a6b-6dc4-71986252b41f.png)

Quickfix リストで選択を行うと定義場所へジャンプします。便利です。
ソースコードを見たところ `-` は private,  `+` は public, `&` は internal `|` は protected を示しているようでした。

https://github.com/OmniSharp/omnisharp-vim/blob/f9c5d3e3375e8b5688a4506e813cb21bdc7329b1/autoload/OmniSharp/actions/members.vim#L80-L85


となると、この結果を fzf に渡して `-` で検索すれば private なメンバーだけを参照できそうです。

## OmniSharpFindMembers の結果を fzf に渡す

つぎに`OmniSharpFindMembers` の結果を fzf に渡したいです。マニュアルを読むと `let g:OmniSharp_selector_findmembers = 'fzf'` を設定すれば良いことが分かりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/4c739558-fdca-46cf-6860-03b547b94a6f.png)

https://github.com/OmniSharp/omnisharp-vim/blob/f9c5d3e3375e8b5688a4506e813cb21bdc7329b1/doc/omnisharp-vim.txt#L420-L422

設定すると自分の画面ではこうなりました。
画面右側は bat で定義場所を bat でプレビューできるように設定しているのですが、引数エラーでコケているようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/01c2435f-3d30-745b-df54-a609fd78a65c.png)

前回の [OmniSharp-Vim と fzf を連携させる](https://qiita.com/lx-sasabo/items/b2226eb3594a2acaeafb) で設定した OmniSharpFindUsages の画面と見比べてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/4a2816cf-5797-2561-a546-b67d9f784ace.png)

見比べてみると、fzf に渡されるパスの部分が違うことに気づきました。
`OmniSharpFindUsages` のときは Neovim を起動した場所からの相対パスになっていました。
`OmniSharpFindMembers` のときはフルパスになっていました。

```
OmniSharpFindUsages のとき : ClassAnalyzer\Program.cs: 49 col 31     if (!analyzer.HasClass(targetClassName))
OmniSharpFindMembers のとき: C:\Users\sasab\works\ClassAnalyzer\src\ClassAnalyzer\CSharpCodeAnalyzer.cs: 9 col 11     namesp..
```

[OmniSharp-Vim と fzf を連携させる](https://qiita.com/lx-sasabo/items/b2226eb3594a2acaeafb) では下記のように fzf へ値を渡していました。

```vim
let g:OmniSharp_fzf_options = {
  \'options': [
    \'--delimiter', ':| col ',
    \'--preview', 'bat --color=always {1} --highlight-line {2}',
    \'--preview-window', '+{2}+3/2'
  \]
\}
```

この設定の場合、区切り文字の `:` か ` col` で区切られた1番目の要素が bat の引数（開きたいファイルのパス）で指定されることになります。
なので、`C:` で始まるフルパスが渡されると 1番目の要素は `C` になってしまい、うまくファイルを開けていなかったようです。


## 解決策（無理やり）

とりあえず、使えればいいやの精神で無理やり解決することにしました。
fzf のオプションは `OmniSharp_fzf_options` で指定しています。
このオプションの指定を `OmniSharpFindMembers` のときは別の変数を参照するように、 OmniSharp-Vim のソースコードを修正します。

![Monosnap omnisharp-vim_autoload_fzf_OmniSharp.vim .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/18c47b04-67a1-a39d-87c9-f5569e9675b6.png)

https://github.com/OmniSharp/omnisharp-vim/blob/f9c5d3e3375e8b5688a4506e813cb21bdc7329b1/autoload/fzf/OmniSharp.vim#L102-L113

ソースコードの 108行目を修正しました。
`OmniSharpFindMembers` のときは `OmniSharp_find_members_fzf_options' という値からオプション設定を読み込むことにします。

```vim
  " let fzf_options = copy(get(g:, 'OmniSharp_fzf_options', { 'down': '40%' }))
  let fzf_options = copy(get(g:, 'OmniSharp_find_members_fzf_options', { 'down': '40%' }))
```

続いて init.vim 側を設定します。
bat に渡す引数を変えています。
また、`OmniSharpFindMembers` のときは、プレビュー画面は上側にあるほうが見やすかったのでプレビュー画面の出現する位置を `up` で指定しています。

```vim
let g:OmniSharp_selector_ui = 'fzf'
let g:OmniSharp_selector_findusages = 'fzf'
let g:OmniSharp_selector_findmembers = 'fzf'
let g:OmniSharp_fzf_options = {
  \'options': [
    \'--delimiter', ':| col ',
    \'--preview', 'bat --color=always {1} --highlight-line {2}',
    \'--preview-window', '+{2}+3/2'
  \]
\}
let g:OmniSharp_find_members_fzf_options = {
  \'options': [
    \'--delimiter', ':| col ',
    \'--preview', 'bat --color=always {2} --highlight-line {3}',
    \'--preview-window', 'up,+{3}+3/2'
  \]
\}
```

設定後の画面です。ちゃんとプレビュー画面が見えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/ab06a3f7-a671-7fd0-fd5f-5ae71ef1fc00.png)

プライベートなメンバーに絞り込んだ様子です。`-` で絞り込んでいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960076/db4e6d2f-5d38-3154-7ae1-21b0e0b9584c.png)

おかげ様で使いやすくなりました！