ycm-core / YouCompleteMe

A code-completion engine for Vim
http://ycm-core.github.io/YouCompleteMe/
GNU General Public License v3.0
25.48k stars 2.81k forks source link

Expand UltiSnips snippet if expand key invoked after UltiSnips trigger string #420

Closed davits closed 2 years ago

davits commented 11 years ago

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.

Valloric commented 11 years ago

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.

davits commented 11 years ago

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?

Valloric commented 11 years ago

I'll figure something out.

nicksergeant commented 11 years ago

+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.

nicksergeant commented 11 years ago

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).

davits commented 11 years ago

@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.

nicksergeant commented 11 years ago

Ah, yeah, right. Hmm.

jalcine commented 11 years ago

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.

francoisjacques commented 11 years ago

@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 .

netsmertia commented 11 years ago

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>"
netsmertia commented 11 years ago

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.

nicksergeant commented 11 years ago

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

jsholmes commented 10 years ago

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

rseymour commented 10 years ago

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.

chmanie commented 10 years ago

@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 #

netsmertia commented 10 years ago

@chmanie yes I did the same for newer version.

kbenzie commented 10 years ago

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.

jvermillard commented 9 years ago

@kbenzie thanks! made my day

kbenzie commented 9 years ago

Glad to help. :)

fourcolors commented 9 years ago

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

let g:UltiSnipsExpandTrigger='<Enter>'
fourcolors commented 9 years ago

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

fourcolors commented 9 years ago

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

ifpumvisible() ? "
" : "\
  "
kbenzie commented 9 years ago

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

egalpin commented 9 years ago

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

wbyoung commented 9 years ago

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.

mikew commented 9 years ago

@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>"
relaxdiego commented 9 years ago

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

guyfedwards commented 9 years ago

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

mellery451 commented 9 years ago

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

reward-yourself commented 7 years ago

@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.

kbenzie commented 7 years ago

@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.

reward-yourself commented 7 years ago

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

montogeek commented 7 years ago

@kbenzie Where should I put that function?

kbenzie commented 7 years ago

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

montogeek commented 7 years ago

@kbenzie Thanks!

pspencil commented 7 years ago

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

puremourning commented 4 years ago

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

bguo068 commented 3 years ago

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>"
einthusan commented 3 years ago

@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>"
puremourning commented 2 years ago

THere's nothing we're going to change here. Using the ultisnips trigger after selecting the snippet is a sufficient workflow for the last near-decade.