2

I have this binding in my .vimrc to trick autointent into actually populating the next line with real characters, so that if I hit enter, leave the line, and click back to it, I can already be at the indentation level of the surrounding code.

"Make autoindent insert actual characters instead of fake characters that go
"away if you move.
inoremap <CR> <CR><space><BS>

However, this leaves lines with trailing whitespace (enough spaces to indent to the level of the surrounding code), like this:

int.main().{
....int.a;
....
....int b;    
}

This lets me click on that blank line, hit i, start typing, and get code at the right indentation level.

Now I'm working on a project where the linter has a Strong Opinion that there should be no trailing spaces, even on blank lines that are, semantically, blank at a particular indentation level.

Can I keep the behavior of being able to click on the tail end of a line and have my cursor be at the right position to insert code on that line, but not fill the file with real trailing spaces? Is there a good way to bind i to automatically jump to the right indentation level when entering insert mode? Or is there another existing keybinding I should be using for "enter insert mode at the indentation level of surrounding code"?

2 Answers 2

2

I'd say the easiest way to insert text at the correct indentation is to use the o or O Normal-mode commands. From :help o:

When 'autoindent' is on, the indent for a new line is obtained from the previous line. When 'smartindent' or 'cindent' is on, the indent for a line is automatically adjusted for C programs.

Of course, these two commands will insert additional lines, so if you really wanted to replace the blank line, you might need to delete it with a separate command, either before or after performing the insertion. But I believe in some cases you might actually want to preserve the blank line, in which case these commands are a perfect fit.


One alternative is for you to keep inserting the extra whitespace into your buffer, but then strip them right before you save the file. You can do so with an autocmd:

autocmd BufWritePre * %s/\s\+$//e

This solution is more limited though, since now you can only jump to a previously indented line until you save the file, after which the whitespace that allowed you to use it will have been stripped.

You could consider a solution using 'virtualedit', which allows you to jump to any column of a line and start inserting at that position, having Vim insert the appropriate indent. But this solution isn't great either, since moving to a line will move you to any column of that line, not necessarily the last one, which is where your original indent ended. Using 'virtualedit' might also interfere with plug-ins or other editing commands you typically use.

So, in short, o and O seem to be the best fit. If you really find yourself often replacing the blank line rather than preserving it, then consider creating a mapping that will first delete it (perhaps checking that it's really empty before doing so) and then using one of the two commands to start editing where the now removed blank line was, but with the proper indentation.

5
  • 2
    C-f in insert mode (along with C-d and C-t) are also handy for this, and cc should also automatically try to get the indent right
    – D. Ben Knoble
    Commented Sep 26, 2020 at 13:32
  • 2
    @Ben Yes good point! I thought I was forgetting something... But <C-f> can be subtle, it only works if using 'cindent' or 'indentexpr', and applies those rules to decide the indent. But for some file types it can't always figure out the correct one, for instance in Python <C-f> doesn't always work (since removing all indent is usually valid, to end the current block...) But yeah I'll incorporate it into the answer. Thanks!
    – filbranden
    Commented Sep 26, 2020 at 16:50
  • Why is o and C-f not doing the same for Python? I understand that the indentation proposed by C-f is valid but the indentation of o is better in my experience. Commented Apr 25, 2022 at 11:11
  • @VivianDeSmedt How is o and <C-f> not doing the same thing in Python? As long as both are listed in 'indentkeys' (which is the default), they should both invoke the same 'indentexpr'. Can you expand on what you're seeing that indicates different behavior between them? (Perhaps post a separate question about it.)
    – filbranden
    Commented Apr 25, 2022 at 12:02
  • 1
    Thanks. I have created a separate question. Commented Apr 25, 2022 at 12:10
1

I have remapped i (and other keys to enter insert mode) to run together with reindent command (:h i_CTRL-F).

noremap i i<c-f>

Note that in order for it to work, cindent (:h 'cindent') has to be enabled. You can turn it on for every filetype with autocmd:

autocmd FileType * set cindent
1
  • 1
    Enabling cindent everywhere is going to cause problems for non C-like languages
    – D. Ben Knoble
    Commented Jun 4, 2023 at 13:57

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.