I have an insert mode mapping which calls a function to select some text and leave vim in select mode.
inoremap <silent> <C-J> <C-\><C-O>:call MyFunction()<CR>
This works in regular insert mode; and it works when the insert-mode completion popup window is visible and I haven't pressed ctrl-p or ctrl-n.
It doesn't work when the insert-mode completion popup window is visible and I have pressed ctrl-p or ctrl-n. In this case:
- the cursor moves to the expected location;
- the literal text
:call MyFunction()
with a newline is inserted in place of the text I wanted to be selected; - vim remains in insert mode instead of switching to select mode.
I believe this is because the C-\
at the start of the RHS is not part of the current completion option, so it has the effect of accepting the completion, which triggers CompleteDone
, which executes MyFunction()
(I listen for the CompleteDone
event and in my listener call MyFunction()
), and then the rest of the RHS is taken literally.
completeopt
is menuone,noinsert
. MyFunction()
looks like:
function! MyFunction()
...
stopinsert
call setpos("'<", ...)
call setpos("'>", ...)
execute "normal! gv\<C-G>"
endfunction
I tried this variation instead:
inoremap <silent> <C-J> <C-R>=pumvisible() ? '<C-Y>' : MyFunction()<CR>
This works when the completion window is open, both when I have and haven't pressed ctrl-p / ctrl-n; but it doesn't work in regular insert mode (it moves the cursor to the start of the line and switches to normal mode – I suspect because MyFunction()
doesn't have an explicit return
, and so implicitly returns 0
, which takes the cursor to the start of the line).
How can I get the mapping to work all the time?
:h CTRL-\_CTRL-N
do what you want?