Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Omnifunc is skipped if c-n or c-p or tags are set #179

Open
cideM opened this issue May 19, 2020 · 19 comments
Open

Omnifunc is skipped if c-n or c-p or tags are set #179

cideM opened this issue May 19, 2020 · 19 comments

Comments

@cideM
Copy link

cideM commented May 19, 2020

I have gopls (Golang LSP) installed and I'm using nvim-lsp and the built-in LSP to use gopls for omnifunc completion. When invoked manually via c-x c-o I get gopls completion candidates. It also works if I remove c-n and c-p from my completion chains, so that only omni is left. But as soon as I re-add c-n or c-p omnifunc completion via mucomplete doesn't work. If I manually cycle through the chains it never shows omni.

  • c-x c-o works
  • \ 'go' : ['ulti', 'omni'], works
  • \ 'go' : ['ulti', 'omni', 'c-n'], does not work
@cideM cideM changed the title Omnifunc is skipped Omnifunc is skipped if c-n or c-p or tags are set May 19, 2020
@lifepillar
Copy link
Owner

Can you show the relevant configuration from your vimrc? Even better, can you reproduce your issue with the provided troubleshooting_vimrc.vim (you need to add your settings)?

@lifepillar
Copy link
Owner

Also, can you please provide links to the relevant plugins?

Are you using Vim or Neovim?

@cideM
Copy link
Author

cideM commented May 21, 2020

I'll try to come up with a reproducible example

@cideM
Copy link
Author

cideM commented May 31, 2020

@lifepillar let me know if this repository with a Dockerfile works. At least I can reproduce the issue this way.

@lifepillar
Copy link
Owner

Ok, I see. Does it help to add noselect to completeopt?

@lifepillar
Copy link
Owner

You should also unset g:mucomplete#reopen_immediately and possibly set g:mucomplete#completion_delay (see :help mucomplete-compatibility).

@cideM
Copy link
Author

cideM commented Jun 2, 2020

Unfortunately neither of the two options had any effect on the issue

@lifepillar
Copy link
Owner

Ok, I'll debug further.

@lifepillar
Copy link
Owner

I am wondering whether this is just an issue with MUcompleteNotify. I am using your Docker image for testing and I have set completeopt=menuone,noselect in init.vim. Now, using your main.go, when I type fu followed by Tab I am offered the same completion as when I type fu followed by CTRL-X CTRL-O. Can you provide an example in which the set of completions is different?

@mg979
Copy link
Contributor

mg979 commented Jul 9, 2020

I think the problem is that nvim-lsp omnifunc is actually asynch. I had similar problems with mucomplete and nvim-lsp because mucomplete doesn't handle well asynch sources. When he puts 'omni' alone it works because it's the only one that is called, but if he puts something after it, omni yields no results as far as mucomplete can see (because it's asynch), so mucomplete calls c-n that overwrites omni.

@lifepillar
Copy link
Owner

mucomplete doesn't handle well asynch sources

Well, MUcomplete doesn't handle asynch at all. If that is the culprit, I guess that MUcomplete cannot be used with nvim-lsp.

How is asynchronous completion implemented? With complete()?

@mg979
Copy link
Contributor

mg979 commented Jul 9, 2020

Probably. Anyway, if mucomplete could handle asynch sources it would be a big improvement, considering that lsp-based completions are generally asynch.

@lifepillar
Copy link
Owner

lifepillar commented Jul 9, 2020

That would probably require a rework of the plugin. Currently, MUcomplete is based on strictly sequential fallback: try first source and wait for result; if no result, try second source and wait, etc. Asynchronous completion requires a totally different approach, Maybe, timers might be used; or maybe something else.

@mg979
Copy link
Contributor

mg979 commented Jul 9, 2020

I don't think you'd need to rework everything, for example you could try something like this (I didn't test it...).

Start by keeping a dict of recognized asynch methods/sources, suppose you fill
this list somehow (yourself, or by letting an asynch source to be registered as
such):

" key is the method, value is the callback status
let s:asynch_methods = {'nvim-lsp': 0}

Then when you verify the completion, if the current method is asynch you start
a timer, and delay the verification:

fun! s:verify_completion(...)
  let method = s:compl_methods[s:i]
  if !a:0 && has_key(s:asynch_methods, method)
    if s:asynch_methods[method] == 0
      " completion hasn't been tried yet
      let s:asynch_methods[method] = 1
      call timer_start(100, function('s:verify_completion'))
      return ''
    else
      " keys have been fed by the callback, reset callback status
      " no return value, proceed to check pumvisible()
      let s:asynch_methods[method] = 0
    endif
  elseif a:0
    " this is the timer callback
    call feedkeys("\<Plug>(MUcompleteVerify)")
    return ''
  endif
  return pumvisible()
            \ ? s:act_on_pumvisible()
            \ : (method ==# 'cmd' ? s:ctrlx_out : '')
            \ . s:next_method()
endf

@mg979
Copy link
Contributor

mg979 commented Jul 9, 2020

Btw the problem with this approach is that you have to guess how long to wait (and overestimate it to be safer), it's not like the asynch source calls the next method on its own if it cannot provide completions (it would be ideal but not really possible unless a source supports this behaviour).

Edit: I tried the approach above but I couldn't make it work.

@alexkornitzer
Copy link

Okay, so I am having this issue (or similar) as well and its most prominent when using vim-lsp with pyls. I have no idea what the cause is but I don't believe its due to async as from what I understand vim-lsp is sync by default.
https://github.com/prabirshrestha/vim-lsp/blob/master/doc/vim-lsp.txt#L1709

What I have found that fixes the issue but I have no idea on the fallout or why it works (@lifepillar maybe you could elaborate?) is to skip the pumvisible check on omni.

  257 fun! s:verify_completion()
+ 258   if s:compl_methods[s:i] == "omni"
+ 259     return s:act_on_pumvisible()
+ 260   endif
  261   return pumvisible()
  262            \ ? s:act_on_pumvisible()
  263            \ : (s:compl_methods[s:i] ==# 'cmd' ? s:ctrlx_out : '')
  264            \ . s:next_method()
  265 endf

@lifepillar
Copy link
Owner

@alexkornitzer Could you provide a minimal vimrc to reproduce your issue?

@alexkornitzer
Copy link

Why of course, sorry for not doing that to start so, here is my minimal conf:

if empty(glob("~/.vim/autoload/plug.vim"))
    execute '!curl -fLo ~/.vim/autoload/plug.vim'
    \ 'https://raw.github.com/junegunn/vim-plug/master/plug.vim'
endif
call plug#begin('~/.vim/plugged')
Plug 'prabirshrestha/async.vim'
Plug 'prabirshrestha/vim-lsp'
Plug 'lifepillar/vim-mucomplete'
call plug#end()

set completeopt-=longest,preview
set completeopt+=menu,menuone,noinsert,noselect
set shortmess+=c

if executable('pyls')
  au User lsp_setup call lsp#register_server({
    \ 'name': 'pyls',
    \ 'cmd': {server_info->['pyls']},
    \ 'whitelist': ['python'],
    \ })
  autocmd FileType python setlocal omnifunc=lsp#complete
endif

let g:mucomplete#enable_auto_at_startup = 1
let g:mucomplete#chains = {}
let g:mucomplete#chains.default  = ['path', 'omni', 'c-p', 'dict', 'uspl', 'ulti']

The following to install pyls:

pip install --user python-language-server

And here is the test file I have been using:

aaa
aaaa
aaaaa
aaaaaa

import sys
sys.a

Hitting tab with the cursor after sys.a fails without the change in my comment above.

@inventionate
Copy link

I tried to use the Neovim built-in LSP client (Intelephense language server) in a chain ['omni', 'path', 'c-n'] and encountered exactly this problem. It quickly became apparent that the problem was the asynchrony of the built-in LSP client. One solution is to use the omnifunc function synchronously, but unfortunately this is currently only possible with a separate function. I have posted this in the linked discussion (neovim/neovim#12390). Maybe it will help someone and I am happy to receive suggestions for improvement. Anyway, thanks for the hints.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants