Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

In Vim, I want to bind a key which will insert a newline and indent that newline up to the column where the cursor used to be. It's a little strange, so let me illustrate:

Example: before and after, with the cursor at |

Before:

a = str "Hello |World"

After:

a = str "Hello 
               |World"

This concept is not related to vim's 'copyindent' nor 'preserveindent' settings (these settings concern themsevles with the leading indentation of the previous line, not the column of the cursor).

share|improve this question
add comment

2 Answers

up vote 1 down vote accepted

Try this mapping.

:inoremap <F2> <CR><C-R>=repeat(' ',col([line('.')-1,'$'])-col('.'))<CR><C-O>:.retab<CR>

When you type F2 (or whatever key you choose for the mapping), Vim will insert a newline (<CR>) followed by a number of spaces (<C-R>=repeat(' ',...)) equal to the difference between the column number of the end of the previous line (col([line('.')-1,'$'])) and the current column number (col('.')), then will execute :retab on the current line to replace those spaces by tabs and/or spaces according to your setting of 'expandtab'.

Edit

That mapping requires that you be in insert mode. I was thinking that you would type the map key after typing Hello and before typing World. To go back and insert that newline in normal mode, use this mapping.

nnoremap <F2> i<CR><C-R>=repeat(' ',col([line('.')-1,'$'])-col('.'))<CR><Esc>:.retab<CR>
share|improve this answer
    
Thanks, this works very well! –  Ein May 28 '13 at 18:21
add comment

I don't have access to a copy of vim (or even vi) at the moment to test this, but try something like

iEnterEsc-Yp:s/./ /gEnterJ

What it does:

  • Insert a line break (no-brainer).
  • Go back up to the a = str "Hello line and make a copy of it.
  • Change every character in the copied line to a space -- so you should now have 15 spaces.
  • Join this line (15 spaces) to the |World" line, so it is now indented 15 spaces.

You might need to delete one space (because the join operation might add one).  If there may be tabs in the line, you might want to add !_expandEnter to expand tabs to spaces in the copy of the first part of the line.  And you might also want to add !_unexpandEnter to compress spaces to tabs.

share|improve this answer
    
I had finished writing this before I saw @garyjohn's answer. And BTW, this might work in vi. –  Scott May 28 '13 at 18:00
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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