How do I use a Vimscript function to control how the gq operator formats text?
Answer
:set formatexpr=MyFormat()
Explanation
The formatexpr option lets you replace Vim's built-in line-breaking logic for the gq operator with your own Vimscript expression or function. This gives complete programmatic control over how text is reformatted — unlike formatprg, which delegates to an external program via a shell pipe, formatexpr runs inside Vim and has access to all of Vim's internal state including buffer variables, line content, and cursor position.
How it works
When you invoke gq{motion} (or gqq for the current line), Vim checks:
- If
formatexpris set, it calls that expression. The expression must format linesv:lnumthroughv:lnum + v:count - 1in place and return 0 on success (non-zero falls back to internal formatting) - If
formatprgis set, it pipes the lines through the external program - Otherwise, Vim applies its built-in algorithm respecting
textwidthandformatoptions
Key variables available inside the expression:
v:lnum— first line to formatv:count— number of lines to formatv:char— character that triggered formatting (when called fromformatoptions+=a)
Example
A minimal formatexpr that delegates to an external LSP formatter (Neovim):
set formatexpr=v:lua.vim.lsp.formatexpr()
Or a custom Vimscript function that right-justifies text to column 80:
function! RightJustify() abort
for lnum in range(v:lnum, v:lnum + v:count - 1)
let line = getline(lnum)
call setline(lnum, printf('%80s', trim(line)))
endfor
return 0
endfunction
set formatexpr=RightJustify()
Tips
- Set
formatexprper filetype usingautocmd FileTypeto apply different formatters for different languages formatexprtakes precedence overformatprgwhen both are set- In Neovim, the built-in LSP client sets
formatexprautomatically when attaching to a language server that supports range formatting — this is howgqbecomes a proper code formatter - Use
:set formatexpr=(empty) to clear it and fall back toformatprgor Vim's internal formatter