7

I'm trying to set up normal mode mappings to make it easy to add white space around the cursor:

<C-h> will add one space to the right of the cursor;
<C-j> will add a newline below;
<C-k> will add a newline above;
<C-l> will add one space to the right of the cursor; and
<C-Enter> will add a newline at the current cursor position.

I also want the cursor position not to move during the command. For left, right, and newline, this is simple:

nnoremap <C-h> i <Esc>l
nnoremap <C-l> a <Esc>h
nnoremap <C-^M> i<CR><Esc><Backspace>

but for above and below, the corresponding commands

nnoremap <C-j> o <Esc>k
nnoremap <C-k> O <Esc>j

will get me back on the right line, but not back to the same column that I was on before.

Is there any way to return to the cursor position I was at just before entering insert mode? My best Google-fu only brought up references to '' & double-backtick (can't figure out how to format the markdown there) and :jumps / <C-O> & <C-I>, neither of which seem to work quite the way I'd like.

Can this be solved without Vimscript? Can it even be solved with Vimscript?

2 Answers 2

8

You can set a local mark to where you're before opening a new line, and go back to this mark afterwards.

You can choose any letter for the mark, let's say for example x:

nnoremap <C-k> mxO<esc>`x
nnoremap <C-j> mxo<esc>`x
  • mx sets the mark x where the cursor is
  • `x moves the cursor back to the position of mark x

You could also look at what tpope wrote in his unimpaired plugin and put the following code inside your vimrc:

set nostartofline

function! s:BlankUp(count) abort
  put!=repeat(nr2char(10), a:count)
  ']+1
endfunction

function! s:BlankDown(count) abort
  put =repeat(nr2char(10), a:count)
  '[-1
endfunction

nnoremap <c-k> :<c-u>call <SID>BlankUp(v:count1)<cr>
nnoremap <c-j> :<c-u>call <SID>BlankDown(v:count1)<cr>

The advantage of this solution over the previous one is that it accepts a count and doesn't change any of your marks.
For example to insert 2 lines above the current one, hit 2<C-k>, 3 lines below 3<C-j>.

PS: to write a double backtick in your post, use triple backticks before and after (and put spaces before and after the double backtick): ``

Edit
I just noticed that in the case of the 2nd solution, if you want the cursor to come back to the same column where it was before pasting a new line, you have to disable the option 'startofline': set nostartofline

When this option is disabled, the column number of your cursor stays the same after using various commands such as <C-d>, gg, dd, >>, :bnext, :25.
See :help 'startofline' for more info.

6

No need for vimscript here, the mappings below do exactly what you ask:

nnoremap <C-j> m`o<Esc>``
nnoremap <C-k> m`O<Esc>``
  • m` is used to set the "previous context mark",
  • o<Esc> does what you expect,
  • `` jumps back to the previous context mark.
3
  • Also note that you can also use m' and '' instead of m` and `` Dec 25, 2015 at 11:20
  • 2
    @EvergreenTree, '' won't jump to the right column, only to the right line.
    – romainl
    Dec 25, 2015 at 11:26
  • Ah, I didn't realize that. Dec 25, 2015 at 11:42

Your Answer

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

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