-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Enable tab complete for '-Format' parameter of Get-Date #4835
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
If AllowAll==true 'ValidateElement' always pass all elements. Useful if we need enable IntelliSense (TabComplete) but effectively disable validation when a parameter can accept not only the listed values but also arbitrary. Ex.: Get-Date -Format
Add ValidateSet attribute to '-Format' parameter of Get-Date to enable IntelliSense (tab complete).
8244665 to
e7ea552
Compare
|
Should we use another attribute name just for the IntelliSense scenario? |
|
ValidateSet is a sealed. |
lzybkr
left a comment
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.
Thanks for thinking about the usability here - I agree we should do something here, just not like this.
| /// Useful if we need enable IntelliSense (TabComplete) but effectively disable validation | ||
| /// when a parameter can accept not only the listed values but also arbitrary. | ||
| /// Ex.: Get-Date -Format | ||
| /// </summary> |
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.
This doesn't feel right to me - you shouldn't use a Validation attribute if you aren't validating.
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.
This should be reverted.
| /// Unix format string | ||
| /// </summary> | ||
| [Parameter(ParameterSetName = "net")] | ||
| [ValidateSetAttribute("FileDate", "FileDateUniversal", "FileDateTime", "FileDateTimeUniversal", AllowAll=true)] |
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 would suggest using an ArgumentCompleter attribute instead - it's a bit more cumbersome, but if this scenario makes sense (and I think it probably does), we can find some way to make it simpler.
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.
Do you suggest enhance ArgumentCompleter to support [ArgumentCompleter("FileDate", "FileDateUniversal", "FileDateTime", "FileDateTimeUniversal")] ?
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.
Just brainstorming here - but maybe a new attribute ArgumentCompletions that also implements IArgumentCompleter - this probably requires some additional code elsewhere, probably similar to the ValidateSet code for completion.
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.
A new attribute requires a lot of code. It seems easiest to add a new constructor public ArgumentCompleterAttribute(params string[] completeStrings)
Introduce new ArgumentCompleter constructor. Invoke the constructor in NativeCommandArgumentCompletion()
| /// </summary> | ||
| [Parameter(ParameterSetName = "net")] | ||
| [ValidateSetAttribute("FileDate", "FileDateUniversal", "FileDateTime", "FileDateTimeUniversal", AllowAll=true)] | ||
| [ArgumentCompleter("FileDate", "FileDateUniversal", "FileDateTime", "FileDateTimeUniversal")] |
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.
This is much better, but I think still a little weird, I still think it's worth considering adding a new attribute ArgumentCompletions. It seems like you could take your class StringArrayArgumentCompleter, rename it, make it an attribute, and either duplicate a little bit of logic around ValidateSet or ArgumentCompleter in the tab completion code.
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.
Is your only thought that ArgumentCompleter is a strange name and you want to rename it?
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 wouldn't rename ArgumentCompleter even if it is a strange name (which I suppose it is.)
It's a really minor thing, but to me, ArgumentCompleter implies some dynamic code to compute the completions, whereas ArgumentCompletions is static.
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 have missed that for a long time - the ability to easily complete a set without limiting the parameter to the completions.
Is it a reasonable compromise that you have to go IArgumentCompleter if you want to provide rich CompletionResults, or should be enable this with ArgumentCompletions too?
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.
Done next iteration.
This attribute is used to specify an argument completions for a parameter of a cmdlet or function without force throw unlike ValidateSetAttribute.
91b98ab to
ceb9385
Compare
lzybkr
left a comment
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.
Just a little cleanup and I think it looks good.
| { | ||
| if (wordToCompletePattern.IsMatch(str)) | ||
| { | ||
| yield return new CompletionResult(str, str, CompletionResultType.Text, str); |
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.
Should this be CompletionResultType.ParameterValue? I think that's the only place the attribute will have any effect.
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 agree.
Fixed.
| var argumentCompletionsAttribute = parameter.CompiledAttributes.OfType<ArgumentCompletionsAttribute>().FirstOrDefault(); | ||
| if (argumentCompletionsAttribute != null) | ||
| { | ||
| try |
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.
You are calling internal code which doesn't throw, so the try/catch is unnecessary.
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.
Fixed.
| Metadata.ValidateNotNullFailure); | ||
| } | ||
|
|
||
| if (AllowAll == true) |
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.
This should be reverted.
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.
Fixed.
| /// Useful if we need enable IntelliSense (TabComplete) but effectively disable validation | ||
| /// when a parameter can accept not only the listed values but also arbitrary. | ||
| /// Ex.: Get-Date -Format | ||
| /// </summary> |
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.
This should be reverted.
| { | ||
| result.IgnoreCase = s_attrArgToBoolConverter.Target(s_attrArgToBoolConverter, argValue); | ||
| } | ||
| else if (argumentName.Equals("AllowAll", StringComparison.OrdinalIgnoreCase)) |
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.
This should be reverted.
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.
Fixed.
lzybkr
left a comment
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.
Code changes are approved - but we should get a couple of tests for the new ArgumentCompletions attribute.
411123c to
f86c15a
Compare
f86c15a to
306fdc6
Compare
|
@iSazonov The tests look good, thanks! |
|
|
| } | ||
|
|
||
| AfterAll { | ||
| #Remove-Module -ModuleInfo $testModule |
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.
Did you forget to uncomment this?
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.
Yes 😄 Today tests is passed. I wonder - I don't change a code.
|
@lzybkr Thanks for great idea! |
Add ArgumentCompletions attribute to '-Format' parameter of Get-Date to enable
IntelliSense (tab complete).
Fix
-Formatparameter with named format values.Additional considerations
No tab completion test added for Get-Date because it seems we have no requirements to check tab completion for every parameter in all cmdlets.