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

Customize order of completions? #64

Open
BalduinLandolt opened this issue Nov 22, 2019 · 4 comments
Open

Customize order of completions? #64

BalduinLandolt opened this issue Nov 22, 2019 · 4 comments

Comments

@BalduinLandolt
Copy link

Thanks for the great packages! I'm using RSyntaxTextArea for a tool to speed up transcribing medieval manuscripts.

Now I'm trying to implement code completion too.
But BasicCompletion doesn't really help me all that much, as it sorts alphabetically.

Instead, I want all the words in the transcription to show up as completions, sorted by how often they appear in the transcription. (Assuming that words that have been common so far, would be more likely to show up again.)

My spontaneous approach was to write a Class WeightedCompletion extending BasicCompletion, with an integer weight (how often the word appears). That class, appart from adding the constructors with weight, overrides compareTo:

        @Override
        public int compareTo(Completion other){
            if (other instanceof WeightedCompletion){
                WeightedCompletion wc = (WeightedCompletion)other;
                int res = -1*Integer.valueOf(getWeight()).compareTo(Integer.valueOf(wc.getWeight()));
                if (res == 0)
                        return super.compareTo(other);
                return res;
            } else {
                return super.compareTo(other);
            }
        }

This works quite neatly when the caret is at the beginning of a new line of after a blank space, whren I hit Ctrl+Space: The completions all appear in the right order.
But, when I start typing a letter, and then hit Ctrl+Space, no code completion popup shows up anymore.

I have not been able to track the problem down, really... but clearly it doesn't like my compareTo.

Long story short: Is there a good way of getting completions in an order other than alphabetical, that I'm missing?

Any ideas/help would be greatly appreciated!

@paul-griffith
Copy link
Contributor

In your CompletionProvider, if you're extending AbstractCompletionProvider, you can override getCompletionByInputText to do something like:

return completions.stream()
	.filter(comp -> comp instanceof WeightedCompletion)
	.filter(comp -> comp.getInputText().startsWith(inputText))
	.sorted(Comparator.comparingInt(WeightedCompletion::getWeight))
	.collect(Collectors.toList());

No need to write the custom comparator yourself.

@antimatter84
Copy link

antimatter84 commented Jul 9, 2021

I too have a problem with the sorting. I just want to retain the order in which the completions are added to the provider. I adapted @paul-griffith 's solution to this:

return completions.stream()
    .filter(comp -> comp.getinputText().startsWith(inputText)
    .collect(Collectors.toList());

I also replaced the addCompletion() and addCompletions() methods with an implementation that does NOT sort after adding a completion. Debugging of my CompletionProvider (extends DefaultCompletionProvider) shows, that the completion objects are then in the order I add them.

But somewhere still a sorting occurs (maybe CompletionProviderBase/AbstractCompletionProvider) and they are not shown in the desired order. How can this be achieved?

SOLVED:
I have extended BasicCompletion and there I override compareTo() to always return 0. This leaves the order of the completions unchanged.

@tttwang23
Copy link

In these situations it is easier to sort using an external comparator. It is less buggy if all completions are ordered by source text only (say case insensitive primary ordering, then case sensitive secondary ordering). If you hack compareTo() then inserting completions into a sorted collection will have unpredictable behaviors.

@ptorngren
Copy link

ptorngren commented Dec 22, 2022

I have the same issue, and have solved it by using an external comparator that I apply by overriding org.fife.ui.autocomplete.CompletionProviderBase.getCompletions(JTextComponent comp):

public List<Completion> getCompletions(JTextComponent comp) {
List<Completion> completions = super.getCompletions(comp);
completions.sort(CompletionComparator.INSTANCE);
return completions;
}

However, this adds a third sort to the operation. Probably not a big issue, but it would have been nice to be able to replace the default org.fife.ui.autocomplete.CompletionProviderBase.SORT_BY_RELEVANCE_COMPARATOR,

By converting this to a regular field with an option to set it externally (or in the constructor), I could easily set my own sort algorithm without the need to override the method and add an extra sort.

Another option that at least takes away the extra sort is to offer the ability to disable the relevance by setting a "sortByRelevance" flag that seems to have been prepared:

if (/*sortByRelevance*/true) {
completions.sort(SORT_BY_RELEVANCE_COMPARATOR);
}

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