Ultisnips: Why when I set UltiSnipsExpandTrigger to '<cr>', I loose '<cr>' in normal Vim editing.

Created on 11 Sep 2014  Â·  14Comments  Â·  Source: SirVer/ultisnips

I use YCM/Ultisnips/Supertab and hope to use carriage return to activate snippets, as I tend to think of tab as an 'enter the PUM/go to next candidate key, and it is disconcerting to have a tab key trigger a snippet.
I got it working how I would like it but soon noticed that setting UltiSnipsExpandTrigger to carriage return seems to disable carriage returns in insert mode for Vim, and of course that isn't acceptable.....
So, am I doing something wrong, or is there a way around this? It seems to me that UltiSnips should only be redefining the UltiSnipsExpandTrigger key when the PUM is visible and the selection candidate is a snippet??? Or am I missing something.

Thanks,
Dave Day

And sorry if this is not the right place for this question. I wasn't sure where to put it.

Most helpful comment

I may have made a mistake, or there could be some behaviour that relevant settings were not included in the snippet, here is a copy paste from my .vimrc which is slightly updated.

let g:ycm_key_list_select_completion=["<tab>"]
let g:ycm_key_list_previous_completion=["<S-tab>"]

let g:UltiSnipsJumpForwardTrigger="<tab>"
let g:UltiSnipsJumpBackwardTrigger="<S-tab>"
let g:UltiSnipsExpandTrigger="<nop>"
let g:ulti_expand_or_jump_res = 0
function! <SID>ExpandSnippetOrReturn()
  let snippet = UltiSnips#ExpandSnippetOrJump()
  if g:ulti_expand_or_jump_res > 0
    return snippet
  else
    return "\<CR>"
  endif
endfunction
inoremap <expr> <CR> pumvisible() ? "<C-R>=<SID>ExpandSnippetOrReturn()<CR>" : "\<CR>"

Hope that works for you as it does for me.

All 14 comments

UltiSnips does not care about you using a completer like YCM (it works just as well alone), so it highjacks your key for expanding always (of course, since you might always want to expand a trigger). Vim makes it hard to come up with a solution that is easy to configure and works for everybody sadly. People had the problem before though, you might want to look at:

https://github.com/SirVer/ultisnips/issues/322

@DaveDay I was looking for a solution to this issue (I'm also a YouCompleteMe user) and found Vim: call consecutive functions in mapping on stackoverflow.

I found the answer in #322 to be a different question, with the solution regarding jumping forward & backward in the completion list rather than only expanding a snippet when pumvisible() is non zero.

The following in my .vimrc has allowed my to have the return key expand snippets when the completion menu is visible and function as expected in insert mode.

let g:UltiSnipsExpandTrigger = "<nop>"
inoremap <expr> <CR> pumvisible() ? "<C-R>=UltiSnips#ExpandSnippetOrJump()<CR>" : "\<CR>"

Hope this helps! :D

SirVer, kbenzie, et al -

Thanks so much for your interest in helping me this this!
No single approach seemed to work to my satisfaction but a combination did.

I had settled on a slightly less ambitious but nevertheless entirely adequate solution from Valloric's YCM issue #420 which uses "control el" as the trigger, and since I swapped caps lock and ctrl, that is very easy to use.

I ran in to another solution that worked but then the tab motions in the actual triggered snippet were broken.

kbenzie's solution in addition to Valloric's Issue #420 have combined to give me the tab centric completion I desired, plus the "CR" Snippet Activation all while allowing the proper behaviours inside
the activated snippets AND leaving me with a functional "CR" key in regular Vim editing!

I have only given it a few minutes testing, but as far as I can tell, I now have EXACTLY what I was
looking for! This ends the work of slightly limping along, being somewhat productive
but not really satisfied. So thanks to all!

After using my previous solution for a few days I came across an issue. When in a completion menu where a snippet is NOT selected hitting enter has no effect. Instead using the following function which first checks if there is a snippet to expand will be successful and returning <CR> if not works in all situations I've come across so far.

let g:UltiSnipsExpandTrigger = "<nop>"
let g:ulti_expand_or_jump_res = 0
function ExpandSnippetOrCarriageReturn()
    let snippet = UltiSnips#ExpandSnippetOrJump()
    if g:ulti_expand_or_jump_res > 0
        return snippet
    else
        return "\<CR>"
    endif
endfunction
inoremap <expr> <CR> pumvisible() ? "<C-R>=ExpandSnippetOrCarriageReturn()<CR>" : "\<CR>"

Hrm... that ExpandSnippetOrCarriageReturn solution isn't working for me. When I complete a snippet from the YCM popup menu (menu triggered with <tab>, snippet triggered with <enter>), the following is inserted into the buffer instead of the snippet:

pumvisible() ? "
" : "\
"

I've never seen a mapping that used vim code before, so I can't tell if there's a typo in your example using pumvisible(). Or maybe this doesn't work with newer versions of Ultisnips or YCM?

Actually, it looks like this string is inserted whenever I hit enter while in insert mode.

I may have made a mistake, or there could be some behaviour that relevant settings were not included in the snippet, here is a copy paste from my .vimrc which is slightly updated.

let g:ycm_key_list_select_completion=["<tab>"]
let g:ycm_key_list_previous_completion=["<S-tab>"]

let g:UltiSnipsJumpForwardTrigger="<tab>"
let g:UltiSnipsJumpBackwardTrigger="<S-tab>"
let g:UltiSnipsExpandTrigger="<nop>"
let g:ulti_expand_or_jump_res = 0
function! <SID>ExpandSnippetOrReturn()
  let snippet = UltiSnips#ExpandSnippetOrJump()
  if g:ulti_expand_or_jump_res > 0
    return snippet
  else
    return "\<CR>"
  endif
endfunction
inoremap <expr> <CR> pumvisible() ? "<C-R>=<SID>ExpandSnippetOrReturn()<CR>" : "\<CR>"

Hope that works for you as it does for me.

Strange - still doesn't work. Must be something in my config, but thanks
for sending over the updated snippet!

Cheers,
Tammer Saleh
+44 7463 939332

On Wed, Jan 7, 2015 at 3:03 PM, Kenneth Benzie [email protected]
wrote:

I may have made a mistake, or there could be some behaviour that relevant
settings were not included in the snippet, here is a copy paste from my
.vimrc which is slightly updated.

let g:ycm_key_list_select_completion=[""]
let g:ycm_key_list_previous_completion=[""]

let g:UltiSnipsJumpForwardTrigger=""
let g:UltiSnipsJumpBackwardTrigger=""
let g:UltiSnipsExpandTrigger=""
let g:ulti_expand_or_jump_res = 0
function! ExpandSnippetOrReturn()
let snippet = UltiSnips#ExpandSnippetOrJump()
if g:ulti_expand_or_jump_res > 0
return snippet
else
return ""
endif
endfunction
inoremap pumvisible() ? "=ExpandSnippetOrReturn()" : ""

Hope that works for you as it does for me.

—
Reply to this email directly or view it on GitHub
https://github.com/SirVer/ultisnips/issues/376#issuecomment-69033351.

Finally had time to debug this. Removed all of my plugins and re-enabled them one-by-one, and the end culprit was https://github.com/tpope/vim-endwise

@tsaleh I use delimitMate and I modified @kbenzie's script to work with it:

let g:UltiSnipsJumpForwardTrigger="<tab>"
let g:UltiSnipsJumpBackwardTrigger="<S-tab>"
let g:UltiSnipsExpandTrigger="<nop>"
let g:ulti_expand_or_jump_res = 0
function! <SID>ExpandSnippetOrReturn()
  let snippet = UltiSnips#ExpandSnippetOrJump()
  if g:ulti_expand_or_jump_res > 0
    return snippet
  else
    return "\<C-Y>"
  endif
endfunction
imap <expr> <CR> pumvisible() ? "<C-R>=<SID>ExpandSnippetOrReturn()<CR>" : "<Plug>delimitMateCR"

Is there any way to get it to work with vim-endwise?

I found this somewhere and it worked with my endwise, delimitmate, ultisnips, youcompleteme, etc. Replace the last line in the previous solution with this:

let g:endwise_no_mappings = 1
inoremap <expr> <CR> pumvisible() ? "\<C-R>=ExpandSnippetOrCarriageReturn()\<CR>" : "\<CR>\<C-R>=EndwiseDiscretionary()\<CR>"

The following command doesn't strictly work:

let g:UltiSnipsExpandTrigger="<nop>"

It results in the text string <nop> being mapped to the expand trigger. As a result, typing '<' in insert mode will misbehave, and literally typing <nop> will trigger completion..

Checking the source, there doesn't seem to be a reasonable way to completely prevent ultisnips mapping "SOMETHING" to the expand trigger, but ensuring 'g:UltiSnipsExpandTrigger' is set to the same value as 'g:UltiSnipsJumpForwardTrigger' has the most reasonable outcome.

let g:UltiSnipsExpandTrigger= "<c-f>"
let g:UltiSnipsJumpForwardTrigger = "<c-f>"

While <nop> is not a valid special token, <NUL> is. The following will do what you want,

let g:UltiSnipsExpandTrigger = "<NUL>"

You can verify it works by checking for mapping starting with <,

:map <

An alternative solution which worked better for me, since I use to auto-complete snippet triggers with _Deoplete_. Therefore the here presented solutions are a nightmare, cause as soon as trigger is typed, but a different completion item is selected (not a rare case), this would always end up expanding the snippet. So I want to expand the snippet only when I selected this entry. (Just to mention, I use to add menuone to the completeopt option.) Therefore I leave my completion mapping as it is:

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

And I hook into the CompleteDone event. Break it down it looks something like this (please make this more pretty, since this is only a shorten example within one file):

autocmd! CompleteDone * call <SID>try_expand()

function! s:try_expand() abort
  " Ignore events without completion item.
  " Furthermore ignore completions with items having a 'kind' property, since
  " UltiSnips does not define such. This is useful to avoid snippet completion
  " in case no snippet trigger has been completed, but a equal named candidate
  " like a variable or function.
  " Check if a at least one completion candidate exists (only one available
  " after completion).
  if !empty(v:completed_item) &&
        \ strlen(v:completed_item.kind) == 0 &&
        \ len(UltiSnips#SnippetsInCurrentScope()) > 0

    call UltiSnips#ExpandSnippet()
  endif
endfunction

Except the remaining issue mentioned at the in-line comments, this works pretty well. I opened a issue ( #1042 ) to improve the kind handling to make this solution absolutely accurate.

Was this page helpful?
0 / 5 - 0 ratings