prabirshrestha / vim-lsp

async language server protocol plugin for vim and neovim
MIT License
3.14k stars 305 forks source link

Support preselect? #424

Closed clason closed 4 years ago

clason commented 5 years ago

Does vim-lsp support the preselect property in CompletionItem? I have a language server (texlab) that uses this in situations where there is a clear, objective "best match" (closing matching begin-end pairs).

thomasfaingnaert commented 5 years ago

@clason I believe this is not implemented yet. I'm not sure if there is actually a nice way to preselect an item with Vim's complete() API. Querying the selected item index seems to be possible using complete_info, but I'm not sure if we can actually set the selected item. Of course, an ugly solution is to just feed the right amount of CTRL-N to select the correct item, although I'm not really a fan of this approach.

clason commented 5 years ago

@thomasfaingnaert An easier "fake" would be to simply put the preselected candidate on top of the list (and possibly unsetting and then setting noselect).

(It's not critical, I merely thought it would be nice to have.)

thomasfaingnaert commented 5 years ago

@clason That's indeed a better solution, I'll check tomorrow if this works for both omnifunc and asyncomplete.

thomasfaingnaert commented 5 years ago

@clason Is this already implemented in texlab's master? I tried this with:

\documentclass{article}

\begin{document}
\begin{equation}

\end{<C-x><C-o>
\end{document}

and I don't see any items with preselect: true. (I did set capabilities.textDocument.completion.completionItem.preselectSupport to true) Or am I misunderstanding how this works?

clason commented 5 years ago

It is (https://github.com/latex-lsp/texlab/commit/7fa581301431178a4a097554ef41501215b2a159, which is included in the new binaries from https://github.com/latex-lsp/texlab/releases) and working in VS Code:


[2019-07-04 18:33:04] {"jsonrpc":"2.0","result":{"data":"Environment","detail":"built-in", "insertTextFormat":1,"kind":20,"label":"equation","preselect":true,"textEdit":{"newText":  "equation","range":{"end":{"character":5,"line":6},"start":{"character":5,"line":6}}}},    "id":50}Content-Length: 198

I'm not sufficiently familiar with the low-level communication between client and server, but maybe the recent changes to the client registration are relevant here (https://github.com/latex-lsp/texlab/commit/86046e795e2c862ab412e2c9f34ac9b51ffe020c, https://github.com/latex-lsp/texlab/commit/db162c7d5a46e1a393d1ffd55d013cf553e5a54e, https://github.com/latex-lsp/texlab/commit/3c494315cbcce9c54781e5563929599b431f1552)?

thomasfaingnaert commented 5 years ago

@clason Seems that you need the closing }, as it works with \end{<C-x><C-o>}, but not with \end{<C-x><C-o> (VSCode behaves the same). I've started implementing preselect in https://github.com/thomasfaingnaert/vim-lsp, branch preselect-item. At the moment, the preselected item is only put on top of the completion list, not preselected. It doesn't seem like completeopt-=noselect works, at least on my machine.

clason commented 5 years ago

@thomasfaingnaert Good catch -- I didn't notice because VS Code auto-closes braces before triggering completion. With the closing braces, vim-lsp omni-complete (but not ncm2-vim-lsp autocomplete) already correctly puts the preselected item on top of the list. This is good enough for me; arguably (at least in vim-land) automatic selection of completion items should be a user choice.

(That's a question I've been wondering about, by the way: How to configure vim-lsp to auto-insert closing braces after selecting a completion in different contexts.)

thomasfaingnaert commented 5 years ago

@clason Ah you're right, it seems that the changes in preselect-item are not even necessary. My guess is that the language server places preselect items in front, and vim-lsp copies the order, whereas ncm2 applies custom sorting.

As for auto-insert closing braces, I don't think that the LSP protocol includes it, so clients would have to do their best themselves to autoclose. For now, a simple mapping may or may not satisfy your needs:

inoremap { {}<Left>

though personally, I find autoclosing more annoying than helpful and prefer to type closing braces myself.

thomasfaingnaert commented 5 years ago

@clason For autoclosing e.g. \end{ with an } on completion, something like this in your vimrc should work:

function! AutoClose()
    let l:current_line = strpart(getline('.'), 0, col('.') - 1)
    if l:current_line =~ '{\w\+$'
        call feedkeys('}')
    endif
endfunction

augroup test
    autocmd!
    autocmd CompleteDone * call AutoClose()
augroup end

Peek 2019-07-05 15-19

Of course, this is a quick hack-ish solution, but it may be a good starting point to expand on.

clason commented 5 years ago

@thomasfaingnaert Re sorting: That makes sense; I'll look into how ncm2 sorts (or not). EDIT: Indeed, ncm2 sorts by default; adding 'sorter': 'none' to the ncm2-vim-lsp source gives the same result as for autocomplete. Do you think that should be changed in ncm2-vim-lsp? Then I'd open an issue about it.

I agree about autoclosing; I definitely don't want that in general -- nor even for autocomplete (think \cite{A,B}). My quick hack is actually

au Filetype tex inoremap <expr> <CR> (pumvisible() ? "\<c-y>}" : "\<CR>")

so I can just press enter to accept the candidate and close the brace, or continue typing something else (like ,). In TeX (as opposed to, e.g., Python), it's very rare to have a completion candidate right before a line break.

Is there any chance of making preselect work without the closing brace?

thomasfaingnaert commented 5 years ago

@clason Definitely a good idea to open an issue in ncm2-vim-lsp to at least discuss it. What do you mean with "completion candidate right before line break"? Both solutions would still work then, I believe. As for preselect, I'm not sure yet why the completeopt-=noselect is not working, do you have the same issue? If so, maybe adding a feedkeys of C-n is good as a temporary solution?

EDIT: Seems to be a conflict with my vimrc.

clason commented 5 years ago

@thomasfaingnaert Will do (on a related note, while testing this I found a comment " FIXME sync call should be implemented in vim-lsp -- I think sync calls are in fact implemented now, is that right?

All I meant is that in my experience, I never want to accept a candidate and insert a line break right after that, so (ab)using as "accept and close braces" doesn't hurt (because otherwise I'd have to add extra keystrokes to delete the brace and enter the line break, which would be inconvenient).

I didn't test the -=noselect option, because putting the preselected candidate first in the list is good enough for me; I'm also not familiar enough with vim-lsp to make such changes myself. Adding a <c-n> seems like a good hack, though.

thomasfaingnaert commented 5 years ago

@clason Ah I see what you meant. I'm not sure about the sync calls, I've only recently started contributing, but you may be right.

noselect worked, it just conflicted with some settings I added in my vimrc, although I definitely agree that we should leave the completeopt up to the user.

Is the current behaviour of master good enough for you, or would you like I create a PR with the changes from preselect-item (which just sorts so the preselect items are in front, but it seems texlab already does this)?

clason commented 5 years ago

@thomasfaingnaert I'll open an issue about it and see what happens; the current FIXME works, so it's bound to be low priority anyway.

The current behavior of master is fine with me (although I don't see your branch so I can't say if there's additional goodies in there), if I can make it work without the closing brace... I don't know if there are other language servers with this feature (C#?) that behave differently though?

thomasfaingnaert commented 5 years ago

@clason It should be publicly available at https://github.com/thomasfaingnaert/vim-lsp/tree/preselect-item, no? No real goodies, basically just a call to sort with a custom sorter. I have not found any other language server that has preselect, so I'm not sure how they handle it. Maybe better to wait for now, as the sorting with a long completion list may make vim-lsp slower?

As for the closing brace, that seems an issue with the language server, so you may want to file report there. I'm not familiar with the codebase, but my guess is that it shouldn't be too much work to fix.

clason commented 5 years ago

@thomasfaingnaert It's public alright; I just didn't think of poking around your personal repositories :)

I agree, let's wait if other people are interested in this and see what they think. For me, this is good enough as is. (Thanks for looking into it!)

I'll bring up the issue with the braces at the language server; for me it's basically a blind guess whether something is an issue with the client or the server :/

thomasfaingnaert commented 5 years ago

@clason I noticed too that it's sometimes hard to pinpoint the issue to the server/client as well. Mostly, I first test with VScode, and if it doesn't work there either it's likely the server. Although, I've seen it's not that simple in all cases, with the autoclosing of } influencing the preselect.

clason commented 5 years ago

The issue with the braces in texlab is now fixed: https://github.com/latex-lsp/texlab/commit/1cddcd00f1b3dcac02fef310067d57e9cfd4bc28

prabirshrestha commented 4 years ago

closing stale issue.