lifepillar / vim-mucomplete

Chained completion that works the way you want!
MIT License
912 stars 18 forks source link

Expand snippet placeholders #188

Open martskins opened 3 years ago

martskins commented 3 years ago

Sorry if this has been documented, I have tried a few different things but I can't seem to make it work as I expect it.

What I'm trying to do is expand the completion item snippets I get from LanguageClient-neovim via a keybinding but the results I've got so far are either have it expand on CompleteDone, which doesn't really work for me because I get expansion on situations were I don't really want to expand (for example when pressing while pum is visible to delete the word I just type and try something else), or it completes and expands but it inserts the placeholders, or it doesn't do any expanding.

In order to reproduce what I'm getting you'd need this vimrc:

set nocompatible
filetype off

call plug#begin()
Plug 'autozimu/LanguageClient-neovim', { 'branch': 'next', 'do': 'bash install.sh' }
Plug 'Shougo/neosnippet.vim'
Plug 'Shougo/neosnippet-snippets'
Plug 'ervandew/supertab'
Plug 'lifepillar/vim-mucomplete'
call plug#end()

filetype plugin indent on

let g:LanguageClient_serverCommands = {}
let g:LanguageClient_serverCommands.go = ['gopls']
let g:LanguageClient_completionPreferTextEdit = 1

set completeopt=noinsert,menuone,noselect
let g:mucomplete#enable_auto_at_startup = 1
smap <C-k>     <Plug>(neosnippet_expand_or_jump)
xmap <C-k>     <Plug>(neosnippet_expand_target)
imap <expr><C-k> pumvisible() ?
  \ mucomplete#neosnippet#expand_snippet("\<c-k>")
    \ : "\<Plug>(neosnippet_expand_or_jump)"

And here's a gif of what I'm getting:

Kapture 2020-11-26 at 21 50 16

Basically what's going on there is I type log.Pri, then move to the Println entry with tab, and press <C-k>. What I would expect there is that it expands the snippet, removes the gibberish from the placeholders and then lets me jump to the placeholders with another press of <C-k>.

Note that if I comment out the LanguageClient_completionPreferTextEdit setting then <C-k> simply closes the pum, which I don't really understand why either, as I would expect it to expand the snippet anyways.

For reference, here's how that looks (even with the setting above commented) with ncm2, which I would love to replace with mucomplete, as it seems a lot simpler and lighter.

Kapture 2020-11-26 at 21 59 04

On another note, I haven't been able to figure out how to configure mucomplete to get more results in the completion menu, as you can see I only get 3 or 4 results but I would like to get more (maybe even all?) completion items there.

lifepillar commented 3 years ago

Does the information in :help mucomplete-compatibility (LanguageClient-neovim and Neosnippet sections) help?

martskins commented 3 years ago

I don't think it does, no. Or at least adding those two options mentioned there doesn't seem to change anything.

lifepillar commented 3 years ago

What do I need on the server side to enable Go completion?

martskins commented 3 years ago

You mean which server? If that's the case then: gopls which you can find here https://github.com/golang/tools/blob/master/gopls/doc/user.md

Also, just realised that you will also need to create a .vim/settings.json file in the project directory with the following for it to use the placeholders:

{
    "initializationOptions": {
        "usePlaceholders": true
    }
}

That's for LanguageClient-neovim to pass that initialization options to gopls so that it uses the placeholders that you saw on my gif.

So the project structure to reproduce this would be something like this:

.
├── .vim
│   └── settings.json
├── go.mod
├── go.sum
└── main.go

The go.mod and go.sum files are created by the go package manager, you can create those by running go mod init.

Sorry for the incomplete instructions in the original message.

lifepillar commented 3 years ago

I need more details, because expanding snippets in general appears to work for me.

Why do you need supertab? It has a mapping conflict with MUcomplete. Can you reproduce your issue without it?

Why haven't you added the 'nsnp' completion method to MUcomplete's chain? That is what allows MUcomplete to offer Neosnippets snippets as completions.

I type log.Pri, then move to the Println entry with tab, and press <C-k>. What I would expect there is that it expands the snippet, removes the gibberish from the placeholders and then lets me jump to the placeholders with another press of <C-k>.

What happens instead? I cannot find a snippet for log.Println in neosnippet-snippets/neosnippets/go.snip, hence when I type log.Println and press CTRL-K it does not expand anything. Is that a snippet you have added yourself?

Anyway, from your top animated GIF above it seems that it has expanded the snippet, so, what exactly is wrong there? I see that the placeholder has the form ${1:v…}, whereas when I expand a snippet the placeholder looks like

<`1…`>

Is that the issue? Also, in your top GIF, some error messages are shown as you are typing. I don't think that has anything to do with MUcomplete.

martskins commented 3 years ago

Yeah sorry, supertab is not really needed here. I removed it and it's still reproducible.

About the nsnp source, I didn't add it because what I'm trying to expand is not a snippet from neosnippet, it's a snippet that is associated with a completion item, it comes from the go's language server, not neosnippet. So log.Println there is not a snippet from neosnippet, it's a completion item provided by LanguageClient-neovim and gopls.

What I'm trying to achieve here is that pressing ctrl-k completes the completion item snippet and then jumps between the arguments of the function (in this case). Here's another gif that might make things clearer:

Kapture 2020-11-29 at 10 06 46

Note that when I first press Ctrl-K the completion item snippet is expanded and the first argumet of the function is selected so that I can replace it by just typing. Pressing Ctrl-K a second time will jump to the second argument.

As for the errors, that's fine, that's just LanguageClient-neovim showing me syntax errors because the file has invalid syntax while I'm completing the snippet.

martskins commented 3 years ago

I guess what I'm looking to do with mucomplete is what ncm2-neosnippet provides https://github.com/ncm2/ncm2-neosnippet.

trigger dynamic snippet of completed item, e.g. parameter expansion.

martskins commented 3 years ago

I managed to make this work by changing mucomplete#neosnippet#do_expand a little, here's how it ended up looking.

fun! mucomplete#neosnippet#do_expand(keys)
  let l:completed_item = v:completed_item
  let l:newtext = s:lsp_snippet(l:completed_item)
  if l:newtext !=# ''
    return neosnippet#anonymous(l:newtext)
  endif

  if get(l:completed_item, 'menu', '') =~# '[neosnippet]'
    return neosnippet#expand(l:completed_item['word'])
  endif

  return a:keys
endf

fun! s:lsp_snippet(completed_item)
  if !has_key(a:completed_item, 'user_data')
    return ''
  endif

  let l:user_data = json_decode(a:completed_item['user_data'])
  if !has_key(l:user_data, 'lspitem')
    return ''
  endif

  let l:lspitem = get(l:user_data, 'lspitem')
  if !has_key(l:lspitem, 'textEdit')
    return ''
  endif

  let l:lspitem = get(l:user_data, 'lspitem', {})
  let l:filter_text = get(l:lspitem, 'filterText')
  let l:new_text = get(l:lspitem['textEdit'], 'newText', '')
  let l:new_text = substitute(l:new_text, l:filter_text, '', '')
  return l:new_text
endf

I'm not sure of the correctness of this and if there are any other things that I should be taking into account, but that seems to work exactly the way I expected it to work for the few tests that I have ran so far.

EDIT: Well, kinda 😁 . It freezes a little while getting the suggestions for Rust this way. And there are some completion items that don't expand as expected, not sure why yet.