最小構成の.vimrcの作り方

## はじめに

プラグインの不具合報告をするために、最小構成の `.vimrc` が必要になりました。
私は何をもって「最小構成」なのかわからず、そもそも作り方がわかりませんでした。

vim-jpでいろいろ教えていただいたので、最小構成の `.vimrc` の作り方を紹介します。

## 環境

- OS：macOS Monterey 12.4
- Neovim：v0.6.1

## 「最小構成の.vimrc」とは？

「あるプラグインが動作する最小構成の `.vimrc` 」のことです。
英語では「Minimal vimrc」といいます。

例えば [ddc.vim](https://github.com/Shougo/ddc.vim) の不具合報告をしたい場合、以下が「最小構成の `.vimrc` 」となります。

- ddc.vimのインストール
- 不具合の再現に必要なプラグインのインストール
- 不具合の再現に必要な設定

## 最小構成の.vimrcを作る目的

ある不具合が発生したとき、その原因を切り分けるために最小構成の `.vimrc` を作成します。

不要なプラグインや設定があると、不具合の原因が対象のプラグインにあるのか判断しづらいです。
最小構成の `.vimrc` を作ることで、自分でも原因の切り分けができ、そもそもIssueを立てずに済むこともあります。

プラグイン開発者の負担を減らすために、最小構成の `.vimrc` を作って試せるスキルは必須です。

## 最小構成のルール

最小構成の `.vimrc` を作る際のルールを紹介します。

### プラグインマネージャーを使わない

Dein.vimなどのプラグインマネージャーを使っていると、不具合の原因がプラグインマネージャー側にあることを否定できません。
プラグインマネージャーを使わないことで、プラグインマネージャーが原因であることを完全に排除できます。

### 1つの.vimrcに50行以内で書く

「50行以内」はddc.vimのIssueテンプレートに書いてあることで、他のプラグインはこの限りではありません。
`.vimrc` を1つとも明記されていませんが、50行以内の長さで分割する必要はあまりないため、できる限り1つに収めるのが望ましいです。

### 不要な設定を書かない

なくても不具合の再現に影響しない設定は書いてはいけません。
例えば `set number` は、不具合に無関係なら書きません。

プラグインも再現に不要なものは入れません。

## 最小構成の.vimrcの作り方

最小構成の `.vimrc` の作り方を紹介します。

### プラグインをダウンロードする

必要なプラグインを `git clone` で適当な場所にダウンロードします。
私は `~/temp` フォルダを使うことが多いです。

```shell-session
$ mkdir ~/temp
$ cd ~/temp
$ git clone {プラグインのURL1}
$ git clone {プラグインのURL2}
...
```

今回は以下のプラグインをダウンロードしました。

```shell-session
$ mkdir ~/temp
$ cd ~/temp
$ git clone https://github.com/github/copilot.vim.git
$ git clone https://github.com/vim-denops/denops.vim.git
$ git clone https://github.com/Shougo/ddc.vim.git
$ git clone https://github.com/Shougo/pum.vim.git
$ git clone https://github.com/Shougo/ddc-around.git
$ git clone https://github.com/Shougo/ddc-matcher_head.git
$ git clone https://github.com/Shougo/ddc-sorter_rank.git
```

### .vimrcを作成する

既存の `.vimrc` を壊さないよう、 `.min.vimrc` のような普段は使わない名前で作成します。

```shell-session
$ touch ~/temp/.min.vimrc
```

### .vimrcを編集する

`.min.vimrc` を編集します。

```shell-session
$ nvim ~/temp/.min.vimrc
```

以下のテンプレートに沿って作るといいです。

```vim:.min.vimrc
syntax enable
filetype plugin indent on

" プラグインを読み込む
set rtp+={プラグインのパス1}
set rtp+={プラグインのパス2}
...

" 必要な設定を書く
...
```

`rtp` は `runtimepath` の省略形です。

`+=` はカンマ区切りのリストの後ろに要素を追加します。
`^=` を使っているのも見ますが、こちらはカンマ区切りのリストの __前__ に要素を追加します。
先頭のパスからプラグインを読み込むので、読み込む順番が関係する場合は使い分けましょう。

今回は以下のように作成しました。

```vim:.min.vimrc
syntax enable
filetype plugin indent on

set rtp+=~/temp/copilot.vim
set rtp+=~/temp/denops.vim
set rtp+=~/temp/ddc.vim
set rtp+=~/temp/pum.vim
set rtp+=~/temp/ddc-around
set rtp+=~/temp/ddc-matcher_head
set rtp+=~/temp/ddc-sorter_rank

call ddc#custom#patch_global('sources',
\  ['around']
\)

call ddc#custom#patch_global('sourceOptions', {
\  '_': {
\    'ignoreCase': v:true,
\    'matchers': ['matcher_head'],
\    'sorters': ['sorter_rank'],
\  },
\  'around': {
\    'mark': 'A',
\  },
\})

call ddc#custom#patch_global('autoCompleteEvents', [
\  'InsertEnter', 'TextChangedI', 'TextChangedP',
\  'CmdlineEnter', 'CmdlineChanged',
\])
call ddc#custom#patch_global('completionMenu', 'pum.vim')

call ddc#enable()

let g:copilot_no_maps = v:true
let g:copilot_node_command = '~/.nodebrew/current/bin/node'
let g:copilot_hide_during_completion = 0
imap <script><silent><nowait><expr> <C-g> copilot#Accept()
```

### Vimを実行する

`.min.vimrc` の作成が完了したら、Vimを実行して動作確認します。

```bash
# Vim
$ vim -N -u ~/temp/.min.vimrc

# Neovim
$ nvim -u ~/temp/.min.vimrc
```

Vimの `-N` オプションは `set nocompatible` と同義で、vi互換の動作を無効にします。

不具合が再現することを確認できたら、GitHubのIssueなどで報告します。

### 使ったファイルを削除する

後片付けとして、今回作成した設定ファイルとプラグインを削除します。
私は新規作成した `~/temp` フォルダにすべて格納したので、フォルダを削除するのみです。

```shell-session
$ rm -rf ~/temp
```

## おまけ：プラグインの不具合報告時に気をつけること

最小構成の `.vimrc` とは関係なく、プラグインの不具合報告時に気をつけることを紹介します。

私は [こちらのIssue](https://github.com/Shougo/ddc.vim/issues/98) ですべて踏み抜いてしまいました。
迷惑を掛けてしまったので、本記事は自戒の念を込めて書いています。

### 最新のVimを使う

最新のVim（Neovim）を使うと不具合が解消されていることがあります。
プラグイン開発者は古いバージョンのサポートまで手が回らない可能性もあり、最新を使うのがマナーです。

HomebrewでNeovimをインストールしている場合、 `brew upgrade nvim` を実行します。

```shell-session
$ nvim --version
NVIM v0.6.1
...
$ brew upgrade nvim
...
$ nvim --version
NVIM v0.7.2
...
```

### 手順は誰でも再現できるように書く

手順は誰でも再現できるように書きます。
「これはわかるだろう」といって省略してはいけません。

例えば私は [こちらのIssue](https://github.com/Shougo/ddc.vim/issues/98) で、手順を以下のように書きました。

> 1. Enter insert mode and launch ddc.vim
> 2. Enter two or more characters
> 3. A pum.vim popup appears
> 4. Completion in copilot.vim does not appear

しかしこれだけだと再現できません。
[copilot.vimのREADME](https://github.com/github/copilot.vim/blob/c2e75a3a7519c126c6fdb35984976df9ae13f564/README.md) を見ると、他にも以下が必要です。

- プラグインのダウンロード
- Node.js 16のインストール
- copilot.vimの初期設定

もっというとdenops.vimを使うために [Deno](https://deno.land/) が必要ですが、ddc.vimを使う上では当たり前過ぎるので、省略しても問題ないと思います。
（「省略してはいけません」と矛盾していますね…。できる限り省略しないほうがいいとは思います）

このように書き直すべきです。

```markdown
1. Download plugins  
    ```shell
    $ mkdir ~/temp
    $ cd ~/temp
    $ git clone https://github.com/github/copilot.vim.git
    $ git clone https://github.com/vim-denops/denops.vim.git
    $ git clone https://github.com/Shougo/ddc.vim.git
    $ git clone https://github.com/Shougo/pum.vim.git
    $ git clone https://github.com/Shougo/ddc-around.git
    $ git clone https://github.com/Shougo/ddc-matcher_head.git
    $ git clone https://github.com/Shougo/ddc-sorter_rank.git
    ```
2. Install Node.js version 16  
    ```shell
    $ nodebrew install-binary v16.16.0
    ```
3. Start Neovim and invoke `:Copilot setup`
4. Enter insert mode
5. Enter two or more characters
6. A pum.vim popup appears
7. Completion in copilot.vim does not appear
```

ちなみに今回作成した最小構成の `.vimrc` で試したところ、pum.vimのポップアップが表示されていても、copilot.vimの補完が表示されました。
なので手順7は嘘になります。

やはり最小構成の `.vimrc` を作って試すのは大事です。

### スクリーンショットは最小構成の.vimrcで試したものを貼る

当たり前ですが、スクリーンショットを貼る場合は最小構成の `.vimrc` で試したものを貼ってください。
他の設定で試したスクリーンショットを貼ると嘘になります。

## おまけ：プラグインマネージャーが内部で何をしているか

最小構成の `.vimrc` を見ると予想できますが、プラグインマネージャーは内部で以下を行っていると推測できます。

1. プラグインを `git clone` する
2. `runtimepath` にプラグインのパスを追加する

これがわかると最小構成の `.vimrc` が作りやすくなります。

## おまけ：NeovimはNVIM_APPNAMEを使うのがいい

Neovimは `NVIM_APPNAME` という環境変数が使えます。
既存の環境を汚さず、影響もされにくいため、使うのをオススメします。

使い方の詳細は以下の記事をご参照ください。

https://qiita.com/uhooi/items/b0eb1b11a69735734f26

## おわりに

最小構成の `.vimrc` を作成できました。
これでプラグインの不具合報告をする際に、開発者の負担を減らせます :relaxed: 

## 参考リンク

- https://vim-jp.org/vimdoc-ja/options.html#:set+=
- https://vim-jp.org/vimdoc-ja/options.html#:set^=
- https://vim-jp.org/vimdoc-ja/options.html#'runtimepath'
- [copilot.vim not working · Issue #98 · Shougo/ddc.vim](https://github.com/Shougo/ddc.vim/issues/98)
- [たった3STEPでプラグイン開発者に喜ばれる報告者になれる？！~Vimプラグイン最小構成の作りかた~](https://zenn.dev/hasu_83/articles/how-to-become-good-reporter)
- [Minimal vimrc · lambdalisue/fern.vim Wiki](https://github.com/lambdalisue/fern.vim/wiki/Minimal-vimrc)