Today I learned how to setup linters and formaters for various languages in VIM.
First we need to install the ALE (Asynchronous Lint Engine) plugin. This
plugin provides a common platform for different linters in VIM. I install it
using vim-plug plugin manager, but one can install it manually or
with another plugin manager without much hassle. The example in this TIL use
vim-plug. Put Plug 'w0rp/ale'
in your vimrc setup and call vim-plug to
install it (:PlugInstall
).
Now that ALE is installed to manage linters we need to install the linters. I choose to use shellcheck for linting and shfmt to format bash scripts.
brew install shellcheck
brew install shfmt
NOTE: The example is with brew, but there are many installation options for all major OS platforms.
ALE is configured to enable supported linters found on the system without any additional configuration. So this should be enough for shellcheck, but I prefer to have it written down in the configuration file. The formater or fixer as it is called in ALE on the other hand must be declared in the configuration.
Plug 'w0rp/ale'
let g:ale_linters = {
\ 'sh': ['shellcheck'] ,
\ }
let g:ale_fixers = {
\ 'sh': ['shfmt'],
\}
The configuration above is enough to get the linter and formater working, but
some additional tweaks are need if we don't like the defaults. By default shfmt
will align and replace the indentation with tabs, I prefer two spaces. To make
it use spaces we need to pass -i 2
argument to shfmt.
let g:ale_sh_shfmt_options='-i 2' " Indent with N spaces
In addition it would be nice to have some key bindings to call commonly used ALE commands.
" Move between warnings or errors with ALENext and ALEPrevious
nmap <silent> <leader>aj :ALENext<cr>
nmap <silent> <leader>ak :ALEPrevious<cr>
" ALEFix will format the file in place
nmap <silent> <leader>af :ALEFix<cr>
ALEFix command will automatically format the bash script. To configure ALEFix
to execute on save put let g:ale_fix_on_save = 1
in the configuration.
With this setup we can be sure that there is consistency across all scripts and catch potential issues while coding. Here is the final bash setup.
Plug 'w0rp/ale'
let g:ale_linters = {
\ 'sh': ['shellcheck'] ,
\ }
let g:ale_fixers = {
\ 'sh': ['shfmt'],
\}
let g:ale_sh_shfmt_options='-i 2'
nmap <silent> <leader>aj :ALENext<cr>
nmap <silent> <leader>ak :ALEPrevious<cr>
nmap <silent> <leader>af :ALEFix<cr>
let g:ale_fix_on_save = 1
Now that ALE is configured we can easily add more linters and languages to the setup, like Python for example:
sudo -H pip install flake8 isort yapf
Plug 'w0rp/ale'
let g:ale_linters = {
\ 'sh': ['shellcheck'] ,
\ 'python': ['flake8'] ,
\ }
let g:ale_fixers = {
\ 'sh': ['shfmt'],
\ 'python': ['isort', 'yapf'],
\}
let g:ale_sh_shfmt_options='-i 2'
nmap <silent> <leader>aj :ALENext<cr>
nmap <silent> <leader>ak :ALEPrevious<cr>
nmap <silent> <leader>af :ALEFix<cr>
let g:ale_fix_on_save = 1
Great stuff! I think I'd just about figured things out for myself, but wasn't sure, and your post really helped because it confirmed my thinking. Thank you.