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

Fallback to file completer in custom/external completer #14781

Merged
merged 2 commits into from
Jan 26, 2025

Conversation

ysthakur
Copy link
Member

@ysthakur ysthakur commented Jan 8, 2025

Description

Closes #14595. This modifies the behavior of both custom and external completers so that if the custom/external completer returns an invalid value, completions are suppressed and an error is logged. However, if the completer returns null (which this PR treats as a special value), we fall back to file completions.

Previously, custom completers and external completers had different behavior. Any time an external completer returned an invalid value (including null), we would fall back to file completions. Any time a custom completer returned an invalid value (including null), we would suppress completions.

I'm not too happy about the implementation, but it's the least intrusive way I could think of to do it. I added a fallback field to CustomCompletions that's checked after calling its fetch() method. If fallback is true, then we use file completions afterwards.

An alternative would be to make CustomCompletions no longer implement the Completer trait, and instead have its fetch() method return an Option<Vec<Suggestion>>. But that resulted in a teeny bit of code duplication.

User-Facing Changes

For those using an external completer, if they want to fall back to file completions on invalid values, their completer will have to explicitly return null. Returning "foo" or something will no longer make Nushell use file completions instead.

For those making custom completers, they now have the option to fall back to file completions.

Tests + Formatting

Added some tests and manually tested that if the completer returns an invalid value or the completer throws an error, that gets logged and completions are suppressed.

After Submitting

The documentation for custom completions and external completers will have to be updated after this.

@sholderbach sholderbach added completions Issues related to tab completion pr:breaking-change This PR implies a change affecting users and has to be noted in the release notes labels Jan 8, 2025
@ysthakur ysthakur closed this Jan 17, 2025
@ysthakur ysthakur deleted the custom_completion_opt branch January 17, 2025 16:37
@ysthakur ysthakur restored the custom_completion_opt branch January 17, 2025 17:51
@ysthakur ysthakur reopened this Jan 17, 2025
@ysthakur
Copy link
Member Author

Sorry, accidentally deleted the branch while pruning stale branches on my fork

@WindSoilder
Copy link
Collaborator

WindSoilder commented Jan 21, 2025

I'm not too happy about the implementation, but it's the least intrusive way I could think of to do it. I added a fallback field to CustomCompletions that's checked after calling its fetch() method. If fallback is true, then we use file completions afterwards.

I'm thinking about another solution, what about making CustomCompletions directly depends on FileCompletions as a fallback completion. Like this:

pub struct CustomCompletion<T: Completer> {
    stack: Stack,
    decl_id: DeclId,
    line: String,
    fallback: T
}

Then if it evals Value::Nothing, we can run fallback.fetch directly. In this way, we don't need to expose a boolean fallback field.

@ysthakur
Copy link
Member Author

@WindSoilder Great idea! That also means CustomCompletions can continue implementing the Completer trait

@tmillr
Copy link

tmillr commented Jan 21, 2025

Sorry if this is off-topic, but there should be a way to configure the external completer so that it overrides internal completion. That way, completion becomes entirely customizable by the user (instead of trying to guess what the user wants in these kind of situations).

TLDR

  • Add the config option to override internal
  • Add/define builtin command to retrieve internal completions based on its pipeline input. The result could also include extra metadata, like what the parser is expecting next and the partial string it's basing its suggestions on, etc.
  • External completer can do whatever it wants: fallback however it wants, merge its own suggestions, only use it's suggestions, only use internal suggestions, sort however it wants, complete env variables, complete snippets even, etc. It could even choose not to parse the input at all. etc. etc. etc.

This would be very nice.

@ysthakur
Copy link
Member Author

@tmillr That seems like it could be useful, but could you open a separate issue asking for that feature? I see you added this to #14822, but that's a huge issue and this feature request could get lost there.

@ysthakur ysthakur force-pushed the custom_completion_opt branch from cdd112c to de24ae5 Compare January 22, 2025 04:34
@ysthakur
Copy link
Member Author

@WindSoilder Implemented your solution, it works well.

Copy link
Collaborator

@WindSoilder WindSoilder left a comment

Choose a reason for hiding this comment

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

Thanks! LGTM

@WindSoilder WindSoilder merged commit a011791 into nushell:main Jan 26, 2025
15 checks passed
@github-actions github-actions bot added this to the v0.102.0 milestone Jan 26, 2025
@ysthakur ysthakur deleted the custom_completion_opt branch January 26, 2025 05:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
completions Issues related to tab completion pr:breaking-change This PR implies a change affecting users and has to be noted in the release notes
Projects
None yet
4 participants