-
Notifications
You must be signed in to change notification settings - Fork 8.2k
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
Changes from all commits
fe41b31
72717ae
c13f7ec
9a49ded
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -172,66 +172,110 @@ public abstract class ArgumentCompleterFactoryAttribute : ArgumentCompleterAttri | |
| [Cmdlet(VerbsLifecycle.Register, "ArgumentCompleter", HelpUri = "https://go.microsoft.com/fwlink/?LinkId=528576")] | ||
| public class RegisterArgumentCompleterCommand : PSCmdlet | ||
| { | ||
| private const string PowerShellSetName = "PowerShellSet"; | ||
| private const string NativeCommandSetName = "NativeCommandSet"; | ||
| 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>@@___"; | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dictionary cannot take |
||
|
|
||
| /// <summary> | ||
| /// Gets or sets the command names for which the argument completer is registered. | ||
| /// </summary> | ||
| [Parameter(ParameterSetName = "NativeSet", Mandatory = true)] | ||
| [Parameter(ParameterSetName = "PowerShellSet")] | ||
| [Parameter(ParameterSetName = NativeCommandSetName, Mandatory = true)] | ||
| [Parameter(ParameterSetName = PowerShellSetName)] | ||
| [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] | ||
| public string[] CommandName { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the name of the parameter for which the argument completer is registered. | ||
| /// </summary> | ||
| [Parameter(ParameterSetName = "PowerShellSet", Mandatory = true)] | ||
| [Parameter(ParameterSetName = PowerShellSetName, Mandatory = true)] | ||
| public string ParameterName { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the script block that will be executed to provide argument completions. | ||
| /// </summary> | ||
| [Parameter(Mandatory = true)] | ||
| [AllowNull()] | ||
| public ScriptBlock ScriptBlock { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Indicates the argument completer is for native commands. | ||
| /// </summary> | ||
| [Parameter(ParameterSetName = "NativeSet")] | ||
| [Parameter(ParameterSetName = NativeCommandSetName)] | ||
| public SwitchParameter Native { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Indicates the argument completer is a fallback for any native commands that don't have a completer registered. | ||
| /// </summary> | ||
| [Parameter(ParameterSetName = NativeFallbackSetName)] | ||
| public SwitchParameter NativeFallback { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// </summary> | ||
| protected override void EndProcessing() | ||
| { | ||
| Dictionary<string, ScriptBlock> completerDictionary; | ||
| if (ParameterName != null) | ||
|
|
||
| if (ParameterSetName is NativeFallbackSetName) | ||
| { | ||
| completerDictionary = Context.CustomArgumentCompleters ?? | ||
| (Context.CustomArgumentCompleters = new Dictionary<string, ScriptBlock>(StringComparer.OrdinalIgnoreCase)); | ||
| completerDictionary = Context.NativeArgumentCompleters ??= new(StringComparer.OrdinalIgnoreCase); | ||
|
|
||
| SetKeyValue(completerDictionary, FallbackCompleterKey, ScriptBlock); | ||
| } | ||
| else | ||
| else if (ParameterSetName is NativeCommandSetName) | ||
| { | ||
| completerDictionary = Context.NativeArgumentCompleters ?? | ||
| (Context.NativeArgumentCompleters = new Dictionary<string, ScriptBlock>(StringComparer.OrdinalIgnoreCase)); | ||
| } | ||
| completerDictionary = Context.NativeArgumentCompleters ??= new(StringComparer.OrdinalIgnoreCase); | ||
|
|
||
| if (CommandName == null || CommandName.Length == 0) | ||
| foreach (string command in CommandName) | ||
| { | ||
| var key = command?.Trim(); | ||
| if (string.IsNullOrEmpty(key)) | ||
| { | ||
| continue; | ||
| } | ||
|
|
||
| SetKeyValue(completerDictionary, key, ScriptBlock); | ||
daxian-dbw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
| else if (ParameterSetName is PowerShellSetName) | ||
| { | ||
| CommandName = new[] { string.Empty }; | ||
| completerDictionary = Context.CustomArgumentCompleters ??= new(StringComparer.OrdinalIgnoreCase); | ||
|
|
||
| string paramName = ParameterName.Trim(); | ||
| if (paramName.Length is 0) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| if (CommandName is null || CommandName.Length is 0) | ||
daxian-dbw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| SetKeyValue(completerDictionary, paramName, ScriptBlock); | ||
| return; | ||
| } | ||
|
|
||
| foreach (string command in CommandName) | ||
| { | ||
| var key = command?.Trim(); | ||
| key = string.IsNullOrEmpty(key) | ||
| ? paramName | ||
| : $"{key}:{paramName}"; | ||
|
|
||
| SetKeyValue(completerDictionary, key, ScriptBlock); | ||
| } | ||
| } | ||
|
|
||
| for (int i = 0; i < CommandName.Length; i++) | ||
| static void SetKeyValue(Dictionary<string, ScriptBlock> table, string key, ScriptBlock value) | ||
daxian-dbw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| var key = CommandName[i]; | ||
| if (!string.IsNullOrWhiteSpace(ParameterName)) | ||
| if (value is null) | ||
| { | ||
| if (!string.IsNullOrWhiteSpace(key)) | ||
| { | ||
| key = key + ":" + ParameterName; | ||
| } | ||
| else | ||
| { | ||
| key = ParameterName; | ||
| } | ||
| table.Remove(key); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 I definitely understand the need but I'd suggest tackling that separately
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Totally agree there should be For
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) |
||
| } | ||
| else | ||
| { | ||
| table[key] = value; | ||
| } | ||
|
|
||
| completerDictionary[key] = ScriptBlock; | ||
| } | ||
| } | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.