I've set formatprg in my vimrc to use the par text formatter when I type gq.

setg formatprg=par\ -w90

When I'm in a buffer whose textwidth has been set (e.g. the gitcommit filetype sets textwidth=72), I'd like to use that number rather than 90.

Instead of hard-coding different values in a bunch of ftplugin files, I'd like to compute the number dynamically upon usage.

I took a look at formatexpr, but if I set a formatexpr it would also be called whenever I enter characters beyond the textwidth line length, and I don't think I'd want to call out to an external process that frequently.

The only other solutions I can think of are writing a wrapper around gq (which I imagine would get complex if I want to support operating-pending mode correctly) and adding an autocmd that listens for the Filetype event and sets formatprg appropriately. That last solution seems the most reasonable, actually.

I'm curious if there's another option I'm overlooking?


That's when the OptionSet event comes in handy, but it doesn't work when it's triggered on startup so you need the VimEnter event too.

If your workflow includes several files opened in different windows/buffers, with different textwidth values, you can include the BufEnter event to adjust formatprg (a global option) according to the textwidth of the current window/buffer.

You could put the following code at the end of your vimrc file:

setg formatprg=par\ -w90

function! UpdateFormatprg()
   let &g:formatprg = substitute( &g:formatprg , '\d\+$', &textwidth , "" )

augroup UpdateFormatprgGroup
   autocmd VimEnter,BufEnter * call UpdateFormatprg()
   autocmd OptionSet textwidth call UpdateFormatprg()
augroup END 

You could add this in ftplugin/gitcommit.vim:

" setlocal textwidth=72
let &l:formatprg = 'par -w' . &l:textwidth

Or using an auto command, just make sure &textwidth is correctly set before the FileType event:

augroup FormatPrg
    autocmd FileType gitcommit let &l:formatprg = 'par -w' . &l:textwidth
augroup END
  • I ended up writing a function that returns &tw > 0 ? &tw : 90 and adding an autocmd that executes setl formatprg=par\ -w'.GetTextWidth()
    – ivan
    Aug 22 '17 at 11:41
  • Be careful, set and setlocal expect a string, thus not evaluating variables. You want the alternative form let &l: (or let & for global variables). For more details, check :h set-args and :h let-&.
    – LEI
    Aug 22 '17 at 11:59
  • The actual autocmd is autocmd FileType * execute 'setl formatprg=par\ -w'.GetTextWidth()
    – ivan
    Aug 22 '17 at 17:38
  • I am curious, is there a reason for using execute 'setlocal ...' over let &l:...?
    – LEI
    Aug 22 '17 at 18:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.