Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving the cursor through long soft-wrapped lines in Vim

I'm sorry if my question isn't very clear. I'm not sure how to phrase it.

I'd like to use VIM to write papers for some classes I'm in. The problem I'm having is with the formatting of lines in the editor. If I don't explicitly break the end of a line with the enter key, when I try to move the cursor through the text, it skips multiple lines if I have a sentence that spans more than one line. Is there any way to make it so that the cursor will be able to move through the text akin to the way it does in most word processors?

like image 580
Victor Brunell Avatar asked Jan 07 '14 15:01

Victor Brunell


People also ask

How do you move between lines in Vim?

In normal mode or in insert mode, press Alt-j to move the current line down, or press Alt-k to move the current line up. After visually selecting a block of lines (for example, by pressing V then moving the cursor down), press Alt-j to move the whole block down, or press Alt-k to move the block up.

How do I skip a line in vi?

To do this, press Esc , type the line number, and then press Shift-g . If you press Esc and then Shift-g without specifying a line number, it will take you to the last line in the file.


2 Answers

The problem with the often used

noremap j gj  
noremap k gk 

option is, that it breaks the <vcount> functionality, if you have lines in your text, which span across multiple lines.
Example: you want 10k (go UP 10 lines), because you use relative numbers in the sidebar, but theres a multiline with 4 lines height. Therefore you end up effectively at 6 lines (6k) above your desired line, which you read from your relative numbers. You'd have to calculate manually! Annoying... Especially if you have multiple multiline between your current position and your desired position - not Vim-istic!

I like my <vcount> function together with my :relativenumber, which is why I wrote the following functions & mapping to solve all problems related to this.
These functions let you use commands like 10j or 10k as expected, despite the presence of multilines with all the advantages of using gj and gk as your default movement mappings:

Edit: I just found the following on reddit, which is so much better then my own solution. This is shortest possible version:

nnoremap <expr> j v:count ? 'j' : 'gj'
nnoremap <expr> k v:count ? 'k' : 'gk'

(If you use noremap instead of nnoremap, then this works in both visual and normal modes)

"Longer" version for better understanding and completeness:

nnoremap <expr> k (v:count == 0 ? 'gk' : 'k')
nnoremap <expr> j (v:count == 0 ? 'gj' : 'j')

source: http://www.reddit.com/r/vim/comments/2k4cbr/problem_with_gj_and_gk/


My old solution:

nnoremap <silent> j :<C-U>call Down(v:count)<CR>
vnoremap <silent> j gj

nnoremap <silent> k :<C-U>call Up(v:count)<CR>
vnoremap <silent> k gk

function! Down(vcount)
  if a:vcount == 0
    exe "normal! gj"
  else
    exe "normal! ". a:vcount ."j"
  endif
endfunction

function! Up(vcount)
  if a:vcount == 0
    exe "normal! gk"
  else
    exe "normal! ". a:vcount ."k"
  endif
endfunction
like image 90
freeo Avatar answered Sep 18 '22 09:09

freeo


That's because the default j and k motions move across physical lines, not the visible, soft-wrapped screen lines (when you have :set wrap). You can use the gj and gk commands for that.

If you want to default to that behavior, you can remap the default keys by putting this into your ~/.vimrc:

noremap j gj
noremap k gk
like image 28
Ingo Karkat Avatar answered Sep 19 '22 09:09

Ingo Karkat