設定ファイルの編集などでは、書き方を間違えるとアプリケーションが動作しなくなることがある。そのため、設定ファイルの編集は慎重に行うものだが、急いでいたり、慣れてきたりすると、どうしてもミスを犯す。その度にどこで間違えているのか目を皿のようにして調べることになるのだが、考えてみればこういった作業は自動化すべきものだ。人が必死になってやるようなことではないように思う。
LinuxやmacOSといったUNIX系OSには、設定ファイルやさまざまな種類のテキスト、またはプログラミング言語などの文法をチェックするツールがたくさんある。通常はコマンドを実行してチェック(静的解析)を行うのだが、Vimでは「ALE」というプラグインを使うと、この作業を自動化することができる。編集中に適当なタイミングでALEが自動的にチェックツールを実行し、エラーがあればユーザーに知らせてくれる。とても便利なプラグインだ。今回は、このALEの使い方を説明しよう。
ALEの設定
ALEの設定方法について説明する前に、前回までに作成してきた設定ファイル「~/.vimrc」を次に掲載しておこう。
"dein Scripts-----------------------------
if &compatible
set nocompatible " Be iMproved
endif
" Required:
set runtimepath+=~/.cache/dein/./repos/github.com/Shougo/dein.vim
" Required:
if dein#load_state('~/.cache/dein/.')
call dein#begin('~/.cache/dein/.')
" Let dein manage dein
" Required:
call dein#add('~/.cache/dein/./repos/github.com/Shougo/dein.vim')
" Add or remove your plugins here
call dein#add('junegunn/seoul256.vim')
call dein#add('vim-airline/vim-airline')
call dein#add('vim-airline/vim-airline-themes')
call dein#add('preservim/nerdtree')
call dein#add('tpope/vim-commentary')
call dein#add('tpope/vim-fugitive')
call dein#add('fholgado/minibufexpl.vim')
" Required:
call dein#end()
call dein#save_state()
endif
" Required:
filetype plugin indent on
syntax enable
" If you want to install not installed plugins on startup.
if dein#check_install()
call dein#install()
endif
" seoul256
let g:seoul256_background = 233
colo seoul256
" vim-airline
let g:airline_powerline_fonts = 1
let g:airline_theme = 'molokai'
" NERDTree
" <C-o> open NERDTree
nnoremap <silent> <C-o> :NERDTreeToggle<CR>
" minibufexpl
nnoremap <silent> bn :<C-u>:bnext<CR>
nnoremap <silent> b1 :<C-u>:b1<CR>
nnoremap <silent> b2 :<C-u>:b2<CR>
nnoremap <silent> b3 :<C-u>:b3<CR>
nnoremap <silent> b4 :<C-u>:b4<CR>
nnoremap <silent> b5 :<C-u>:b5<CR>
nnoremap <silent> b6 :<C-u>:b6<CR>
nnoremap <silent> b7 :<C-u>:b7<CR>
nnoremap <silent> b8 :<C-u>:b8<CR>
nnoremap <silent> b9 :<C-u>:b9<CR>
"End dein Scripts-------------------------
set number
syntax on
set whichwrap=b,s,[,],<,>,~,h,l
set cursorline
set incsearch
set hlsearch
set ignorecase
上記の設定ファイルの「call dein#add(‘fholgado/minibufexpl.vim’)」の部分を、次のように編集する。
call dein#add('fholgado/minibufexpl.vim')
call dein#add('dense-analysis/ale')
ALEの設定はこれだけだ。後は、環境と状況に応じて適宜動作してくれる。
静的解析ツールをインストール
ALEはVimで静的解析ツールに仕事を割り当てる、いわば執事のように動いてくれるプラグインであり、静的解析ツールとしては動作しない。そのため、静的解析ツールは別途インストールしておく必要がある。本稿執筆時点において、ALEが対応するプログラミング言語とテキスト形式、ツールは以下の通りだ。
| プログラミング言語 | チェックツール |
|---|---|
| Ada | gcc、gnatpp (保存時にチェック) |
| Ansible | ansible-lint |
| API Blueprint | drafter |
| AsciiDoc | alex (保存時にチェック)、proselint、redpen、textlint、vale、write-good |
| ASM | gcc |
| Awk | gawk |
| Bash | language-server、bash -n、shellcheck、shfmt |
| Bats | shellcheck |
| BibTeX | bibclean |
| Bourne Shell | sh -n、shellcheck、shfmt |
| C | ccls、clang、clangd、clang-format、clangtidy (保存時にチェック)、cppcheck、cpplint、cquery、flawfinder、gcc、uncrustify |
| C# | csc (保存時にチェック)、mcs、mcsc (保存時にチェック)、uncrustify |
| C++ | ccls、clang、clangcheck (保存時にチェック)、clangd、clang-format、clangtidy (保存時にチェック)、clazy (保存時にチェック)、cppcheck、cpplint (保存時にチェック)、cquery、flawfinder、gcc、uncrustify |
| Chef | cookstyle、foodcritic |
| Clojure | clj-kondo、joker |
| CloudFormation | cfn-python-lint |
| CMake | cmake-format、cmakelint |
| CoffeeScript | coffee、coffeelint |
| Crystal | ameba (保存時にチェック)、crystal (保存時にチェック) |
| CSS | csslint、fecs、prettier、stylelint |
| Cucumber | cucumber |
| CUDA | nvcc |
| Cypher | cypher-lint |
| Cython | cython |
| D | dfmt、dls、dmd、uncrustify |
| Dafny | dafny |
| Dart | dartanalyzer (保存時にチェック)、dartfmt、language_server |
| Dockerfile | dockerfile_lint、hadolint |
| Elixir | credo、dialyxir (保存時にチェック)、dogma (保存時にチェック)、elixir-ls (デフォルト無効)、mix (保存時にチェック(デフォルト無効)) |
| Elm | elm-format、elm-ls、elm-make |
| Erb | erb、erubi、erubis、ruumba |
| Erlang | erlc、SyntaxErl |
| Fish | fish -n |
| Fortran | gcc、language_server |
| Fountain | proselint |
| FusionScript | fusion-lint |
| Git Commit Messages | gitlint |
| GLSL | glslang、glslls |
| Go | bingo (デフォルト無効)、go build (保存時にチェック(デフォルト無効))、gofmt、goimports (デフォルト無効)、golangci-lint (保存時にチェック(デフォルト無効))、golangserver (デフォルト無効)、golint、gometalinter (保存時にチェック(デフォルト無効))、go mod (保存時にチェック(デフォルト無効))、gopls (デフォルト無効)、gosimple (保存時にチェック(デフォルト無効))、gotype (保存時にチェック(デフォルト無効))、go vet (保存時にチェック)、revive (保存時にチェック(デフォルト無効))、staticcheck (保存時にチェック(デフォルト無効)) |
| GraphQL | eslint、gqlint、prettier |
| Hack | hack、hackfmt、hhast (デフォルト無効) |
| Haml | haml-lint |
| Handlebars | ember-template-lint |
| Haskell | brittany、cabal-ghc、floskell、ghc、ghc-mod、hdevtools、hfmt、hie、hindent、hlint、stack-build (保存時にチェック)、stack-ghc、stylish-haskell |
| HCL | terraform-fmt |
| HTML | alex (保存時にチェック)、fecs、html-beautify、HTMLHint、prettier、proselint、tidy、write-good |
| Idris | idris |
| Ink | ink-language-server |
| ISPC | ispc (保存時にチェック) |
| Java | checkstyle、eclipselsp、google-java-format、javac、javalsp、PMD、uncrustify |
| JavaScript | eslint、fecs、flow、jscs、jshint、prettier、prettier-eslint、prettier-standard、standard、tsserver、xo |
| JSON | fixjson、jq、jsonlint、prettier |
| Julia | languageserver |
| Kotlin | kotlinc (保存時にチェック)、ktlint (保存時にチェック)、languageserver |
| LaTeX | alex (保存時にチェック)、chktex、lacheck、proselint、redpen、texlab、textlint、vale、write-good、 |
| Less | lessc、prettier、stylelint |
| LLVM | llc |
| Lua | luac、luacheck |
| alex (保存時にチェック)、languagetool (保存時にチェック)、proselint、vale | |
| Make | checkmake |
| Markdown | alex (保存時にチェック)、languagetool (保存時にチェック)、markdownlint (保存時にチェック)、mdl、prettier、proselint、redpen、remark-lint、textlint、vale、write-good |
| MATLAB | mlint |
| Mercury | mmc (保存時にチェック) |
| NASM | nasm (保存時にチェック) |
| Nim | nim check (保存時にチェック)、nimlsp、nimpretty |
| nix | nix-instantiate、nixpkgs-fmt |
| nroff | alex (保存時にチェック)、proselint、write-good |
| Objective-C | ccls、clang、clangd、uncrustify |
| Objective-C++ | clang、clangd、uncrustify |
| OCaml | merlin、ocamlformat、ocp-indent、ols |
| Pawn | uncrustify |
| Perl | perl -c (デフォルト無効)、perl-critic、perltidy |
| Perl6 | perl6 -c (デフォルト無効) |
| PHP | langserver、phan see :help ale-php-phan to instructions、phpcbf、phpcs、php-cs-fixer、php -l、phpmd、phpstan、psalm (保存時にチェック) |
| PO | alex (保存時にチェック)、msgfmt、proselint、write-good |
| Pod | alex (保存時にチェック)、proselint、write-good |
| Pony | ponyc |
| PowerShell | powershell (保存時にチェック)、psscriptanalyzer (保存時にチェック) |
| Prolog | swipl |
| proto | protoc-gen-lint |
| Pug | pug-lint |
| Puppet | languageserver、puppet、puppet-lint |
| PureScript | purescript-language-server、purty |
| Python | autopep8、bandit (デフォルト無効)、black、flake8、isort、mypy、prospector (デフォルト無効)、pycodestyle (デフォルト無効)、pydocstyle (デフォルト無効)、pyflakes、pylama (保存時にチェック)、pylint (保存時にチェック)、pyls (デフォルト無効)、pyre (デフォルト無効)、reorder-python-imports、vulture (保存時にチェック(デフォルト無効))、yapf |
| QML | qmlfmt、qmllint |
| R | lintr、styler |
| Racket | raco |
| ReasonML | merlin、ols、reason-language-server、refmt |
| reStructuredText | alex (保存時にチェック)、proselint、redpen、rstcheck、textlint、vale、write-good |
| Re:VIEW | redpen |
| RPM spec | rpmlint (デフォルト無効) |
| Ruby | brakeman (保存時にチェック)、debride (保存時にチェック)、rails_best_practices (保存時にチェック)、reek、rubocop、ruby、rufo、solargraph、sorbet、standardrb |
| Rust | cargo (保存時にチェック)、rls (デフォルト無効)、rust-analyzer (デフォルト無効)、rustc (デフォルト無効)、rustfmt |
| Sass | sass-lint、stylelint |
| Scala | fsc、metals、sbtserver、scalac、scalafmt、scalastyle |
| SCSS | prettier、sass-lint、scss-lint、stylelint |
| Slim | slim-lint |
| SML | smlnj |
| Solidity | solc、solhint、solium |
| SQL | pgformatter、sqlfmt、sqlformat、sqlint |
| Stylus | stylelint |
| SugarSS | stylelint |
| Swift | sourcekit-lsp、swiftformat、swiftlint |
| Tcl | nagelfar (保存時にチェック) |
| Terraform | fmt、tflint |
| Texinfo | alex (保存時にチェック)、proselint、write-good |
| Text | alex (保存時にチェック(デフォルト無効))、languagetool (保存時にチェック)、proselint (デフォルト無効)、redpen (デフォルト無効)、textlint (デフォルト無効)、vale (デフォルト無効)、write-good (デフォルト無効) |
| Thrift | thrif |
| TypeScript | eslint、fecs、prettier、standard、tslint、tsserver、typecheck |
| VALA | uncrustify |
| Verilog | iverilog、verilator、vlog、xvlog |
| VHDL | ghdl、vcom、xvhdl |
| Vim | vimls、vint |
| Vim help | alex (保存時にチェック(デフォルト無効))、proselint (デフォルト無効)、write-good (デフォルト無効) |
| Vue | prettier、vls |
| XHTML | alex (保存時にチェック)、proselint、write-good |
| XML | xmllint |
| YAML | prettier、swaglint、yamllint |
| YANG | yang-lsp |
上記テーブルはGitHubに公開されている「ALE Supported Languages and Tools」のデータを表にしたものだ。最新の対応状況はこちらのページの内容を参照してほしい。
例えば、JSONファイルの編集をするなら「fixjson」「jq」「jsonlint」「prettier」をインストールしておけばよい。どれか1つでもよいし、全部インストールしてもかまわない。ALEでは個々のツールは排他的ではなく補完的に利用されるので、インストールしておけばそれだけ包括的にチェックが行われることになる。
また、XMLファイルの静的解析を行いたいのであれば、「xmllint」がインストールされていればよいことになる。Ubuntu 18.04 LTSで調べると、xmllintは「libxml2-utils」というパッケージに含まれていることがわかる。
パッケージをインストールしておけば、後はALEがこのツールを使って適当なタイミングで静的解析を行い、問題があれば報告してくれる。
ALEの動作サンプル
実際にALEが動作するところを見てみよう。次のスクリーンショットは、誤ったフォーマットのXMLファイルをVimで編集しているものだ。しかし、xmllintがインストールされていないため、ユーザーには何の報告も行われていない。
ここでxmllintをインストールしてから同じ操作を行うと、次のようにxmllintの動作結果がVimの画面に表示されるようになる。問題がある行に自動的に通知が入り、さらにVim下部にエラー内容を示すメッセージが表示されるようになる。
動作させているとわかると思うが、この機能はかなり便利だ。シンタックスエラーのような単純なミスをミスした段階で知ることができる。編集するファイルがあまりにも巨大だったり、PCのスペックが相当に低いと処理の重さを感じることがあるかもしれないが、その場合は機能を無効化するなり、設定を変更するなりしてチェックの頻度を調整すればよい。
今回の成果物
今回のプラグイン設定を追加した設定ファイルは以下の通りだ。
"dein Scripts
if &compatible
set nocompatible " Be iMproved
endif
" Required:
set runtimepath+=~/.cache/dein/./repos/github.com/Shougo/dein.vim
" Required:
if dein#load_state('~/.cache/dein/.')
call dein#begin('~/.cache/dein/.')
" Let dein manage dein
" Required:
call dein#add('~/.cache/dein/./repos/github.com/Shougo/dein.vim')
" Add or remove your plugins here
call dein#add('junegunn/seoul256.vim')
call dein#add('vim-airline/vim-airline')
call dein#add('vim-airline/vim-airline-themes')
call dein#add('preservim/nerdtree')
call dein#add('tpope/vim-commentary')
call dein#add('tpope/vim-fugitive')
call dein#add('fholgado/minibufexpl.vim')
call dein#add('dense-analysis/ale')
" Required:
call dein#end()
call dein#save_state()
endif
" Required:
filetype plugin indent on
syntax enable
" If you want to install not installed plugins on startup.
if dein#check_install()
call dein#install()
endif
" seoul256
let g:seoul256_background = 233
colo seoul256
" vim-airline
let g:airline_powerline_fonts = 1
let g:airline_theme = 'molokai'
" NERDTree
" <C-o> open NERDTree
nnoremap <silent> <C-o> :NERDTreeToggle<CR>
" minibufexpl
nnoremap <silent> bn :<C-u>:bnext<CR>
nnoremap <silent> b1 :<C-u>:b1<CR>
nnoremap <silent> b2 :<C-u>:b2<CR>
nnoremap <silent> b3 :<C-u>:b3<CR>
nnoremap <silent> b4 :<C-u>:b4<CR>
nnoremap <silent> b5 :<C-u>:b5<CR>
nnoremap <silent> b6 :<C-u>:b6<CR>
nnoremap <silent> b7 :<C-u>:b7<CR>
nnoremap <silent> b8 :<C-u>:b8<CR>
nnoremap <silent> b9 :<C-u>:b9<CR>
"End dein Scripts
set number
syntax on
set whichwrap=b,s,[,],<,>,~,h,l
set cursorline
set incsearch
set hlsearch
set ignorecase


