47

I like the smart-indent feature of Vim, it allows me to create well-indented code blocks.

I regularly copy/paste code in to buffers, but that code is often poorly formatted.

What would be ideal is to "re-process" the code through the smart-indent system.

Is such a thing possible?

For example, how would you 'fix' the following code (an extract from a larger block - I don't want to fix each line manually...) :

    else 
                {
                        m[c] = 5;
                Finished = true;
std::cout<<"(ID,R,E)"<<"-->"<<"("<<g[c]<<","<<r[c]<<","<<E1 <<")"<< std::endl;
std::cout << "\n"<<"finish-->" << r[c] << "\t" <<"E1-->"<< E1 <<"\n" ;
                }
        }
2
  • 2
    Are you talking about pasting code that was originally poorly indented or properly indented code that changes when you paste it into Vim?
    – jamessan
    Commented Feb 4, 2015 at 3:39
  • The pasted code is poorly indented to start with. Let me include an example....
    – rolfl
    Commented Feb 4, 2015 at 3:43

7 Answers 7

55

I do this one of two ways.

Indent adjusted paste

First, if the code in the buffer is formatted, but at a different level of indentation, I use ]p instead of p, which pastes the code as is, but with the indentation shifted such that the first line pasted is the same depth as the line I'm on.

E.G. source copied to buffer

while (1) {
    dostuff();
}

E.G. result of pasting it with ]p

int myfunc() {
    int i = 5; /* Cursor on this line before paste */
    while (1) {
        dostuff();
    }
 }

vim puts the while at the same indentation level as int i. This is quick, but only works if the copied code is properly indented within itself.

Reformat after paste

The = operator in vim reformats the code based on the configured formatting rules. For short snippets of pasting, I'll go into visual mode with v, select the lines I just pasted and then press = to reformat them.

For larger pastes, I take advantage of the fact that the cursor goes to the first pasted line, and that vim says something like "84 more lines". I can then enter 84== to reflow those 84 lines (of course, substitute 84 with the number of lines you actually paste).

References

:help ]p for adjusted indent paste

:help = covers ={motion}, [count]== and {Visual}= for filtering through custom or builtin indent rules

5
  • 6
    You can nicely select the code you pasted in visual mode using `[v`]
    – craigp
    Commented Feb 4, 2015 at 7:04
  • 1
    @Badger Just to clarify, is that backtick-bracket-v-backtick-bracket?
    – phatskat
    Commented Feb 4, 2015 at 13:31
  • 1
    yup.. the textarea freaked out about the backticks, so I couldn't put it in a code block :P
    – craigp
    Commented Feb 4, 2015 at 14:41
  • The = operator in vim reformats the code based on the configured formatting rules I'd give +100 if I could. I could have saved days.
    – Wossname
    Commented Jun 25, 2017 at 14:37
  • 1
    I use <control+R>" to paste, so that I don't have to leave insert mode. What is ]p equivalent for <control+R>" ?
    – user9120
    Commented Jul 12, 2017 at 9:56
20

The = command can be used to reindent.

Like most normal mode commands it can be applied to a motion, so you can reindent the just pasted code with =']. This reindents from the current cursor position to the '] mark, which is the last line of the paste.

= can also be used from visual mode.

Another useful command is ]p, which pastes at the same indent level as the current line. This can help paste properly indented text, although at a different indent depth, in accordance with the surrounding text.

8

Using =ap (mnemonic is 'format a paragraph') will have vim attempt to autoformat the current paragraph.

If you want to pay careful attention to what you're potentially reformatting, you might find it saner and quicker to use vap to visually select the current paragraph (giving you a visual indication of what is being reformatted), followed by =. I find this useful in files where I know that vim will reformat incorrectly, and I don't want to mistakenly incorrectly format other lines.

1
  • Good when writing but not useful whe you code. The code recognized as paragraph is the text between two blank row, then in some case you select too much.
    – Antonio
    Commented Jul 22, 2021 at 8:32
5

To reindent a file already in the buffer, use gg=G: See Fix Indentation

For reindenting a portion of a file, various bounds can be applied to the = filter (for example, == fixes just the current line).

To keep the indentation unchanged when pasting text you can :set paste before you paste text into the buffer, this will prevent vim from auto-indenting text that you've just pasted. After pasting stuff, you can go back using set :nopaste when you're done. See vimdoc here.

If you find yourself pasting stuff frequently, it'd be a good idea to use this tip on the VimWiki and setup a key for "paste-mode" toggle by adding these lines to your .vimrc:

nnoremap <F2> :set invpaste paste?<CR>
set pastetoggle=<F2>
set showmode

You can then hit <F2> to toggle paste-mode. vim will show the words "PASTE" in the status line when paste mode is active.

4
  • 2
    This question is not about pasting code with indentation, it's about fixing poorly indented code.
    – rolfl
    Commented Feb 4, 2015 at 3:46
  • 4
    I didn't see the comment you posted. However, you can still use gg=G to reindent the whole file.
    – Bhargav
    Commented Feb 4, 2015 at 3:48
  • @rolfl That's where I usually start in such cases: gg=G, then look at the parts that vim got wrong.
    – muru
    Commented Feb 4, 2015 at 4:08
  • If you'd like more control (or reduce the repeated hassle) consider adding an auto-command to invoke a code-formatting tool like astyle when you save a buffer. See this question on SO for the details.
    – Bhargav
    Commented Feb 4, 2015 at 4:11
2

To re-indent the whole block of a braced or bracketed block automatically, place your cursor on the same line where is a bracket, and try =%. To change your shift width, use e.g. :set sw=2.

If this won't work as expected, to decrease indent manually (outdent), try <% and repeat with . (if necessary). Use >% for opposite.

So:

else
       {
         // some code
       }

becomes:

else
{
  // some code
}

For specific code, to re-indent one line or few lines automatically, try:

  • == to re-indent the current line
  • 5== to re-indent 5 lines

To increase/decrease indent manually for one line or few lines, try:

  • << to de-indent the current line by shiftwidth spaces
  • 5<< to de-indent 5 lines by shiftwidth spaces
  • >> to indent the current line by shiftwidth spaces
  • 5>> to indent 5 lines by shiftwidth spaces
  • . to repeat if necessary

You can also do indentation in visual mode (v) by selecting text and pressing = (auto-indent), < (de-indent) or >(indent).

Another trick is to correct indentation of the entire file by: gg=G.

If you've tabs instead of spaces, use: :retab which will replace all Tabs with spaces (See: How to replace tabs with spaces?).


For external methods, you can try:

  • pythonTidy for reformat Python code, e.g.:

    :%!pythonTidy
    

Related:

1

I recently installed vim-pasta (https://github.com/sickill/vim-pasta), and that seems to improve the indentation of code when I paste. The README also has some good discussion about various code pasting strategies.

0
1

There are already a lot of things covered in the existing answers. I just like to add one mapping that I use very often for indentation.

nnoremap <Leader>i  mzgg=G`z

I have seen some vimrc with this mapped to ===.

Either way this is a great mapping to have and I use this almost everytime especially when pasting code copied from somewhere else.

Or even better put this in an autocmd so that Vim indents it just before you write the changes to the disk.

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.