Neovim on Macの初期設定

# 内容
Neovim on Macの初期設定について、覚え書き。

# まとめ
- Neovimを入れたら、`~/.zshrc`にNeovimのホームフォルダ設定等を書き込む。
```zsh
export XDG_CONFIG_HOME=~/.config
export PATH=$PATH:/path/to/Neovim/bin
alias vi="nvim"
alias vim="nvim"
```
- `Terminal`から、プラグイン管理ソフトの[vim-plugin](https://github.com/junegunn/vim-plug)を入れる。
```zsh
sh -c 'curl -fLo "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/autoload/plug.vim --create-dirs \
       https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
```
- `$XDG_CONFIG_HOME/nvim/init.vim`に設定を書き込む。下記の要領でgithubのリポジトリ名を記載し、`:PlugInstall`をNeovim上で打つことでインストールできる[^1]。
    - Neovimを再起動するか、Neovimで`$XDG_CONFIG_HOME/nvim/init.vim`を開いた状態で`:source %`を打つことで、設定が反映される。
    - アンインストールするには、該当行を削除して`:PlugClean`。
    - なお、設定ファイル上でのコメントアウトには`"`が使われている。
```vimscript
call plug#begin()
Plug 'projekt0n/github-nvim-theme'
Plug 'luk400/vim-jukit'
call plug#end()
```
- プラグインの中には、上述の`:PlugInstall`だけでは有効にならないものも存在する。そういった際には、該当プラグインのgithubを読んで初期設定を行う必要がある。一方、とりあえずの最初の一歩として、下記を試すのもアリ。
    - `:プラグイン名`をNeovim上で叩いてみる。
    - `$XDG_CONFIG_HOME/nvim/init.vim`に、下記の設定を書いてみる。
        - なお本設定に限らず、github上で（Neovimの）プラグインのコンフィグ例を探していると、`$XDG_CONFIG_HOME/nvim/init.vim`に直書きするものと、`lua <<EOF`〜`EOF`で挟み込む必要があるものが混在しているので注意。
        - 挟み込む必要があるものかどうかは、やっている内に分かってくる（luaで書かれているかどうかの違い。luaのコメントアウトは`--`）。
```vimscript
lua << EOF
require'プラグイン名'.setup{}
EOF
```
- 好みにもよるが、下記設定も`$XDG_CONFIG_HOME/nvim/init.vim`に書き込んでおく。
```vimscript
set tabstop=4
set autoindent
set smartindent
set shiftwidth=4
set number
set expandtab
syntax on
set title
set clipboard+=unnamedplus
set noswapfile
set nobackup
set nowritebackup
set showmatch
set autochdir
```

# プラグイン選択
Neovimのプラグインは、Visual Studio Codeの拡張機能と比較すると、下記が異なる。

1. ある機能（例えば自動補完）について多くの場合はデファクト・スタンダードが存在せず、自分でどれかを選ぶ必要がある。
2. プラグイン開発は個人主導・小規模であることが多く、主導者が開発から離れると、プラグインのメンテナンスがされなくなる（その代わり、尖った機能提供をするプラグインも多い）。
3. 導入・設定が複雑（慣れるまでは、プラグインをインストールしても動かせない）。

人が多く集まるプラグインの方が、A) 開発が継続される可能性が高く、B) 導入・設定についてもある程度情報が出てくる。そのため、基本的には単に人気のプラグインを探せば良い。
探し方として、**同機能のプラグインをある程度見つけて、github上でのスター数と最終更新日を比較する**ことが有効（とは言え良いプラグインでも、単純な機能についてはメンテナンスの必要がなく、最終更新日が古い場合もある。）。

2022年11月26日現在の、プラグイン選択の例を下記に示す。

**■ プラグイン管理**
|プラグイン名|スター数|最終更新日|
|-|-|-|
|[vim-plug](https://github.com/junegunn/vim-plug)|29.9k|9/13|
|[dein.vim](https://github.com/Shougo/dein.vim)|3.3k|2 days ago|
|[packer.vim](https://github.com/wbthomason/packer.nvim)|4.6k|9/10|

**■ 自動補完**
|プラグイン名|スター数|最終更新日|
|-|-|-|
|[coc](https://github.com/neoclide/coc.nvim)|21.7k|6 hours ago|
|[nvim-cmp](https://github.com/hrsh7th/nvim-cmp)|4.3k|yesterday|
|[coq](https://github.com/ms-jpq/coq_nvim)|2.8k|2 hours ago|
|[ddc](https://github.com/Shougo/ddc.vim)|509|2 days ago|

# その他
- Visual Studio Codeの快適性を再現しようとすると、自動補完機能は必須なのだが、Neovimだと少しハードルが高い。
    - 上述のcoc/cmp/coq/ddcは全て試したが、[coc](https://github.com/neoclide/coc.nvim)が一番お手軽。~~速度の問題で、個人的にはcoqを利用中。~~ coqだとインラインのエラー表示がダブる等の不具合が多いので、cocを高速に使えないか模索中。
        - coqでは`set signcolumn=no`の設定を入れておかないと、ノーマル／インサートモードの移行時に画面がガクガクして死ぬ。
    - cocに次いで[nvim-cmp](https://github.com/hrsh7th/nvim-cmp)、[coq](https://github.com/ms-jpq/coq_nvim)、[ddc](https://github.com/Shougo/ddc.vim)の順で簡単。coqは設定時に管理者権限が必要で怖い。ddcは、プラグイン以外にも少しインストールするものがある。
        - この3つでは、追加でLSP（=Language Server Protocol）なるものを入れる必要がある。難しいことはなく、下記を`init.vim`に書くだけ（python向けLSPのpyrightを使う場合）。
```vimscript
call plug#begin()
Plug 'neovim/nvim-lspconfig'
call plug#end()
lua << EOF
require('lspconfig')['pyright'].setup{
    capabilities = capabilities,
}
EOF
```
- Pythonのmatplotlibの出力をインラインで見たいと思ったとき、選択肢には[vim-jukit](https://github.com/luk400/vim-jukit)くらいしかなさそう。
    - iTerm2の設定で、"General > tmux > Automatially bury the tmux client session after connecting"にチェックを付けておく必要あり。
    - `init.vim`に下記の設定が必要。
        - 初期設定なら、`\os`で起動、`\<Space>`でファイル実行、`<Enter>`で行・選択範囲実行。終了は`\od`。
    - `~/.tmux.conf`に下記の設定が必要かも。
```init.vim
call plug#begin()
Plug 'luk400/vim-jukit'
call plug#end()
let g:jukit_terminal = 'tmux'
let g:jukit_inline_plotting = 1
```
```~/.tmux.conf
set-option -sg escape-time 10
set-option -g focus-events on
```
- Markdown（数式あり）の編集をリアルタイムで見たいと思ったとき、[markdown-preview.nvim](https://github.com/iamcco/markdown-preview.nvim)が良さげ。
    - `:MarkdownPreview`コマンドで、既定のブラウザでプレビュー画面が立ち上がる。
- Pythonのf文字列を適切にハイライトするいは、`$XDG_CONFIG_HOME/nvim/after/syntax/python.vim`に[下記の設定](https://gist.github.com/phelipetls/8726d6cd68e66ad6b83586ae53f3b3d8)が必要。
    - **ファイル名が`python.vim`である必要がある点に注意。**
    - `init.vim`には何も書かなくて良い。
```vimscript
syn match pythonEscape +{{+ contained containedin=pythonfString,pythonfDocstring
syn match pythonEscape +}}+ contained containedin=pythonfString,pythonfDocstring

syn region pythonfString matchgroup=pythonQuotes
      \ start=+[fF]\@1<=\z(['"]\)+ end="\z1"
      \ contains=@Spell,pythonEscape,pythonInterpolation
syn region pythonfDocstring matchgroup=pythonQuotes
      \ start=+[fF]\@1<=\z('''\|"""\)+ end="\z1" keepend
      \ contains=@Spell,pythonEscape,pythonSpaceError,pythonInterpolation,pythonDoctest

syn region pythonInterpolation contained
      \ matchgroup=SpecialChar
      \ start=+{{\@!+ end=+}}\@!+ skip=+{{+ keepend
      \ contains=ALLBUT,pythonDecoratorName,pythonDecorator,pythonFunction,pythonDoctestValue,pythonDoctest

syn match pythonStringModifier /:\(.[<^=>]\)\?[-+ ]\?#\?0\?[0-9]*[_,]\?\(\.[0-9]*\)\?[bcdeEfFgGnosxX%]\?/ contained containedin=pythonInterpolation
syn match pythonStringModifier /![sra]/ contained containedin=pythonInterpolation
syn match pythonStringModifier /\zs *= *\ze[}:!]/ contained containedin=pythonInterpolation

hi link pythonfString String
hi link pythonfDocstring String
hi link pythonStringModifier PreProc
```
- Vimの配色については、個別で色を指定するのではなく、カラースキームを扱うのが普通。
    - 設定項目が多くて大変なため。
    - `init.vim`に下記を書き込む（永続）か、`:colorscheme スキーム名（タブで候補の確認可）`コマンドを打つ（一時的）かで設定可能。
    - ターミナル側の配色の影響を受けることもあるので、そちら（例えばiTerm2側）の設定確認も必要。
```vimscript
colorscheme スキーム名
```
- 一応、[「Vimでカーソル下のハイライト情報を表示する」](https://qiita.com/pasela/items/903bb9f5ac1b9b17af2c)のような方法で、色情報の確認は可能。

# 感想
- Neovimについて、日本語の情報がそこまでネットに落ちていない。
    - 何なら、英語の情報もそこまで落ちていない。
    - 昔ながらの「ドキュメント読め」「Readme読め」「ソース読め」のハードコア。
- Emacsも好きなのだが、こちらはNeovimに比べて活気が感じられない。
    - Visual Studio CodeやNeovimならできる「エラー内容のインライン表示」等は、Emacsだと（多分）できない。
- Visual Studio Codeと異なり、「完全に」マウスレスで操作を完了させられる点がVimの利点。
- Emacsと異なり、マウスレスでも高速にカーソル移動できるのがVimの利点（Evilはあるけど）。あとNeovimだと、Emacsよりも何かとモダン。
- そういった意味で、プラグイン（これはどのエディタにもある）を漁るよりも、Vim基本操作によるカーソル高速移動を極めることの方が大事。
    - 最近感動したコマンドは下記。
        - `set relativenumber`: 行数表記が、通常の表記から相対表記になる。`k/j`がメチャ強になる必須設定。なぜこの設定が界隈であまり強調されていないのかが疑問。
        - `:%y`: ファイル全体をコピーできる。
        - `gv`: さっき選んだビジュアル範囲を、再度選択できる。
        - `aw/iw`: 文字単位で選択できる。例えば`wor|d`（`|`はカーソル位置）の状態で`daw`と叩くと、`word`全体が消える。 
    - 特段の目的もなくプラグインを漁りたくなるのは、試験前に漫画を読んだり部屋を掃除したくなる心理と一緒。
- [easymotion](https://github.com/easymotion/vim-easymotion)や[hop](https://github.com/phaazon/hop.nvim/blob/master/doc/hop.txt)等のカーソル移動系のプラグインも試したけど、下記の理由からVim基本操作の方が好き。
    1. 移動系プラグインだとヒント（ラベル）を表示させて確認するまで移動ができないので、常に表示されている行数や文字を利用したVim基本操作（`{number}j/k`／`f{char}`）と比べて、1ステップ遅れる、
    2. 移動系プラグインで表示されるヒント（ラベル）がテキストに重なって表示されるため、見にくい。
- なので時間ができたときに、下記のようなプラグインを作りたい。
    1. **現在行の下に**、常に列数のルーラーが表示される。
        - ルーラーの表示は`A1234567890B01234567890C1234567890...`
    2. `f{char}{number}`でその列にカーソルが移動する。
    3. `F{number}{char}{number}`で、`{number}`行目`{char}{number}`列目にジャンプする。
    4. 例えば4行目にカーソルがある場合、下記のように4列目と5列目の間に列数ルーラーが表示される。
        - `(`にジャンプしたければ、`fb7`とタイプする。
```
 1 from random import randint
 2
 3 def dice():
 4     return randint(1, 6)
   A1234567890B1234567890C1
 5
 6 for i in range(10):
 7     print(dice())
```

[^1]: `call plug#begin()`のカッコ内に、プラグイン保存先のディレクトリを指定することもできる。