Skip to content

Instantly share code, notes, and snippets.

@romainl
Last active August 21, 2022 17:17
Show Gist options
  • Save romainl/d2ad868afd7520519057475bd8e9db0c to your computer and use it in GitHub Desktop.
Save romainl/d2ad868afd7520519057475bd8e9db0c to your computer and use it in GitHub Desktop.
Formatting without moving
" gq wrapper that:
" - tries its best at keeping the cursor in place
" - tries to handle formatter errors
function! Format(type, ...)
normal! '[v']gq
if v:shell_error > 0
silent undo
redraw
echomsg 'formatprg "' . &formatprg . '" exited with status ' . v:shell_error
endif
call winrestview(w:gqview)
unlet w:gqview
endfunction
nmap <silent> GQ :let w:gqview = winsaveview()<CR>:set opfunc=Format<CR>g@
@mroavi
Copy link

mroavi commented Aug 21, 2022

Hi @romainl. I've been using this script for a long time, and it has turned out to be very useful. Thank you very much for that. There is only one annoyance that haven't been able to fix. I was wondering if you could help me: this function does not work well with the repeat . operator. The error that gets thrown is:

Error detected while processing function Format:
line    7:
E121: Undefined variable: w:gqview

I have tpope's vim-repeat plugin installed. Do you know if there is an easy way to support it?

@romainl
Copy link
Author

romainl commented Aug 21, 2022

Hi @mroavi, the issue happens even without vim-repeat so we can leave it out of the equation.

The simplest thing to do to prevent that message would be to check for the existence of w:gqview before doing anything with it:

function! Format(type, ...)
    normal! '[v']gq
    if v:shell_error > 0
        silent undo
        redraw
        echomsg 'formatprg "' . &formatprg . '" exited with status ' . v:shell_error
    endif
    if exists('w:gqview')
        call winrestview(w:gqview)
        unlet w:gqview
    endif
endfunction

But that w:gqview is actually the most important part of the whole thing: "without moving". Without it, you still get the expected behaviour when using GQ<motion> explicitly but . will leave the cursor at the end of the motion.

Did you try @George-B's snippet?

@mroavi
Copy link

mroavi commented Aug 21, 2022

I looked at it but couldn't understand how to use it. I will leave a comment asking for an example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment