# Jump cursor vertically over code blocks. Keep horizontal position

I'm thinking about a feature which I think would improve my workflow a lot. I don't know if it already exists..

The feature is about moving the cursor vertically over code blocks without losing its horizontal position in a speedy way. I would regard it as a more convenient alternative for { and }. Or you could say it would be the vertical equivalent for w/e and b.

What I really don't like about { and } is that I lose the horizontal position of the cursor.

The behavior of the feature for moving the cursor should be like this:

• Move the cursor up/down to the next line that is preceded or followed by an empty line. (ignore white spaces)
• Don't lose the horizontal position of the cursor. If the line is shorter put the cursor on the last position of that line, but remember the position it came from. Even if you hit j or k afterwards the cursor should maintain its initial horizontal position. (same behavior as j/k)

Example for moving down: (moving up behaves the same, just in the other direction.)

X0 indicates the initial position.

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAA[X0]AAAAAAA
AAAAAAAAAAAAA
AAAAAAAAA[X1]

BBBBBBBBBBB[X2]BBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBB
BBBBBBBBBBB[X3]BBBBBBBB

CCCCCCCCCCC[X4]CCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCC[X5]


If I hit k on the last line it would go back to position 11, right under X4.

Do you know of such a feature or do you know how I could create it?

Here is a small function, that seems to do what you want:

function! Move(up)
let curpos = getcurpos()
let firstline='$$^\s*\n$$\zs\S\+'
let lastline ='\S\+\ze\n\s*$' let flags = 'Wn'. (a:up ? 'b' : '') " Move to first or last line of paragraph, " or to the beginning/end of file let pat = '$$'.firstline.'\|'.lastline.'$$\|\%^\|\%$'
" make sure cursor moves and search
" does not get stuck on current line
call cursor(line('.'), a:up ? 1 : col('$')) let target=search(pat, flags) if target > 0 let curpos[1]=target let curpos[2]=curpos[4] endif call setpos('.',curpos) endfu nnoremap <silent> <leader>j :call Move(0)<cr> nnoremap <silent> <leader>k :call Move(1)<cr>  This relies on the getcurpos() function, which has been included as patch 7.4.578. If you don't have it, you can use the winsaveview()/winrestview() function, to work around it. This might however mess up the screen, not sure this will work reliably. (with a newer vim, you can throw away the values in the dictionary returned by winsaveview() and only update the other values, but that is not possible with older vims as well). function! Move(up) let curpos = winsaveview() let firstline='$$^\s*\n$$\zs\S\+' let lastline ='\S\+\ze\n\s*$'
let flags = 'Wn'. (a:up ? 'b' : '')
" Move to first or last line of paragraph,
" or to the beginning/end of file
let pat = '$$'.firstline.'\|'.lastline.'$$\|\%^\|\%$' " make sure cursor moves and search " does not get stuck on current line call cursor(line('.'), a:up ? 1 : col('$'))
let target=search(pat, flags)
if target > 0
let curpos.lnum=target
let curpos.col=curpos.curswant
endif
call winrestview(curpos)
endfu

• I get an error: Unknown function: getcurpos. Jul 22, 2016 at 16:55
• Your Vim is too old, can use winsaveview for that, let me update the question. What version is this? Jul 22, 2016 at 17:02
• Version is 7.4.53. My distro does only offer this out dated version :/ Jul 22, 2016 at 17:06
• @Rotareti updated answer Jul 22, 2016 at 17:11
• Moving up works perfectly! On moving down the cursor gets stuck every 1 to 10 movements. Anyway this is fantastic! I'll try to get an update for vim to fix it. Jul 22, 2016 at 17:48

You can start working from this simple mapping:

:nnoremap J :let c=col('.') <bar> execute "normal! }k".c."<bar>"<CR>


Decomposition

:let c=col('.')     " save the current column into the variable c
<bar>               " chain another command
execute "normal!    " execute a normal command
}k                  " go to next paragraph and up one line
c."<bar>"           " go to the column number c


Note: this won't work without a newline after the paragraph.