Automatically run mix format on save in NeoVim.
keywords
vim elixir2022-06-21
There Are a few challenges when it comes to automatically mix format
-ing your files on save in Vim.
:w
, or :wq
. Formatting after :wq
gave me trouble in the past and would fail formatting. I think this is because mix format
was called via the editor, but then the editor process exited, so it was getting terminated (I think). This simple config seems to do a pretty good job at solving these challenges:
First, in $nvim_config_dir/ftplugin/elixir.vim
(and eelixir.vim
) I have an autocommand set up. It uses BufWritePost
because the work is going to happen async. I think BufWritePre
should be OK too.
augroup formatting
autocmd! * <buffer>
autocmd BufWritePost <buffer> :call elixir#formatting#mix_format()
augroup END
Then in $nvim_config_dir/autoload/elixir/formatting.vim
I have these two functions.
function elixir#formatting#on_mix_format_exit(id, data, event)
if a:data > 0
echom "⚠ mix format "
else
execute 'edit'
echom "✓ mix format "
endif
endfunction
function elixir#formatting#mix_format()
let l:filepath = expand('%:p')
let l:mixformatcmd = 'nohup mix format '
\. l:filepath
\. ' 2>&1 > /dev/null'
call jobstart(
\['bash', '-c', mixformatcmd],
\{'detach': 1,
\ 'on_exit': function(
\ 'elixir#formatting#on_mix_format_exit')})
endfunction
Since the mix_format
function spawns a job to run the actual mix format
program, it happens in the background so you can continue typing.
Instead of doing just mix format path/to/file
, I am using nohup
, which allows mix format
to keep going even if the parent process dies.
I also set the detach
option on the job so that it will not be killed when nvim exits.
When the job finishes, on_mix_format_exit
is called and checks if mix format
ran with errors or not. execute edit
reloads the buffer contents, which has the formatted version at this point, and it does it without changing where the cursor is at.