-
Notifications
You must be signed in to change notification settings - Fork 8k
Support registering a cover-all completer for native commands #25230
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
Conversation
|
@MartinGC94 can you please review this PR when you have time? Thank you! |
src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs
Show resolved
Hide resolved
src/System.Management.Automation/engine/CommandCompletion/ExtensibleCompletion.cs
Show resolved
Hide resolved
src/System.Management.Automation/engine/CommandCompletion/ExtensibleCompletion.cs
Show resolved
Hide resolved
|
Only one of these catch-all completers can be registered and it sounds like you are planning on doing that in |
|
Since we say about interactive session I believe the user knows what they want. If the user loads UnixTabCompletion they want the behavior. If they load a module with another completer they want another behavior. Otherwise, the loading order will be affected, which is even worse. One thing we could consider is that if last resort completer has already been added, then when trying to add a new one, throw and require explicit deletion of the previous one before adding new. |
|
It's not a user setting, it's an implementation detail. MS has made this unix completer module and plan on using this "catch-all" in their implementation. If someone else decides to make a similar module that covers some other commands then the user won't be able to use both modules at the same time. Throwing an error will let the user know that they can't use both at the same time but ideally one module shouldn't block another unless there's a good reason for it. |
The module loaded last always overlaps the previous ones. It's always been that way. (In some cases, we may use fully qualified names) |
Is it though? If both modules include their own "catch-all" completer that is applied, then there are 3 possible scenarios when completing a command parameter: The only bad scenario is scenario 3, but even that isn't that bad because presumably, whoever made the worse completer still made a completer that is "good enough". Scenario 3 could also happen if a module includes a named completer so it never reaches the other modules "catch-all" completer. |
Interesting idea! However, I doubt about if there really will be another catch-all completer except for the I labelled this PR to be reviewed by the console interactive WG. At the meanwhile, @SeeminglyScience, what do you think? |
|
I agree that people should try to register completers by their real command name, but for the same reasons you need it for |
|
The scenario with the second module does not seem vital to me. If someone is going to create add-ons for new Unix commands, then they should not write a new module, but create add-ons for bash completion and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry this is late, I apparently never clicked submit review :(
| { | ||
| key = ParameterName; | ||
| } | ||
| table.Remove(key); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know that I'm suggesting a larger change here, but the pattern is typically Get-* | Unregister-*. Treating null as remove will potentially hide some design time errors like passing a misspelled variable name.
I definitely understand the need but I'd suggest tackling that separately
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally agree there should be Get-ArgumentCompleter and Unregister-ArgumentCompleter cmdlets for better discoverability and manageability! I will open an issue to track.
For Register-ArgumentCompleter, today its behavior when specifying -ScriptBlock $null is to blindly set null to completerDictionary[key]. It essentially disables the previous setting for key without clearing that entry. So, change in this PR only just clear that key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Opened #25800 (Consider adding Get-ArgumentCompleter and Unregister-ArgumentCompleter for custom completer management)
src/System.Management.Automation/engine/CommandCompletion/ExtensibleCompletion.cs
Show resolved
Hide resolved
|
|
||
| // For a native command, if a cover-all completer is registered, then return it. | ||
| // For example, the 'Microsoft.PowerShell.UnixTabCompletion' module. | ||
| if (isNative && registeredCompleters.TryGetValue("*", out scriptBlock)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So two things to consider here
- Linux can have a binary named
* - If we document
*as the catch all that might make it seem like we're generally supporting wildcard matching in the command name
What about a parameter called -Fallback that can't be used with Name? Then either stored in a different field, as null in registeredCompleters, or as some series of unlikely characters?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SeeminglyScience, sorry for the long delay. I've updated the code to introduce a new switch parameter -NativeFallback. The key used for the fallback completer should be unlikely a file name or path. Can you please take another look? Thank you!
|
The Interactive WG discussed the issue regarding multiple catch all completers today. For the first iteration of this we think it's best to keep to a single registered completer due to implementation concerns. If there is demand we will consider additional changes to support it. |
225e56a to
9a49ded
Compare
| private const string NativeFallbackSetName = "NativeFallbackSet"; | ||
|
|
||
| // Use a key that is unlikely to be a file name or path to indicate the fallback completer for native commands. | ||
| internal const string FallbackCompleterKey = "___ps::<native_fallback_key>@@___"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dictionary cannot take $null as the key, so I have to create a special key to indicate the fallback completer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! ❤️
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
Will this in 7.6? |
We haven't started the last 7.6 preview release yet. So yes, this one will be included :) |
PR Summary
This PR contains the following changes:
Refactor
Register-ArgumentCompleterto make it-ScriptBlockisnull(currently it keeps the key value pair but only set the value to null)Add the parameter
-NativeFallbackto support registering a cover-all completer for native commands.Microsoft.PowerShell.UnixTabCompletionto hook up with PowerShell to provide tab completion for many native commands on Linux and macOS systems.With this change, a new parameter set gets added (which includes the parameter
-NativeFallback)PR Context
The module
Microsoft.PowerShell.UnixTabCompletionis designed to leverage the completion system ofBashandZshto provide tab completion for native utilities on Linux and macOS systems that already have completion support forBashorZsh. However, today, a native command completer has to be associated with a specific command, so theUnixTabCompletionmodule needs to discover all native utilities ahead of time and register a proxy completer for each of them, which not only takes time but also cannot pick up any utilities installed later. It will be helpful to support a cover-all completer so that if there is no specific completer registered for a native command, then we fall back to the cover-all completer for it.PR Checklist
.h,.cpp,.cs,.ps1and.psm1files have the correct copyright headerWIP:or[ WIP ]to the beginning of the title (theWIPbot will keep its status check atPendingwhile the prefix is present) and remove the prefix when the PR is ready.- [ ] Issue filed: The parameter
-NativeFallbackis added toRegister-ArgumentCompleterto support registering a cover-all completer for native commands MicrosoftDocs/PowerShell-Docs#12321