もた日記

くだらないことを真面目にやる

Vimメモ : Neovimで開発環境を段階的に構築する(4)LinterとFormatter

多言語パック

vim-polyglotは各種ファイルタイプ用のプラグインをまとめたもので、標準で対応していないような新しいプログラミング言語や使い慣れていないファイルタイプを編集するときに便利。
対応しているファイルタイプの一覧はこのページで確認可能。

Repository スター数
sheerun/vim-polyglot 2819
Plug 'sheerun/vim-polyglot'

例えばcsvファイルを開いてみると、vim-polyglotインストール前では、

f:id:wonder-wall:20190803232244p:plain

のように通常の表示だが、インストール後では、

f:id:wonder-wall:20190803232255p:plain

のように色付き表示になり、:WhatColumnなどのコマンドが使えるようになっている。
これはcsvファイルタイプのプラグインとしてcsv.vimがインストールされているからである。

このようにさまざまなファイルタイプ用のプラグインがインストールできるが、自分の好みとは合わないものもあるのでその場合は以下のように無効にできる。

let g:polyglot_disabled = ['csv']

Linter

ソースコードを解析して警告やエラーを表示するLinterプラグインとしては下記が挙げられる。
syntasticは単独では非同期に実行ができないようなので、最近は非同期実行ができるALE(Asynchronous Lint Engine)が人気。

Repository スター数
vim-syntastic/syntastic 9972
dense-analysis/ale 8073
neomake/neomake 2172
Plug 'dense-analysis/ale'

ALEをインストールしたらまずは:ALEInfoコマンドを実行してみる。
Pythonファイルの場合は以下のように利用可能なLinterと有効になっているLinterが確認できる。

 Current Filetype: python
Available Linters: ['bandit', 'flake8', 'mypy', 'prospector', 'pycodestyle', 'pydocstyle', 'pyflakes', 'pylama', 'pylint', 'pyls', 'pyre', 'vulture']
  Enabled Linters: ['flake8', 'mypy', 'pylint']
 Suggested Fixers:
  'add_blank_lines_for_python_control_statements' - Add blank lines before control statements.
  'autopep8' - Fix PEP8 issues with autopep8.
  'black' - Fix PEP8 issues with black.
  'isort' - Sort Python imports with isort.
  'remove_trailing_lines' - Remove all blank lines at the end of a file.
  'reorder-python-imports' - Sort Python imports with reorder-python-imports.
  'trim_whitespace' - Remove all trailing whitespace characters at the end of every line.
  'yapf' - Fix Python files with yapf.

ALEInfoの最後のほうで、

  Command History:
(executable check - failure) flake8
(executable check - failure) mypy
(executable check - failure) pylint

のようにLinterコマンドの実行に失敗しているので、pipでインストールする(今回はpyenv-virtualenvでneovim3という環境を作成済み)。

pyenv shell neovim3
pip install flake8 mypy pylint

インストールにPythonファイルを開いてみると警告(--)とエラー(>>)が左端に表示されるようになる。

f:id:wonder-wall:20190803234410p:plain

特定のLinterだけを有効にしたい場合はale_lintersで設定し、ale_echo_msg_formatでどのLinterが表示しているかの情報を追加することもできる。
文字上のハイライトが気になる場合はale_set_highlightsでオフにできる。

let g:ale_set_highlights = 0
let g:ale_linters = {'python': ['flake8']}
let g:ale_echo_msg_format = '[%linter%] %s [%severity%]'

f:id:wonder-wall:20190803234424p:plain

また、下記設定を追加することでC-k, C-jで前後の警告、エラーの箇所に移動できるようになる。

nmap <silent> <C-k> <Plug>(ale_previous_wrap)
nmap <silent> <C-j> <Plug>(ale_next_wrap)

なお、Linterの結果(警告の数とエラーの数)をlightline.vimのステータスラインに表示することもできる(lightline.vimだと設定が長くなってしまうが、vim-airlineだともっと簡単に連携できる)。

Plug 'maximbaz/lightline-ale'
let g:lightline = {'colorscheme': 'onedark'}
let g:lightline.component_expand = {
  \   'linter_checking': 'lightline#ale#checking',
  \   'linter_warnings': 'lightline#ale#warnings',
  \   'linter_errors': 'lightline#ale#errors',
  \   'linter_ok': 'lightline#ale#ok',
  \ }
let g:lightline.component_type = {
  \   'linter_checking': 'left',
  \   'linter_warnings': 'warning',
  \   'linter_errors': 'error',
  \   'linter_ok': 'left',
  \ }
let g:lightline.active = {
  \   'left': [
  \     ['mode', 'paste'],
  \     ['readonly', 'filename', 'modified'],
  \     ['linter_checking', 'linter_errors', 'linter_warnings', 'linter_ok'],
  \   ]
  \ }

f:id:wonder-wall:20190803235749p:plain

Formatter

ソースコードを整形してくれるFormatterプラグインとしては下記が挙げられる。
ALEはFormatterとしても使用できるので今回はALEを採用する(ちなみにALEはLanguage Server Protocol Clientなので自動補完や定義ジャンプもできる)。

Repository スター数
dense-analysis/ale 8073
Chiel92/vim-autoformat 1535
prettier/vim-prettier 790
sbdchd/neoformat 700
rhysd/vim-clang-format 637
google/vim-codefmt 649

ALEでソースコードを整形するには:ALEFixコマンドを実行すればよいが、何も設定していない状態だと下記メッセージが表示される。

No fixers have been defined. Try :ALEFixSuggest

Pythonファイルを開いた状態で:ALEFixSuggestコマンドを実行するとFormatterとして利用できるツールが表示される。

Try the following fixers appropriate for the filetype:

'add_blank_lines_for_python_control_statements' - Add blank lines before control statements.
'autopep8' - Fix PEP8 issues with autopep8.
'black' - Fix PEP8 issues with black.
'isort' - Sort Python imports with isort.
'reorder-python-imports' - Sort Python imports with reorder-python-imports.
'yapf' - Fix Python files with yapf.

Try the following generic fixers:

'remove_trailing_lines' - Remove all blank lines at the end of a file.
'trim_whitespace' - Remove all trailing whitespace characters at the end of every line.

See :help ale-fix-configuration

Press q to close this window

今回はblackを使うので下記コマンドでインストール。

pyenv shell neovim3
pip install black

そしてinit.vimにFormatter(Fixer)の設定を追加する(全ファイルタイプ向けの行末の空白と無駄な空行を削除する設定も追加)。

let g:ale_fixers = {
  \   '*': ['remove_trailing_lines', 'trim_whitespace'],
  \   'python': ['black'],
  \ }

以下のコードに対して:ALEFixコマンドを実行すると、

f:id:wonder-wall:20190804000807p:plain

コードが整形される。

f:id:wonder-wall:20190804000822p:plain

なお、ファイル保存時に自動で適用したい場合は下記設定を追加しておけばよい。

let g:ale_fix_on_save = 1

まとめ

今回の~/.config/nvim/init.vim(ALEのlightline.vim連携の設定は省略)。

call plug#begin('~/.vim/plugged')
Plug 'joshdick/onedark.vim'
Plug 'itchyny/lightline.vim'
Plug 'ntpeters/vim-better-whitespace'
Plug 'Yggdroot/indentLine'
Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }
Plug 'majutsushi/tagbar', { 'on': 'TagbarToggle' }
Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }
Plug 'junegunn/fzf.vim'
Plug 'airblade/vim-rooter'
Plug 'tpope/vim-fugitive'
Plug 'airblade/vim-gitgutter'
Plug 'xuyuanp/nerdtree-git-plugin', { 'on': 'NERDTreeToggle' }
Plug 'sheerun/vim-polyglot'
Plug 'dense-analysis/ale'
call plug#end()

set number
set termguicolors
" airblade/vim-gitgutter
set updatetime=100

let g:python_host_prog = $HOME . '/.pyenv/versions/neovim2/bin/python'
let g:python3_host_prog = $HOME . '/.pyenv/versions/neovim3/bin/python'

" joshdick/onedark.vim
colorscheme onedark
" itchyny/lightline.vim
let g:lightline = {'colorscheme': 'onedark'}
" sheerun/vim-polyglot
" let g:polyglot_disabled = ['csv']

" dense-analysis/ale
let g:ale_set_highlights = 0
let g:ale_linters = {'python': ['flake8']}
let g:ale_echo_msg_format = '[%linter%] %s [%severity%]'
let g:ale_fixers = {
  \   '*': ['remove_trailing_lines', 'trim_whitespace'],
  \   'python': ['black'],
  \ }
" let g:ale_fix_on_save = 1
nmap <silent> <C-k> <Plug>(ale_previous_wrap)
nmap <silent> <C-j> <Plug>(ale_next_wrap)

" scrooloose/nerdtree
nmap <C-e> :NERDTreeToggle<CR>
" majutsushi/tagbar
nmap <F8> :TagbarToggle<CR>
" junegunn/fzf.vim
nmap <C-p> :History<CR>

実践Vim 思考のスピードで編集しよう! (アスキー書籍)

実践Vim 思考のスピードで編集しよう! (アスキー書籍)

wonderwall.hatenablog.com

wonderwall.hatenablog.com