I have mapped my arrows keys to move in a visual-line mode, leaving the hjkl keys for normal, logic line movement:

" Visual movement with the arrows and End-Home 
nnoremap <Down> gj
nnoremap <Up> gk
vnoremap <Down> gj
vnoremap <Up> gk
inoremap <Down> <C-o>gj
inoremap <Up> <C-o>gk
inoremap <Home> <C-o>g<Home>
inoremap <End>  <C-o>g<End>

This works, but for a minor problem. I have a bit of code in my status line to change color between input mode and normal mode, like this:

if version >= 700
  highlight statusLine cterm=bold ctermfg=black ctermbg=red
  au InsertLeave * highlight StatusLine cterm=bold ctermfg=black ctermbg=red gui=bold guifg=black guibg=red
  au InsertEnter * highlight StatusLine cterm=bold ctermfg=black ctermbg=green   gui=bold guifg=black guibg=green

...and I noticed now (on a machine slower than the one I have at home) that every time I press one of the arrows, the temporary mode switch of <ctrl>o (at least, I think) make the status line flash rapidly red then green again.

It is possible to redefine the keys to avoid the temporary jump to normal mode?


I have two ideas, but both are quite complex:

  1. Use :inoremap <expr> and perform the cursor repositioning with :call cursor() yourself. The downside is that you have to do the calculation which wrapped column is directly over / under the cursor.
  2. Use :inoremap <expr> to wrap the <C-o>gj command in :set eventignore+=InsertLeave,InsertEnter before and option restore afterwards, like this:
function! IgnoreOn( motion )
    set eventignore+=InsertLeave,InsertEnter
    return "\<C-o>" . a:motion
function! IgnoreOff()
    set eventignore-=InsertLeave,InsertEnter
    return "\<Left>\<Right>" | " Workaround for missing screen update.
inoremap <expr> <SID>IgnoreOff IgnoreOff()
inoremap <expr> <SID>IgnoredDown IgnoreOn('gj')
inoremap <script> <Down> <SID>IgnoredDown<SID>IgnoreOff
  • Tried, seems to work but the first Down after entering input mode is ignored. The problem is that I do not understand it ... could you point me to somewhere when to learn about <SID> stuff? Or (if you have time) comment the code? Thanks! – Rmano Apr 29 '14 at 16:40
  • Actually, the cursor also moves the first time, just the screen isn't updated until another cursor move or char insertion. I've added a workaround to my answer. – Ingo Karkat Apr 30 '14 at 6:29
  • The <SID> just makes the mappings local; you could have used <Plug>, too. And see :h :map-expr for details. – Ingo Karkat Apr 30 '14 at 6:30
  • Sorry for the delay --- it works like a charm. Thanks, marked solved. – Rmano May 7 '14 at 14:39

My solution is based on Igno's suggestions, but does not require excessive mouse movement.

autocmd! InsertEnter * set eventignore-=InsertLeave
function! s:UpDown(keys)
  set eventignore+=InsertLeave
  return "\<C-O>".a:keys
inoremap <expr> <DOWN> <SID>UpDown('gj')
inoremap <expr> <Up> <SID>UpDown('gk')

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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