4

I was reading that the way to indent in vim is a gg=G sequence. This however loses my cursor position.

How can I indent my file without losing my cursor position?

  • 1
    Did you tried :normal! gg=G? – SibiCoder Jun 23 '16 at 4:09
  • 2
    @SibiCoder Yes. Doesn't work. – Akiva Jun 23 '16 at 4:10
8

You could define a custom command using :help winsaveview():

command! -range=% Equal let b:wv = winsaveview() | silent execute <line1> . ',' . <line2> . 'normal! ==' | call winrestview(b:wv)

:Equal             like gg=G
:12,23Equal        like :12,23normal! ==
v{motion}:Equal    like v{motion}=
5

Expanding on Karl Yngve Lervåg's answer:

maHmbgg=G`bzt`a

Explanation:

ma   - Set mark 'a'
H    - Jump to the top of the window
mb   - Set mark 'b'
gg=G - Indent from the first line to the last
`b   - Jump to mark 'b'
zt   - Scroll the cursor line to the top of the window
`a   - Jump to mark 'a'

This will preserve your scroll position after indenting.

If you want to preserve the relative cursor position after the cursor line has been indented, you have to update the new cursor position after indenting. The following script expands on romainl's answer:

function! s:reindent(line1, line2)
  let view = winsaveview()
  let text = getline('.')
  execute a:line1.','.a:line2.'normal! =='
  let view.col -= strchars(text) - strchars(getline(view.lnum))
  call winrestview(view)
endfunction


command! -range=% Reindent call s:reindent(<line1>, <line2>)
  • 2
    That's really clever. I like it! – DJMcMayhem Jun 23 '16 at 17:18
  • +1 Almost perfect, but doesn't preserve the column. – Akiva Jun 24 '16 at 13:35
  • @Akiva The column should be restored unless the cursor line was re-indented. If you really really want to restore the relative position of the cursor after indenting, you would have to store the cursor position (like in romainl's answer) and the current line's text then adjust the cursor after indenting. I'll update the answer with a script that can do that. – Tommy A Jun 24 '16 at 14:00
3

You should use a mark, e.g.:

magg=G`a

Here ma will set the a mark at the current position, then gg=G indents the file, and `a will jump to the mark.

In order to put the cursor at the center of the screen afterwards, you could finish this off with zz. See :h scroll-cursor for more info and for similar scroll mappings.

  • 1
    Workable, but could use some improvement. It places the cursor at the bottom of the page, and is disorienting that way. – Akiva Jun 23 '16 at 5:03
  • 1
    'a will go back first non-whitespace character of the line, use `a to go to exact position marked – Sundeep Jun 23 '16 at 5:09
  • 4
    @Akiva to preserve the cursor and scroll position: maHmbgg=G`bzt`a. It sets two marks, a for the current cursor position, and b for the top of the buffer. After indenting, it jumps the b mark and uses zt to scroll it to the top. Then jump to the a mark. – Tommy A Jun 23 '16 at 5:13
  • 1
    Thanks, guys. I agree that using ` is better! – Karl Yngve Lervåg Jun 23 '16 at 6:35
  • 1
    @Akiva: I updated with a comment about using e.g. zz to center the window around the cursor. – Karl Yngve Lervåg Jun 23 '16 at 6:40

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.