Youcompleteme: Expand UltiSnips snippet if expand key invoked after UltiSnips trigger string

Created on 4 Jul 2013  路  39Comments  路  Source: ycm-core/YouCompleteMe

ycm_ulti
The first thing that came to mind when I saw this was, highlight snippet and press <Enter> to expand. But it didn't work :)
IMHO it's a common reaction, when you see something you want, you select it, and press enter.

Most helpful comment

Using a key other than return to expand snippets conflicts with my muscle memory from using Sublime Text in the past, which also means I like to use tab/shift-tab to move through the completion menu. For anyone similarly afflicted as myself I hope this helps.

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>"

Setting let g:UltiSnipsExpandTrigger = "<nop>" to do nothing is probably not required if you still want an alternative trigger in contexts where YouCompleteMe is not applicable.

All 39 comments

Yeah, it's something I want to get working (although in a slightly different way than you're describing). Currently you're forced to remap the UltiSnips expand key; it would be great if you didn't have to do that.

You'd still have to press TAB twice on occasion (once to insert the end of the ultisnips trigger string and once more to expand the snippet) but if your cursor is already after a snippet trigger string, one TAB should suffice.

But in that case usage of Tab key will conflict with the case when user just want to go to next completion.
Or you mean something like double-click?

I'll figure something out.

+1 for this, I think the optimal user experience here is to allow <return> to trigger the highlighted snippet, though I can see how that might be tricky to implement.

Or as you mentioned, to simply immediately trigger the snippet if the text selection is a 100% match to the snippet. This is how snipMate and others would normally work. I defined a snippet for log and when I type log -> <tab>, it'll automatically replace log with the snippet.

That way you could autocomplete on tab (or whatever the user has setup for YCM completion).

@nicksergeant that behavior is also conflicting with YCM use-case; what if there are other entries starting with log in completion list. The only non-conflicting case to use <tab> when the snippet is the only entry in completion list.

Ah, yeah, right. Hmm.

The safest option would have resorting to the user's navigational keys (hjkl) for moving up and down the list and using to actually expand the selected option.

@Valloric I like your proposal of using an additional to expand a selected snippet. In the case of a single match (and it's a snippet) It should probably autoexpand to the snippet with a single .

I use this to trigger snippet with tab. This will expand snippet with single tab press. But if first entry is a snippet and i need to go next then i have to use down or pass some more keystroke to filter out first entry.

function! g:UltiSnips_Complete()
    call UltiSnips_ExpandSnippet()
    if g:ulti_expand_res == 0
        if pumvisible()
            return "\<C-n>"
        else
            call UltiSnips_JumpForwards()
            if g:ulti_jump_forwards_res == 0
               return "\<TAB>"
            endif
        endif
    endif
    return ""
endfunction

au BufEnter * exec "inoremap <silent> " . g:UltiSnipsExpandTrigger . " <C-R>=g:UltiSnips_Complete()<cr>"
let g:UltiSnipsJumpForwardTrigger="<tab>"
let g:UltiSnipsListSnippets="<c-e>"

After this binding YCM+UltiSnips uses become lot easier for me. Thanks @jalcine for hjkl suggestion.

func! g:jInYCM()
    if pumvisible()
        return "\<C-n>"
    else
        return "\<c-j>"
endfunction

func! g:kInYCM()
    if pumvisible()
        return "\<C-p>"
    else
        return "\<c-k>"
endfunction
inoremap <c-j> <c-r>=g:jInYCM()<cr>
au BufEnter,BufRead * exec "inoremap <silent> " . g:UltiSnipsJumpBackwordTrigger . " <C-R>=g:kInYCM()<cr>"
let g:UltiSnipsJumpBackwordTrigger = "<c-k>"

Now I only need Tab, Ctrl+J and Ctrl+K to use YCM and UlitSnips.

@netsmertia awesome. One thing, you have g:UltiSnipsJumpBakcwordTrigger misspelled, it should be g: UltiSnipsJumpBackwordTrigger.

Is this ever going to be fixed by default? Seems super unfortunate.

What's funny about this is I found this issue, but I still don't know what key I should hit to trigger the snippet. ;)

[edit] ahh, using that vimrc example ctrl-l works.

@netsmertia Your solution works for me so far. Great, thank you so much! But for the newest version I had to replace the underscores in UltiSnips_ExpandSnippet() and UltiSnips_JumpForwards() with a #

@chmanie yes I did the same for newer version.

Using a key other than return to expand snippets conflicts with my muscle memory from using Sublime Text in the past, which also means I like to use tab/shift-tab to move through the completion menu. For anyone similarly afflicted as myself I hope this helps.

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>"

Setting let g:UltiSnipsExpandTrigger = "<nop>" to do nothing is probably not required if you still want an alternative trigger in contexts where YouCompleteMe is not applicable.

@kbenzie thanks! made my day

Glad to help. :)

Um... so this seems to work fine for me

let g:UltiSnipsExpandTrigger='<Enter>'

Actually thats not working out so well... can't press enter in insert mode.. eeek

@kbenzie it seems to not be working for me? It keeps trying to insert this when I press enter

ifpumvisible() ? "
" : "\
  "

It may be an issue with other plugins you have installed. I recall others seeing unexpected interacting behaviour.

@kbenzie Thanks for the above VimL snippet! Working very nicely for me with terminal Vim and MacVim.

I don't use UltiSnips, but would still like to be able to press tab to select a completion and enter/return to dismiss the suggestion popup.

I agree with the sentiment here that you see something you want the natural reaction is to press enter.

@fourcolors @kbenzie The last line of the snippet is incorrect, it should be:

inoremap <expr> <CR> pumvisible() ? "\<C-R>=ExpandSnippetOrCarriageReturn()\<CR>" : "\<CR>"

Though I can't get it working properly with vim-endwise

EDIT:

This seems to work for vim-endwise

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

@mikew thanks for that! your endwise-related modification to @kbenzie's suggestion worked for me too.

I just found a really nice solution using supertab. When you hit tab, if there is a snippet it will be expanded, if not ycm is triggered. Article

@guyfedwards nice find - that works much better than the other workarounds out there.

@kbenzie Hi, could you please help? I still cannot get omnisharp-completion to work on arch linux. It appears to work with cpp file. The reason is that the variable g:ulti_expand_or_jump_res is always 0 even if I set it to be 1 before the function definition. The same happens with g:util_expand_res. Completion works fine with neocomplete or supertab. Thanks.

@hoangngan82 Hi, I've not actually used this configuration for a long time so am not in the best position to help unfortunately. My only suggestion would be to disable all other plugins to ensure you are not having interactions with those and see if the problem persists, that way it might become clearer what the problem is. Sorry this isn't very helpful, I've moved to using a <C-p> and <C-n> to select items in the popup menu and only using <Tab> for UltiSnips expansion. Sorry.

@kbenzie Thank you for your quick response. I will try your suggestion.

@kbenzie Where should I put that function?

@montogeek when I used it I placed it in my .vimrc file after loading both the YouCompleteMe and UltiSnips plugins using my package manager.

@kbenzie Thanks!

I tried @kbenzie solution but still pressing enter only inserts an enter instead of completing. I tried disabling a lot of things but still cannot get it to work...

ultisnip

Here is my vimrc

Triggering ultisnips snippets works fine if you re-bind the keys as documented. We're not likely to make further changes in this space, though it might be possible if/when we are forced into supporting snippet-based completions for LSP

This might not answer the question directly but provides a way to allow the two greatest plugins to work together nicely

  1. just use TAB and SHIFT-TAB for UltiSnips and
  2. use CTRL-P, CTRL-N, and CTRL-SPACE for YouCompleteMe
inoremap <C-Space> <C-x><C-o>
if !exists('g:ycm_semantic_triggers')
   let g:ycm_semantic_triggers = {}
endif
let g:ycm_key_list_select_completion = ['<c-n']
let g:ycm_key_list_previous_completion = ['<c-p']
let g:UltiSnipsExpandTrigger="<tab>"
let g:UltiSnipsJumpForwardTrigger="<tab>"
let g:UltiSnipsJumpBackwardTrigger="<S-tab>"

@Valloric This should be the MOST ideal fix for this problem. I believe the issue will be closed once and for all after 7 years!
Basically, pressing Tab and Shift-Tab cycles through the completion forward/backward. It will NOT automatically (read: accidentally) expand a snippet, so you can use arrow keys or Ctrl+n/Ctrl+p or Tab/Shift+Tab to go up and down the selection options worry free. Then ONLY on Enter it will expand the snippet. Once your in the snippet, you can use Tab and Shift+Tab to jump forward and backward in the snippet writing. This is the most expected, intuitive and desirable outcome I can think of. Please confirm!

let g:UltiSnipsExpandTrigger = "<NOP>"
let g:UltiSnipsJumpForwardTrigger = "<TAB>"
let g:UltiSnipsJumpBackwardTrigger = "<S-TAB>"
function ExpandSnippet()
    call UltiSnips#ExpandSnippet()
    if g:ulti_expand_res
        return ""
    else
        return "\<CR>"
    endif
endfunction
inoremap <expr> <CR> pumvisible() ? "<C-R>=ExpandSnippet()<CR>" : "\<CR>"
Was this page helpful?
0 / 5 - 0 ratings