I like using the <CR> key to confirm my selection in the popup menu. However I don't like the <CR> key doing absolutely nothing when no item was selected in the menu -- in this case, it usually means I don't want to confirm a completion, I just want to insert a newline.

My current remap

inoremap <expr> <CR> pumvisible() ? "\<C-y>" : "\<CR>"

will "confirm the selection" and close the popup menu even if no item is selected -- i.e. the cursor stays in the same place. Is there another function I can use in the above ternary operation, or some other approach, that will give me the desired behavior?


The following works elegantly without the need for too many bindings.

function! s:CRComplete()
  if empty(v:completed_item)
    execute "norm! i\<CR>"
  endif endfunction
inoremap <CR> <LEFT><RIGHT><C-O>:call <SID>CRComplete()<CR>

Edits: In view of Hotschke's answer, the check for v:completed_item in my function above is simplified.

<LEFT><RIGHT> is added for the situation in which omni-complete returns a Pattern not found.


I solved this with a fairly hacky solution. I just remap the keys I want to use for scrolling the popup menu to also increment/decrement a counter as the menu is scrolled. If the counter is zero, we will insert a newline instead of "confirming" our choice in the popup menu. Note these were developed with the neocomplete plugin with the option let g:neocomplete#enable_auto_select=0.

I personally just use <Tab>/<S-Tab> and <ScrollWheelUp>/<ScrollWheelDown> but included some other remaps for people who prefer different keys.

"Reset the counter with autocmds where possible
au BufEnter * let b:tabcount=0
au InsertEnter * let b:tabcount=0
"Helper functions
function! s:tabincrease() "use this inside <expr> remaps
  let b:tabcount+=1
  return "" "returns empty string so can be used inside <expr>
function! s:tabdecrease() "use this inside <expr> remaps
  let b:tabcount-=1
  return ""
function! s:tabreset() "use this inside <expr> remaps
  let b:tabcount=0
  return ""
"Map the default keys for navigating completion popup menu
inoremap <expr> <C-y> pumvisible() ? "\<C-y>".<sid>tabreset() : "\<C-y>"
inoremap <expr> <C-e> pumvisible() ? "\<C-e>".<sid>tabreset() : "\<C-e>"
inoremap <expr> <C-n> <sid>tabincrease()."\<C-n>"
inoremap <expr> <C-p> <sid>tabdecrease()."\<C-p>"
"Map custom keys for confirming/cancelling a menu selection
inoremap <expr> <CR> pumvisible() ? b:tabcount==0 ? "\<C-e>\<CR>" : "\<C-y>".<sid>tabreset() : "\<CR>"
inoremap <expr> <Space> pumvisible() ? "\<Space>".<sid>tabreset() : "\<Space>"
inoremap <expr> <BS> pumvisible() ? "\<C-e>\<BS>".<sid>tabreset() : "\<BS>"
"Map custom keys for scrolling through the menu
inoremap <expr> <Tab> pumvisible() ? <sid>tabincrease()."\<C-n>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? <sid>tabdecrease()."\<C-p>" : "\<S-Tab>"
inoremap <expr> <Down> pumvisible() ? <sid>tabincrease()."\<C-n>" : "\<Down>"
inoremap <expr> <Up> pumvisible() ? <sid>tabdecrease()."\<C-p>" : "\<Up>"
inoremap <expr> <ScrollWheelDown> pumvisible() ? <sid>tabincrease()."\<C-n>" : "\<ScrollWheelDown>"
inoremap <expr> <ScrollWheelUp> pumvisible() ? <sid>tabdecrease()."\<C-p>" : "\<ScrollWheelUp>"

My version works as following

  1. When pum is visible & entry selected which is a snippet, expand snippet.
  2. When pum is visible & entry selected which is not a snippet, only close pum.
  3. When pum is visible & no entry selected, close pum and insert newline.
  4. When pum is not visible, insert newline.
function! s:ExpandSnippetOrClosePumOrReturnNewline()
    if pumvisible()
        if !empty(v:completed_item)
            let snippet = UltiSnips#ExpandSnippet()
            if g:ulti_expand_res > 0
                return snippet
                return "\<C-y>"
            return "\<C-y>\<CR>"
        return "\<CR>"
inoremap <silent> <CR> <C-r>=<SID>ExpandSnippetOrClosePumOrReturnNewline()<CR>

see also https://github.com/vim/vim/issues/2004

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.