3

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?

4 Answers 4

3

To add to existing answers, I found empty(v:completed_item) to be unreliable, and sometimes it will be empty even though I have something selected in the pum.

What worked for me was to use complete_info() and directly get the line selected. if the selected line is -1, then we know for sure nothing is selected.

pumvisible() ? (complete_info().selected == -1 ? '<C-y><CR>' : '<C-y>') : '<CR>'
1
1

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.

0

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>
endfunction
function! s:tabdecrease() "use this inside <expr> remaps
  let b:tabcount-=1
  return ""
endfunction
function! s:tabreset() "use this inside <expr> remaps
  let b:tabcount=0
  return ""
endfunction
"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>"
0

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
            else
                return "\<C-y>"
            endif
        else
            return "\<C-y>\<CR>"
        endif
    else
        return "\<CR>"
    endif
endfunction
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 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.