vimでfortlsを使う時の導入方法と設定例まとめ

# はじめに
以下の記事を見てからずっと「自分の環境でもLSPを導入したいなぁ」と思っていた。

https://qiita.com/sakamoti/items/fa2040ce127e2c3cbb10

実際に導入すると極めて便利だったが、様々なところから設定を持ってこなければならず大変だったので、今回は上の記事にない設定を追加で示す。
この記事はまとめサイトに近いため各所に参考ページのリンクを貼っている。本記事が読みづらい場合は参考ページの方を当たってほしい。また、記述に誤りがあると思うので、適宜報告をお願いします。

# 導入方法
本記事でも簡単に導入方法を説明する。
## 手順
1. vim-plugを導入する（[参考](https://qiita.com/kouichi_c/items/e19ccf94b8e5ab6ed18e)）
パッケージマネージャのvim-plugを導入する。
    ```terminal
    curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
          https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
    ```
2. .vimrcなどにプラグインの設定を書く
今回は以下のプラグインを導入する。
    - vimでLanguage Serverを使うためのプラグインの[`vim-lsp`](https://github.com/prabirshrestha/vim-lsp)
    - vim-lspの設定を大幅に簡略化するプラグインの[`vim-lsp-settings`](https://github.com/mattn/vim-lsp-settings)
    - vimの自動補完プラグインの[`asycomplete.vim`](https://github.com/prabirshrestha/asyncomplete.vim)
    - asyncomplete.vimをLSPに対応させるプラグインの[`asyncomplete-lsp.vim`](https://github.com/prabirshrestha/asyncomplete-lsp.vim)
    - textEditをいい感じに行ってくれるプラグインである[`vim-vsnip-integ`](https://github.com/hrsh7th/vim-vsnip)
    - `vim-vsnip-integ`の前提プラグインである[スニペットプラグイン](https://zenn.dev/shougo/articles/snippet-plugins-2020)の[`vim-vsnip`](https://github.com/hrsh7th/vim-vsnip)
    ```vim:.vimrc
    call plug#begin('~/.vim/plugged')
    Plug 'prabirshrestha/asyncomplete.vim'
    Plug 'prabirshrestha/asyncomplete-lsp.vim'
    Plug 'prabirshrestha/vim-lsp'
    Plug 'mattn/vim-lsp-settings'
    Plug 'hrsh7th/vsnip'
    Plug 'hrsh7th/vsnip-integ'
    call plug#end()
    ```
    vimを再起動するか`:source ~/.vimrc` したあと、
    ```vim:.vimrc
    :PlugInstall
    ```
    とする。これでvim-plugがプラグインをインストールしてくれる。
3. LspInstallServerする
    filetypeがfortranになっているファイルを開き、以下のコードを入力する。
    ```vim:*.f90
    :LspInstallServer
    ```
    様々な理由でデフォルトの拡張子と異なる拡張子を使っている場合は[以下のように設定する](https://sysfrontier.com/2018/09/13/post-309/)。
    ```vim:~/.vimrc
    autocmd BufNewFile,BufRead *.test set filetype=fortran
    ```
# 諸設定
## vim-lspの設定例
vim-lspについて設定できることは`:help vim-lsp`で確認することができる。ここでは自分が設定した内容を紹介する。先ほどの`.vimrc`の`call plug#end()`の後に記載している。
この設定では、Diagnostics(診断)機能を有効化し、Diagnosticsをステータスラインに表示するようにしている。また、[textEditと呼ばれる補完を支援する機能](https://zenn.dev/matsui54/articles/2021-09-03-ddc-lsp)も有効化している。
```vim:.vimrc
let g:lsp_diagnostics_enabled=1 " diagnosticsの有効化
let g:lsp_diagnostics_echo_cursor=1 " カーソル位置のdiagnosticsをステータスラインに表示する機能の有効化
let g:lsp_text_edit_enabled=1
```
デフォルトの設定では、diagnosticsはvirtual textと呼ばれる仕組みで表示される。diagnosticsの発生源(エラー箇所など)の真下に編集できない仮想の文字列(virtual text)が表示される。ほかにもカーソル位置にdiagnosticsをfloatで表示する機能もある。
diagnosticsがある行はsignと呼ばれる記号で強調表示される。signは行の一番左に、diagnosticsの属性ごとに決まった文字で表示される。これは`g:lsp_diagnostics_signs_enabled`を0にすることで表示をオフにできる。
diagnosticsの属性にはError、Hint、Information、Warningの4種類があり、signを変更するには対応する変数を変更すればよい。例えばerrorなら`g:lsp_diagnostics_sign_error`を変更すればよい。この辺りは`vim-lsp`の`g:lsp_diagnostics_signs_enabled`を見ればわかる。

## asyncomplete.vimの設定例
個人的な好みでtabキーで補完に切り替えている。この設定の書き方は[`asyncomplete.vim`のreadme.md](https://github.com/prabirshrestha/asyncomplete.vim)にある。
```vimscript:.vimrc
inoremap <expr> <Tab>   pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
inoremap <expr> <cr>    pumvisible() ? asyncomplete#close_popup() : "\<cr>"
```
補完のpopupの表示までのdelayは`g:asyncomplete_popup_delay`で変更できる。
また、デフォルトでは`g:asyncomplete_auto_completeopt`により、vimに標準で存在する補完の設定である`completeopt`を`completeopt=menuone,noinsert,noselect`に書き換えている。もし違った挙動にしたいなら、`let g:asyncomplete_auto_completeopt = 0`を追加し、`set completeopt = hoge`とする。その他詳細は`:help asyncomplete.vim`を参照。

## fortlsの設定例
他の言語のLSPを触ったことがないため分からないが、FortranのLSPであるfortlsにはプロジェクトごとに挙動を制御するための設定ファイルを作成することができる。ソースファイルがあるディレクトリに`.fortls`という名前のファイルを作成することでいろいろな設定を行うことができる。設定の一覧は[fortlsの公式サイト](https://fortls.fortran-lang.org/options.html)に書いてある。特に自分が使っている設定は以下のような形になる。
```json:.fortls
{
    "lowercase_intrinsics": true,
    "source_dirs": ["/external/fortran/src","./**"]
}
```
`lowercase_intrinsics`をtrueに指定することで補完が小文字でされるようになる。また、`source_dirs`を指定することで、よそのディレクトリにあるソースコードも適切に参照するようになる。
# おわりに
設定を書いているときはあっちこっち調べて大変だったので参考サイトともにまとめてみた。実際のところ、ヘルプを全部読めば理解できたので、丁寧にヘルプやドキュメントを読めば問題なさそうだが、備忘録として残しておく。
# その他参考文献

https://qiita.com/sakamoti/items/a8479b036571bf7d3cb5