Formatting in vim

2023-09-04

So far, many plugins like vim-autoformat and ALE have been quite helpful in formatting code within Vim. However, it’s still advantageous to learn how to use Vim’s built-in features for text formatting. This is particularly useful when:

This post provides a brief introduction to Vim’s built-in formatting features.

Filter

A filter in vim is a program that accepts text at standard input, changes it in some way, and sends it to standard output.

The easiest way to use filters is to select lines in visual mode and then use :! to call external programs. For instance, to format a JSON string, select the lines and then execute :!jq.

You can find detailed information about filters in :h filter.

Format Program

Typing shell commands repeatedly to use filters can be inconvenient. For example, if you want to use isort and yapf to format your Python code, you’d have to keep typing :!isort - | yapf whenever you need formatting.

In Vim, you can use gq to format selected lines. Vim uses the defined formatprg, which can be set using the following code:

" set formatprg globally
set formatprg=isort\ -\ |\ yapf
let &formatprg='isort - | yapf'

" set formatprg locally
setlocal formatprg=isort\ -\ |\ yapf
let &l:formatprg='isort - | yapf'

For more details, refer to :h gq and :h formatprg.

Format the Whole File

To format the entire file, you can use gggqG or select the entire file in visual mode and then format it. However, using gg and G moves the cursor. You can use CTRL-O to return to the previous position.

If you want to automate the formatting process, you may need to use marks to store the cursor position and jump back to that position after formatting. Here’s the command to achieve this: maHmbgggqG`bzt`a.

ma            " set mark a at cursor position
Hmb           " go to top line in window and set mark b there
gg            " go to first line in file
gqG           " format the whole file
`b            " go back to top line in display
zt            " position the text in the window as before
`a            " go back to saved cursor position

If you want to define functions to automate formatting, you can utilize winrestview() and winsaveview().

Finally, if you want to automatically format your Python code using isort and yapf whenever you save files, you can achieve this with the following code:

autocmd FileType python let &l:formatprg='isort - | yapf'
autocmd BufWritePre *.py normal! maHmbgggqG`bzt`a