Skip to content

Instantly share code, notes, and snippets.

@bboykov
Last active April 11, 2021 10:24
Show Gist options
  • Save bboykov/f2503c05a6d0d99fe740248a78f775d8 to your computer and use it in GitHub Desktop.
Save bboykov/f2503c05a6d0d99fe740248a78f775d8 to your computer and use it in GitHub Desktop.
TIL: Lint and format in VIM

TIL: Lint and format in VIM

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
@qmacro
Copy link

qmacro commented Apr 11, 2021

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment