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

Implement argument completion/hints #234

Closed
oblitum opened this issue Apr 6, 2013 · 151 comments · Fixed by #3412
Closed

Implement argument completion/hints #234

oblitum opened this issue Apr 6, 2013 · 151 comments · Fixed by #3412

Comments

@oblitum
Copy link
Contributor

oblitum commented Apr 6, 2013

int foo(int a, int b, int c);
void bar(int a, int b);

bar(foo(1, 2, 3), 42);
// bar<ctrl-space> + selection brings bar's prototype into preview window:
// int bar(int a, int b);
// foo<ctrl-space> + selection brings foo's prototype into preview window, destroying previous bar completion context.
// now to fill out the remaining bar parameters after the first one, I must recall them.

clang_complete completion mechanism (+ supertab) is much nicer than this:

int foo(int a, int b, int c);
void bar(int a, int b);

bar(foo(1, 2, 3), 42);
// bar<tab> + selection *inserts* bar's call into code with traversable parameters:
// bar(<#int a#>, <#int b#>)
// foo<tab> + selection *inserts* foo's call into code with traversable parameters:
// bar(foo(<#int a#>, <#int b#>, <#int c#>), <#int b#>)
// to cycle between parameters you just go to normal mode and press tab. Then, you can just start typing to automatically enter insert mode, overwriting the selected one.
// this way, you never lose completion context for nested completions.
// there's an option to hide the characters used to surround the parameters using VIM's conceal feature, so <# and #> may not even clutter the view.

This video (at time 2m30s) illustrates how this parameter completion works.

And this is a GIF from a fork that patches YCM to provide this:

param completion

I guess this behavior turns the extra preview window popup completely unnecessary, and hence, discarding it provides yet one more feature: less interface cluttering. So it's both cleaner and more powerful.

I'm willing to switch to YCM, but still, without this, I feel it doesn't obsoletes clang_complete. It's the single thing that I very miss.

This is the clang_complete/supertab config for that:

set conceallevel=2
set concealcursor=vin
let g:clang_snippets=1
let g:clang_conceal_snippets=1
let g:clang_snippets_engine='clang_complete'

" Complete options (disable preview scratch window, longest removed to aways show menu)
set completeopt=menu,menuone

" Limit popup menu height
set pumheight=20

" SuperTab completion fall-back 
let g:SuperTabDefaultCompletionType='<c-x><c-u><c-p>'

http://stackoverflow.com/a/13548812

Usage of conceal is explained at clang_complete docs.

Regards.

@skogler
Copy link

skogler commented Apr 7, 2013

+1 from me, I recently switched and I miss this a lot.

@Valloric
Copy link
Member

Valloric commented Apr 7, 2013

Agreed, something like this needs to be added (and will). I've talked about this in issue #36. An even better system would be having something like what's present in jedi-vim (which works only with Python code) where the parameter types are placed above the current line. See the very bottom of this screenshot:

AFAIK this is a massive hack enabled by heavy abuse of Vim's conceal feature, but if it ends up working the way I envision it, then I'm willing to hack my way to this functionality.

If that does not end up working well, I'll be going with what clang_complete does by leveraging UltiSnips.

@meh
Copy link
Contributor

meh commented Apr 7, 2013

Woah, that would be awesome.

@oblitum
Copy link
Contributor Author

oblitum commented Apr 7, 2013

Cool.
Just a note, at the time I could not get UltiSnips nor SnipMate to work seamlessly as their own let g:clang_snippets_engine='clang_complete'. Their snippets engine is predictable, aways works the same, and also, personally I like the ability of cycling parameters in normal mode. I guess this simple <#, #> solution turns it more error proof than integration with other plugins. I'm not sure what can be benefited from UltiSnips/SnipMate when libclang is able to provide parameters and parameters info through CXTranslationUnit_IncludeBriefCommentsInCodeCompletion which can be leveraged in a custom crafted solution.

@oblitum
Copy link
Contributor Author

oblitum commented Apr 7, 2013

My opinion is that those plugins are sure good for code snippets, but not so well targeted for parameters. One issue with UltiSnips for example is that if you mistakenly traverse to the last parameter without filling a previous one, it's game over, you can't go back in the parameter list because it's not based on special matches (e.g. <# and #>), reaching the last one is its way of assuming the ending of the filling process. So you're left to go back, select and replace the text manually.

@oblitum
Copy link
Contributor Author

oblitum commented Apr 7, 2013

Also, that jedi-vim pic of yours is very appropriate since clang_complete currently has issues with inputting default parameters (tuple=None).

@zhaocai
Copy link
Contributor

zhaocai commented May 22, 2013

:+1 I enabled jedi-vim just for this feature.

@vheon
Copy link
Contributor

vheon commented Jul 2, 2013

Any news about the jedi like feature? I know that @Valloric want to do a Client Server architecture with YouCompleteMe so I imagine that he is preoccupied with something else at the moment, but I'd love to see something like that in YouCompleteMe 👍

@RobertBuhren
Copy link

Yeah, i'd love that too!

@oblitum
Copy link
Contributor Author

oblitum commented Oct 31, 2013

@vheon it seems like the client server architecture is already in good enough shape into master :)

@vheon
Copy link
Contributor

vheon commented Oct 31, 2013

@oblitum yeah, I notice it :) I keep waiting and I'm curious about how @Valloric will deal with this feature, although I'm not sure it will come soon.

@jsholmes
Copy link

This would be a really great feature.

@PlasmaHH
Copy link

This is indeed a feature I am missing from clang_complete. In the meantime, what would improve the situation a bit at least for me, would be to include all overloads of a function in the dropdown list, so that we can at least see there are some. Using the preview window for that is really ugly.

@senft
Copy link

senft commented Feb 19, 2014

Hey, is this something that is still worked on?

@oblitum
Copy link
Contributor Author

oblitum commented Mar 3, 2014

@PlasmaHH implementation for argument completion to work like clang_complete would probably need to list overloads in popup, instead of the way it's implemented now.

@oblitum
Copy link
Contributor Author

oblitum commented Mar 12, 2014

For anyone interested in a behavior just like clang_complete's parameter completion using g:clang_snippets_engine='clang_complete' I started a preliminary work under oblitum/YouCompleteMe/tree/clang_complete-params. The behavior can be viewed in this video:

http://youtu.be/hCI-EuptQv8
https://docs.google.com/file/d/0B0_mzHzbl3GbLUJqZW55SlRwN1k (more recent)

It's just the same simple but fast parameter completion approach. Right now it's just a patch over the original YCM's ClangCompleter, if I turn it into something more modular I'll try a pull-request but for now it serves as a preview. Since I'll keep using it I'll make fixes if I find dirty corners.

Also the preview windows instead of just showing overloads, since now they "all" show up in the popup, it's also supposed to show brief comments with the accompanying prototype. But so far, even trying to enable all libclang flags to get these brief comments, I was unable to make them show up here in my machine. If anyone can help with extracting brief comments (if it's working in libclang anyway) I would appreciate.

@florian-wagner
Copy link

Am 12.03.2014 21:38, schrieb Francisco Lopes:

For anyone interested in a behavior just like clang_complete's
parameter completion using |g:clang_snippets_engine='clang_complete'|
I started a preliminary work under
oblitum/YouCompleteMe/tree/clang_complete-params
https://github.com/oblitum/YouCompleteMe/tree/clang_complete-params.
The behavior can be viewed in this video:

http://youtu.be/e7w9q99mA6I

it's just the same simple but fast parameter completion approach.
Right now it's just a patch over the original YCM's ClangCompleter, if
I make it turn into something more modular I'll try a pull-request but
for now it serves as a preview. Since I'll keep using it I'll make
fixes if I find dirty corners.

Also, I have disabled the preview window in my |.vimrc| but this
branch also changes its behavior. Instead of showing overloads, since
now they all show up in the popup, it's supposed to show brief
comments with the accompanying prototype. But so far, even trying to
enable all libclang flags to get these brief comments, I was unable to
make them show up here at my machine, hence I've just disabled the
preview window in my |.vimrc|.


Reply to this email directly or view it on GitHub
#234 (comment).

Video has been removed by the author!?

@oblitum
Copy link
Contributor Author

oblitum commented Mar 13, 2014

@florian-wagner check the new link, I have made some updates.

@RobertBuhren
Copy link

Looks awesome. This should be merged with mainline :)

@rhlobo
Copy link

rhlobo commented Mar 13, 2014

Looks great!

@rhlobo
Copy link

rhlobo commented Mar 16, 2014

I am using jedi-vim together with YCM...
This way I get to use YCM and earn some extra nice features such as better argument completion (as shown in the image a few comments ago)

In order to prevent conflicts, I disable most of jedi-vim that is related to completion:

    " jedi-vim {
        let g:jedi#auto_vim_configuration = 0
        let g:jedi#popup_on_dot = 0
        let g:jedi#popup_select_first = 0
        let g:jedi#completions_enabled = 0
        let g:jedi#completions_command = ""
        let g:jedi#show_call_signatures = "1"

        let g:jedi#goto_assignments_command = "<leader>pa"
        let g:jedi#goto_definitions_command = "<leader>pd"
        let g:jedi#documentation_command = "<leader>pk"
        let g:jedi#usages_command = "<leader>pu"
        let g:jedi#rename_command = "<leader>pr"
    " }

@bstaletic
Copy link
Collaborator

@blayz3r That actually doesn't seem like a bad idea.

The quick and dirty solution is to add sig_label = sig_label[ sig_label.find( '(' ) : ] below this line.

The problem with that is that it assumes that a function call looks like foo(bar), but what about lisp's (+ 2 3) or some weird language with foo[bar] (assuming that such a thing exists)?

Right now that assumption holds, but with ycm-core/ycmd#1245, YCM won't be able to make that assumption and we actually need to respect the trigger characters.

@bstaletic
Copy link
Collaborator

Back with a better patch, though it would still fail if the trigger is something insane like (( or ... This is because we store triggers as regexes and my patch only strips leading escape characters.

diff --git a/ycmd/completers/completer_utils.py b/ycmd/completers/completer_utils.py
index 1e1a86bc..d8709b33 100644
--- a/ycmd/completers/completer_utils.py
+++ b/ycmd/completers/completer_utils.py
@@ -66,6 +66,12 @@ class PreparedTriggers( object ):
     self._filetype_to_prepared_triggers = final_triggers
 
 
+  def GetTriggerCharactersForFiletype( self, filetype ):
+    trigger_regex_set = self._filetype_to_prepared_triggers[ filetype ]
+    return [ trigger.pattern.lstrip( '\\' ) for trigger in
+             self._filetype_to_prepared_triggers[ filetype ] ]
+
+
   def SetServerSemanticTriggers( self, server_trigger_characters ):
     self._server_trigger_map = {
       ','.join( self._filetype_set ): server_trigger_characters
diff --git a/ycmd/completers/language_server/language_server_completer.py b/ycmd/completers/language_server/language_server_completer.py
index 87071427..0f4ba889 100644
--- a/ycmd/completers/language_server/language_server_completer.py
+++ b/ycmd/completers/language_server/language_server_completer.py
@@ -1058,6 +1058,20 @@ class LanguageServerCompleter( Completer ):
     response = self.GetConnection().GetResponse( request_id,
                                                  msg,
                                                  REQUEST_TIMEOUT_COMPLETION )
+    result = response[ 'result' ]
+    filetype = self._CurrentFiletype( request_data[ 'filetypes' ] )
+    trigger_characters = (
+        self.signature_triggers.GetTriggerCharactersForFiletype(
+          filetype ) )
+    for sig in result[ 'signatures' ]:
+      sig_label = sig[ 'label' ]
+      indices = []
+      for trigger in trigger_characters:
+        index = sig_label.find( trigger )
+        if index != -1:
+          indices.append( index )
+      sig_label = sig_label[ min( indices ) : ]
+      sig[ 'label' ] = sig_label
 
     return response[ 'result' ]
 

@blayz3r
Copy link

blayz3r commented Aug 14, 2019

Just curious how this is going

@puremourning
Copy link
Member

work in progress. you can use it (it's totally stable) using my signature-help branch of YCM.

I use it every day, but I'm willing to tolerate some jankiness.

The hardest thing to get right is the popup placement and that's where the most work is required.

@blayz3r
Copy link

blayz3r commented Aug 14, 2019

@puremourning thanks for the update, I'll take it for a spin. One thing I wasn't clear on: Does Vim allow the signature to have syntax highlighting?

@puremourning
Copy link
Member

You mean in the popup ? In theory yes (the popup is a buffer), but tbh I don't see how that would mix well with the PMenu highlight groups, and without that there would be no contrast. I'm completely against using borders for this, so that sort of rules it out. But I suppose it is something worth trying (feel free to play with python/ycm/signature_help.py:UpdateSignatureHelp)

@blayz3r
Copy link

blayz3r commented Aug 14, 2019

You mean in the popup ? In theory yes (the popup is a buffer), but tbh I don't see how that would mix well with the PMenu highlight groups, and without that there would be no contrast. I'm completely against using borders for this, so that sort of rules it out. But I suppose it is something worth trying (feel free to play with python/ycm/signature_help.py:UpdateSignatureHelp)

Great thanks

@skywind3000
Copy link

Great, when will it get merged ?

@puremourning
Copy link
Member

When it is ready. And when we have the time. Testing and feedback welcome.

@skywind3000
Copy link

It is convenience to include it in the master and make it disabled by default, and could be enabled manually.

I believe this is much easier for users to test, and you can collect more feedbacks. Rather than leaving it in other branches. (no body knows there is a branch).

@bstaletic
Copy link
Collaborator

There's a pull request where Ben is working on the feature. To merge the PR locally do:

  • cd YouCompleteMe
  • git fetch origin +refs/pull/3412/merge:sig_help
  • git checkout sig_help
  • cd third_party/ycmd
  • git fetch origin +refs/pull/1255/merge:sig_help
  • git checkout sig_help

The pull request (#3412) referenced this thread.

@puremourning
Copy link
Member

puremourning commented Aug 16, 2019

It is convenience to include it in the master and make it disabled by default, and could be enabled manually.

No. This is excruciatingly risky and we won't risk the thousands of users that don't want to test unstable stuff.

@puremourning
Copy link
Member

puremourning commented Aug 16, 2019

it's not so hard:

cd /path/to/YCM
git remote add pm https://github.com/puremourning/YouCompleteMe
git fetch pm
git checkout signature-help
git submodule sync --recursive
git submodule update --init --recursive
./install.py --clangd-completer <usual stuff>

@skywind3000
Copy link

No. This is excruciatingly risky and we won't risk the thousands of users that don't want to test unstable stuff.

Even if it is disabled by default ?

@puremourning
Copy link
Member

Yes.

@skywind3000
Copy link

That's fair, you are the author (Everything is up to you).

@blayz3r
Copy link

blayz3r commented Aug 16, 2019

Took it for a spin and it looks promising, only comment is that having the function name repeated in the signature threw me off a bit I believe there is a patch here. Just my 2 cents.

I am curious if having the name in the signature helps or hurts the popup placement issue

@puremourning
Copy link
Member

I assume you're talking about python ?

If so having the function name there makes it consitent with all of the language servers i've tested, which i think is better because it's even more jarring when it looks different in different languages.

@blayz3r
Copy link

blayz3r commented Aug 16, 2019

@puremourning yep python, ok cool.

Thanks for all your work on this BTW

@miallo
Copy link

miallo commented Oct 2, 2019

it's not so hard:

cd /path/to/YCM
git remote add pm https://github.com/puremourning/YouCompleteMe
git checkout signature-help
git submodule sync --recursive
git submodule update --init --recursive
./install.py --clangd-completer <usual stuff>

Just in case anyone is just blindly copy/pasting the commands: after git remote add... you need to run git pull pm ;)

@puremourning
Copy link
Member

git fetch pm actually.

@ghost
Copy link

ghost commented Oct 13, 2019

it's not so hard:

cd /path/to/YCM
git remote add pm https://github.com/puremourning/YouCompleteMe
git fetch pm
git checkout signature-help
git submodule sync --recursive
git submodule update --init --recursive
./install.py --clangd-completer <usual stuff>

When I run git submodule update --init --recursive (after running sync), I get

error: Server does not allow request for unadvertised object 31d3137f9a9c1ea01f0e1b588e4dc4912adf0244
Fetched in submodule path 'third_party/ycmd', but it did not contain 31d3137f9a9c1ea01f0e1b588e4dc4912adf0244. Direct fetching of that commit failed.

@puremourning
Copy link
Member

Try again now - I pushed some updates just now.

@mergify mergify bot closed this as completed in #3412 Oct 22, 2019
@skywind3000
Copy link

awesome !!

@blayz3r
Copy link

blayz3r commented Nov 9, 2019

Been using this and it is working way better than I expected. Thanks everyone who worked on this and for taking the time to get it right.

@puremourning
Copy link
Member

Thanks for your kind words 😊. wouldn’t have been possible without Incredible work from @brammool and @bstaletic And not to mention all the language server authors.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.