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?

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

3 Answers 3

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>)
3
  • 2
    That's really clever. I like it!
    – DJMcMayhem
    Commented Jun 23, 2016 at 17:18
  • +1 Almost perfect, but doesn't preserve the column.
    – Anon
    Commented Jun 24, 2016 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
    Commented Jun 24, 2016 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.

5
  • 1
    Workable, but could use some improvement. It places the cursor at the bottom of the page, and is disorienting that way.
    – Anon
    Commented Jun 23, 2016 at 5:03
  • 1
    'a will go back first non-whitespace character of the line, use `a to go to exact position marked
    – Sundeep
    Commented Jun 23, 2016 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
    Commented Jun 23, 2016 at 5:13
  • 1
    Thanks, guys. I agree that using ` is better! Commented Jun 23, 2016 at 6:35
  • 1
    @Akiva: I updated with a comment about using e.g. zz to center the window around the cursor. Commented Jun 23, 2016 at 6:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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