sponsor Vim development Vim logo Vim Book Ad

basic Tip #38: Cursor one line at a time when :set wrap

 tip karma   Rating 306/92, Viewed by 5151 

Read and edit this tip on the Vim tip wiki. The wiki may have a more recent version of this tip.

created:   March 7, 2001 8:41      complexity:   basic
author:   [email protected]      as of Vim:   5.7

If your tierd of the cursor jumping past 5 lines when :set wrap then add these mappings to you vimrc file.

nnoremap j gj
nnoremap k gk
vnoremap j gj
vnoremap k gk
nnoremap <Down> gj
nnoremap <Up> gk
vnoremap <Down> gj
vnoremap <Up> gk
inoremap <Down> <C-o>gj
inoremap <Up> <C-o>gk

What they do is remap the cursor keys to use there `g' equvilant. See :help gj

 rate this tip  Life Changing Helpful Unfulfilling 

<< The basic operation about vim-boolean optionals | Undo and Redo >>

Additional Notes

[email protected], May 26, 2004 2:12
Is there any way to turn these mappings on and off when setting wrap and nowrap?
Anonymous, June 5, 2004 17:30
This seems only to work in the ~/.vimrc file, not in the system-wide vimrc in /etc?!
[email protected], January 22, 2006 16:30
mine "works" from /etc/vim/vimrc, but it moves one line down, then one char to the right. Kinda strange
Anonymous, January 24, 2006 15:53
I removed vnoremap <Up> gk and then it seems to work.
Anonymous, January 24, 2006 16:14
Sorry, remove <C-o> from the last line- inoremap <Up> <C-o>gk . It works here.
Anonymous, March 13, 2006 10:40
To enable/disable the key mappings with wrap:

nnoremap <silent> c :call ChooseWrap()<CR>
function ChooseWrap()
  let l:choice=confirm("Toggle Wrapping?", "&yes;\n&no;", 0)
  if l:choice==1
    if &wrap;
      call DisableDisplayWrapping()
    else
      call EnableDisplayWrapping()
    endif
  endif
endfunction
function EnableDisplayWrapping()
  if !&wrap;
    setlocal wrap
    " don't skip wrapped lines
    nnoremap <buffer> <Up> gk
    nnoremap <buffer> <Down> gj
    inoremap <buffer> <Up> <C-O>gk
    inoremap <buffer> <Down> <C-O>gj
  endif
endfunction
function DisableDisplayWrapping()
  if &wrap;
    setlocal nowrap
    nunmap <buffer> <Up>
    nunmap <buffer> <Down>
    iunmap <buffer> <Up>
    iunmap <buffer> <Down>
  endif
endfunction

(if you hit 'c' in command mode, it'll pop up a menu asking if you want to toggle wrapping - you could obviously change this slightly to have it ask you if you would like to enable or disable wrapping)
[email protected], April 13, 2006 0:40
***FIX:*** Remove the trailing spaces.

Us lazy bunnies been copypasting the code in the tip to our _vimrc files, but that code contains a trailing space after each line except the last one. In other words, the above code sets the mapping
nnoremap j gj<Space>
which of course amounts to "Map j to go 1 terminal line down, then one character to the right."

Here's the same code with trailing spaces removed, for sleepy caterpillars like myself:
nnoremap j gj
nnoremap k gk
vnoremap j gj
vnoremap k gk
nnoremap <Down> gj
nnoremap <Up> gk
vnoremap <Down> gj
vnoremap <Up> gk
inoremap <Down> <C-o>gj
inoremap <Up> <C-o>gk

Cheers,

Sietse Brouwer
[email protected], April 13, 2006 0:58
Erratum: the fix works. The above code doesn't.

It's not because the note system adds any trailing whitespace --- I checked the page source. I think it's because browsers copy <br> as though it were a space. They don't when you only select a single line and move the mouse to the right of its end; they do once you move the mouse down onto the next line. By "line" I mean text that ends with a <br> tag: any wrapping your browser introduces because of screen width doesn't have this problem. (I should bloody well hope so: imagine copying a paragraph from your browser to your word processor, and getting extra spaces sprinkled all across its contents. About as painful as dancing on spitzen.)

This behaviour occurs in Opera 8.54, IE6, and Firefox 1.5 without plugins. Bug report time!

Cheers,

Sietse Brouwer
[email protected], May 10, 2006 14:47
I found the following to work pretty nicely for myself.
It only maps movements per-screen (using the 'g' prefix) iff in wrap mode.
Put the following in your .vimrc:

<pre>
   " mapping to make movements operate on 1 screen line in wrap mode
   function! ScreenMovement(movement)
      if &wrap;
         return "g" . a:movement
      else
         return a:movement
      endif
   endfunction
   onoremap <silent> <expr> j ScreenMovement("j")
   onoremap <silent> <expr> k ScreenMovement("k")
   onoremap <silent> <expr> 0 ScreenMovement("0")
   onoremap <silent> <expr> ^ ScreenMovement("^")
   onoremap <silent> <expr> $ ScreenMovement("$")
   nnoremap <silent> <expr> j ScreenMovement("j")
   nnoremap <silent> <expr> k ScreenMovement("k")
   nnoremap <silent> <expr> 0 ScreenMovement("0")
   nnoremap <silent> <expr> ^ ScreenMovement("^")
   nnoremap <silent> <expr> $ ScreenMovement("$")
</pre>
Anonymous, June 10, 2006 9:22
... should be mentioned that
    :h map-<expr>
is new to Vim7
Anonymous, October 13, 2006 12:29
This works great, however I'm using the MSWIN mappings and it interferes with the shift-selection.  For instance if I shift-select a block of text and release the shift key, subsequent up/down keypresses do not exit the select mode.  Is there a way to remedy this?
If you have questions or remarks about this site, visit the vimonline development pages. Please use this site responsibly.
Questions about Vim should go to the maillist. Help Bram help Uganda.
   
SourceForge.net Logo