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

render completion options by language server priority #7349

Closed
wants to merge 1 commit into from

Conversation

estin
Copy link
Contributor

@estin estin commented Jun 15, 2023

Hi!
On multi ls with completion items rendered without any priority.
This PR groups completion items by language server id.
And in future allows to do some visualization to separate groups

For my use case (on python) with follow config

[language-server]
simple-completion-language-server = { command = "simple-completion-language-server" }

[[language]]
name = "python"
language-servers = [ "pylsp", "simple-completion-language-server" ]

on master, I expects items from pylsp on top of the list, for me it primary ls for completion
as-is

on this PR, all as I expected, on top items from pylsp and on bottom from simple-completion-language-server
with-group

Don't sure about it's nature behavior for other users.
Feel free to close this PR.
Sorry for my poor English.

@poliorcetics
Copy link
Contributor

poliorcetics commented Jun 16, 2023

LGTM, though what is simple-completion-language-server ? A simple text search doesn't give me much results in duckduckgo or github

@poliorcetics
Copy link
Contributor

It may have to be a config option, but I'm unsure about that, let's wait for maintainers :)

@estin
Copy link
Contributor Author

estin commented Jun 16, 2023

@poliorcetics it's https://github.com/estin/simple-completion-language-server
simple and buggy solution for lexical completion #3328

@poliorcetics
Copy link
Contributor

poliorcetics commented Jun 16, 2023

Thank you very much, I'll have a look!

Comment on lines 23 to 35
#[inline]
fn group(&self, _data: &Self::Data) -> usize {
self.language_server_id
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't think of other places we would want to re-use this group concept. Ideally I'd like to see this built in to the sort_text function: something like fn sort_key(&self, data: &Self::Data) -> impl Ord and then CompletionItem's Item implementation would contain the logic for using self.language_server_id. That depends on either rust-lang/rust#91611 to return an impl Ord, or rust-lang/rust#29661 so that we wouldn't have to explicitly implement sort_key in every Item:

pub trait Item {
    type Data;
    type SortKey: Ord = Cow<str>;

    // ...

    fn sort_key(&self, data: &Self::Data) -> Self::SortKey {
        self.filter_text()
    }

    // ...
}

Maybe there's a clever way around the language features here that I'm not seeing though?

There was a similar thread of this idea in #2705 (comment).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While making this an assoc type would be annoying I think it's not the worst thing having to explicitly specify a type

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • removed group concept.
  • introduced Item.score function to control score and sorting

helix-term/src/ui/completion.rs Outdated Show resolved Hide resolved
Comment on lines 23 to 35
#[inline]
fn group(&self, _data: &Self::Data) -> usize {
self.language_server_id
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While making this an assoc type would be annoying I think it's not the worst thing having to explicitly specify a type

@pascalkuthe
Copy link
Member

pascalkuthe commented Jun 17, 2023

I dont think this needs a config option since it only acts as a tie breaker where the order is semi random right now

@estin estin force-pushed the menu-item-ls-priority branch from a29de2c to 08b39a2 Compare June 25, 2023 21:01
@kirawi kirawi added A-helix-term Area: Helix term improvements S-waiting-on-review Status: Awaiting review from a maintainer. labels Jun 30, 2023
@estin estin force-pushed the menu-item-ls-priority branch from bb8c355 to 7a85d52 Compare August 5, 2023 18:51
@estin estin force-pushed the menu-item-ls-priority branch from 7a85d52 to 754b66b Compare August 30, 2023 11:55
@estin estin requested a review from pascalkuthe August 30, 2023 12:13
@estin estin force-pushed the menu-item-ls-priority branch from a87489a to 3b4aa5b Compare September 7, 2023 06:10
@estin estin requested a review from pascalkuthe September 11, 2023 05:58
@estin estin force-pushed the menu-item-ls-priority branch from 3b4aa5b to 90ae281 Compare October 3, 2023 14:40
@estin estin force-pushed the menu-item-ls-priority branch from 90ae281 to 411a655 Compare October 17, 2023 06:26
@estin estin force-pushed the menu-item-ls-priority branch 2 times, most recently from 0397c6b to c6525d0 Compare November 13, 2023 08:14
@estin estin force-pushed the menu-item-ls-priority branch from c6525d0 to 56e4302 Compare November 17, 2023 12:45
Comment on lines 21 to 30
/// Second ordering rule on equals items score
type TieBreaker;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should be able to add a default value here so we don't have to define it in every single implementation.

@@ -29,30 +32,36 @@ pub trait Item: Sync + Send + 'static {
let label: String = self.format(data).cell_text().collect();
label.into()
}

fn tie_breaker(&self, _data: &Self::Data) -> Self::TieBreaker;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I don't like having this extra function, it should be unnecessary because this is the intent of sort_text (should really be renamed as sort_key).

Let's try modifying the return value of sort_text as K: Ord, and use a default that uses Cow<str>. Then for your one specific implementation you can instead return (label, language_server_id) ((Cow<str>, usize))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree we don't want an extra method. I am not sure what the right API is here though.

A couple points:

  • for the picker the concept of sort text does not make sense IMO. In general I think the needs of the picker and of the menu keep diverging (some of mikes colum related work for example) so I think we will likely just endup with two traits (or even something totally different for the picker)
  • for the menu I am not sure how much sense all of this actually makes. It feels wrong to me to sort by language server first since fuzzy matching is not very selective so you would see all the "bad" completions from one server before those from a second server. A score bonus is not a good solution because it's hard to implement (how large should the bonuss shpuld be is subjctive and would depend on word length/content) and ultimately not feel predictable. I proposed making it a tie breaker but exactly identicsl fuzzy scores are not as common as you would think fue to the fairly complex bpnus system. It's probably the least bad option right now.
  • all of this doesn't even take into account yet that we do not actually want to sort for a lot of servers. With incomplete completion request support we have to rerequest completions on every keypress and are not supposed to do filtering and scoring ourself. The question then becomes how to mix those servers with other completion options. The server sorts internslly according to their own criteria and scoring system which we are unaware of and also not comparable. This feature has a really large impact and is very commonly used (and the capability is not respected, for example by RA) so I see it as fairly high priority so such an obvious conflict here is a concern for me.

This makes it hard for me to review since I dont understand the full problem space yet. We may endup needing a very different solution and changing the trait before we have figured that out feels premature. Perhaphs sorting by server first works after all if we filter items with a score below 50% of the top score or something. Ideally we should study what other ides (primarily vscode) do here. There is also a whole can of worms of super long LSP issue trackers where it was discussed how filtering and sorting should work exactly (which can sometimes not have a clear co conclusion, I need to read trough all that carefully again).

One thing I am fairly sure about is that we want this to be (language_server, label) and not the other way around. Score ties are already rare (which is the only situation where sort_text matters) and when they do occur we want to group by language sever first (otherwise the language sever comparison basically never matters anyway).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I am fairly sure about is that we want this to be (language_server, label)

I was assuming that too, but that probably doesn't make sense either since you could have very weak matches from your priority server that would now appear before better matches from a second one.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah no that actually would not happen (currently). Sort text is not used for fuzzy matching. It's only used as a tie breaker if the fuzzy match score is equal.

So sorting would be (fuzzy_score, language_server, label) so the order of these two only takes effect when the score is the same (which is already pretty rare)

@estin estin force-pushed the menu-item-ls-priority branch from 56e4302 to 59bc4ad Compare December 19, 2023 06:43
@estin estin force-pushed the menu-item-ls-priority branch from 59bc4ad to 83242b7 Compare January 14, 2024 12:25
@estin
Copy link
Contributor Author

estin commented Jan 14, 2024

Now PR makes next changes:

  • populate completion menu item by lsp definition order
  • remove duplicated code

@estin
Copy link
Contributor Author

estin commented Feb 10, 2024

rethink on #9590

@estin estin closed this Feb 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-helix-term Area: Helix term improvements S-waiting-on-review Status: Awaiting review from a maintainer.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants