pre-commit + vim integration
β’ 297 words β’ 2 min β’ updated
Is it possible to transparently invoke pre-commit in the background upon saving in vim (:w)?
Initially I found this Stack Overflow question, but it had no answer.
Digging a bit deeper I realized that I could do it with an autocmd:
autocmd BufWritePost * execute '! if [ -e $(git root)/.pre-commit-config.yaml >/dev/null 2>&1 ]; then pre-commit run; fi'That trashes the screen upon completion. This can be resolved by invoking
:redraw! afterwards:
autocmd BufWritePost * execute '! if [ -e $(git root)/.pre-commit-config.yaml >/dev/null 2>&1 ]; then pre-commit run; fi' | redraw!We can be less intrusive by prepending silent! so that, even if the command
fails, it doesn’t get in the way:
autocmd BufWritePost * silent! execute '! if [ -e $(git root)/.pre-commit-config.yaml >/dev/null 2>&1 ]; then pre-commit run; fi' | redraw!And last but not least, ideally pre-commit should run only on the file
associated with the current buffer. Pass --files to pre-commit with the %
argument:
autocmd BufWritePost * silent! execute '! if [ -e $(git root)/.pre-commit-config.yaml >/dev/null 2>&1 ]; then pre-commit run --files %; fi' | redraw!This approach works as intended.
There’s a brief period in which you can see pre-commit running in the
background. It’s arguable whether that’s a feature or a bug.
Ah, and git root is simply an alias in my ~/.gitconfig:
root = rev-parse --show-toplevelWhenever there are pre-commit violations (e.g. end-of-file-fixer) they are
applied inplace. There’s no need to run :e!.
This is bare, but I am happy.
Perhaps the only missing piece is to extend it in such a way it’s only executed in the repositories I opt into.
If this turns out to be too intrusive, I am thinking to switch to using a vim
keymap e.g. <leader>p instead of an autocmd.