9

From time to time I have to work with code that isn't indented to the level of indentation I have Vim set up to (4 spaces per level), usually after copy/pasting something in the file. I usually make do with << and >>. The problem is they don't jump to the next indentation level, they just add or subtract 4 spaces.

If I have code like this

if condition:
    do this
   do that

doing >> on do that will result in

if condition:
    do this
       do that

I want it to go to this

if condition:
    do this
    do that

Beside easily matching the indentation of the line above, I want it to jump to the next level of indentation, not add 4 spaces.

This is what I have in my .vimrc regarding indentation

:set tabstop=4 shiftwidth=4 expandtab
  • If you also have filetype plugin indent on in your .vimrc, filetype (and plugin) indentation-related rules will apply. I.e. check what your tabstop value actually is (set tabstop? will do; same for the other settings), when editing, and change those values by adding your line to an 'after' file, something like: stackoverflow.com/a/159066/5000478 – VanLaser Oct 10 '16 at 13:43
  • 3
    >> and << respectively add and remove indent which is not what you want. What you want is "formatting", which is done with ==. – romainl Oct 10 '16 at 14:01
  • could also map :nnoremap >> ^i<tab><esc> if you really want tab behaviour on >> – Wolfie Oct 10 '16 at 14:07
  • @romainl == will jump to the level of the line above. While a good thing to know, it would not work in all cases I'm interested in. As an addition to the question, what I want is for >> and << to indent/dedent up to the next multiple of shiftwidth from the border in that direction. – Dumitru Oct 10 '16 at 14:51
  • 2
    No, == uses either equalexpr or equalprg to reformat the given lines. – romainl Oct 10 '16 at 19:26
12

When you use one of the commands {count}>>, {count}<<, >{motion} or <{motion}, on some lines which have already been indented, and you want their new indentation level to be a multiple of your 'shiftwidth' option value, you can enable the 'shiftround' option, and add this line in your vimrc:

set shiftround
2

If you always want >> to indent to the next tabstop and << to delete to the last tabstop, you can rebind them like so:

:nnoremap << ^i<BS><esc>
:nnoremap >> ^i<tab><esc>

This will move the cursor, but you could probably do some mark trickery to move it back. ^ doesn't leave a m' mark, but you can leave one manually inside the binding.

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.