5

I would like to map <End> and <Home> to go to the end or beginning of the current line (not the screen), even if the cursor is on a wrapped line:

|1 First line.      |
|2 This is some very| <- Wrapped line 
|  long text        |
|3                  |

So here what should be the mappings:

<Home>  Cursor go to the first letter of visible line (wrapped or not).
<End>   Cursor go beyond the last letter of visible line (wrapped or not).

An important thing is that I use virtualedit:

set virtualedit=all
noremap <Up> gk
noremap <Down> gj
noremap k gk
noremap j gj

For a normal line, this can be solved using these mappings:

noremap <End> $l
noremap <Home> 0
"i_<End> already mapped
"i_<Home> already mapped

However on a wrapped line none of the above mappings work.

Here below the cases that must work:

|1 First line.       | Initial                   
       ^
|1 First line.       | <Home>                    (1)
   ^      
|1 First line.       | <End>                     (2)
              ^
|1 First line.       | <Home>                    
   ^                   l<Down>
|2 This is some very |                           
    ^
|2 This is some very | <End>                    (3)
                    ^
|2 This is some very | <Home>                    (4)
   ^                   l<Down>
|  long text         |                           
    ^ 
|  long text         | <Home>                    (5)
   ^
|  long text         | <End>                     (6)
            ^

The solution proposed by statox in his answer works for <Home>, but not really for <End>. So, I added a l to the <End> mapping. Then all the cases pass, but (3) that goes on the next line.

nnoremap <silent> <End>  :set virtualedit=<CR>g$:set virtualedit=all<CR>l 
nnoremap <silent> <Home> :set virtualedit=<CR>g0:set virtualedit=all<CR> 

Most editors solve case (3) by adding a virtual blank column at the end of the screen, so the cursor can be virtually placed here in this particular case.

How can I achieve the same behavior in Vim?

1 Answer 1

10

You're looking for g0 and g$ which are the equivalent of 0 and $ for wrapped lines. See :h g0, :h g$ and even :h g^.

To quote the doc about g$:

When lines wrap ('wrap' on): To the last character of the screen line and [count - 1] screen lines downward |inclusive|. Differs from "$" when a line is wider than the screen.

When lines don't wrap ('wrap' off): To the rightmost character of the current line that is visible on the screen. Differs from "$" when the last character of the line is not on the screen or when a count is used. Additionally, vertical movements keep the column, instead of going to the end of the line.


EDIT

About the virtualedit option maybe you could try something like:

nnoremap <silent> <end> :set virtualedit=<CR>g$:set virtualedit=all<CR>

The mapping can be explained like this:

nnoremap                   Create a normal mode mapping
<silent>                   Make the mapping silent to avoid messages in the command line
<end>                      The key to map
:set virtualedit=<CR>      Unset virtualedit
g$                         Use g$ normally
:set virtualedit=all<CR>   Set the virtualedit option again
5
  • I can't reproduce your problem, on my system g$ moves the cursor on the . of your first line example. Have you tried using it with vim -u NONE? Where does g$ move your cursor?
    – statox
    Commented Sep 30, 2016 at 13:08
  • Then it is an option in your vimrc which is causing this. You should read the doc I linked and probably play with the wrap related options. You can also have a look at this question to help you debug your vimrc.
    – statox
    Commented Sep 30, 2016 at 13:15
  • @nowox actually the doc for g$ says When 'virtualedit' is enabled moves to the end of the screen line. so this is probably the option to tweak in your vimrc :)
    – statox
    Commented Sep 30, 2016 at 13:22
  • 1
    @nowox see my edit.
    – statox
    Commented Sep 30, 2016 at 13:33
  • I've edited my question (again), and I removed my comments.
    – nowox
    Commented Sep 30, 2016 at 20:26

Your Answer

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

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