2

I have a function that depends on the character under the cursor : if it's a ), then the function does nothing ; if it's not, the function adds a ).

function! Ket()
   let char = getline(".")[col('.')-1]
   if char != ')'
      execute "normal! a)\<esc>"
   endif
endfunction

If I call it from normal mode, using :call Ket(), it works fine.

But I have it remapped from insert mode, as follows :

inoremap ) <Esc>l:call Ket()<CR>a. This mapping should (from my understanding) :

  • escape insert mode with <Esc>,
  • go one character to the right with l (because escape to normal mode moves the cursor to the left),
  • call my Ket() function,
  • get back to insert mode (a)

If I am in insert mode, and my cursor is on a ) character, then I get what I expect by pressing ) : the cursor moves to the right, and I end up in insert mode.

But if my cursor is on any other character, pressing ) only escapes insert mode, as if I had pressed Esc.

2
  • 1
    See :h :map-<expr> for a better approach. Keep in mind however that insert-mode maps are tricky, and what you're trying to do is a solved problem. Something like delimitMate or auto-pairs will do a much better job at handling corner cases than your naive map. Jun 16, 2016 at 14:19
  • I checked this help indeed, thanks. As for the plugins, I know the solution exists, but I'm trying to code it myself to improve my Vimery :)
    – Feffe
    Jun 16, 2016 at 14:30

1 Answer 1

2

Instead of leaving insert mode you could try to do the same without the need for a function (because in this case it's a simple case):

inoremap <expr> )  strpart(getline('.'), col('.')-1, 1) == ")" ? "\<Right>" : ")"

Decomposing:

inoremap <expr> )  

will insert the result of the mapping as instead of )

strpart(getline('.'), col('.')-1, 1) 

get the current character under cursor

== ")" ? "\<Right>" : ")"

if it's a ) insert the right key, if not, insert a ).


If you want to keep your function, you can do it as well like this:

function! Ket()
  if strpart(getline('.'), col('.')-1, 1) == ")" 
    return "\<Right>" 
  else
    return  ")"
  endif
endfunction

inoremap <expr> ) Ket()
2
  • It seems to work perfectly, though I had to take away the "\" in '\<Right>', otherwise a ` \ ` was added each time there was already a ). Thank you for the very detailed explanation, that's exactly what I need.
    – Feffe
    Jun 16, 2016 at 14:15
  • Strange, here it's working as is ...
    – nobe4
    Jun 16, 2016 at 14:17

Your Answer

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

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