Skip to content

Add / amend syntax displayed from Get-Command -syntax #8692

Closed

Description

@kilasuit

This request is for discussing amendments to the current output display of the Get-Command Syntax parameter by either/or/both

  • Making the Default output easier to read, perhaps making use of differentiating colours the output of Mandatory / Non-Mandatory Parameters
  • Adding a new Parameter that implements a PrettySyntax Parameter

This is based off of a tweet as per below by Mathias R. Jessen (@IISResetMe) in which the Output Syntax was much easier to read by making use of regex to amend the output of the current implementation which aligned with the PowerShell Documentation on docs.microsoft.com in which Steve Lee (@SteveL-MSFT) responded that a discussion should take place on formatting ideas

Someone complained output from gcm -syntax is cluttered - there's a regex for that:
(gcm command -syntax) -replace '\]? \[*(?=-|<C)',"`r`n " pic.twitter.com/p9jU3vTMAc

— Mathias Jessen (Mathias R. Jessen (@IISResetMe)) May 16, 2017

Activity

  1. added
    Issue-Discussionthe issue may not have a clear classification yet. The issue may generate an RFC or may be reclassif
    on Jan 18, 2019
  2. SteveL-MSFT commented on Jan 18, 2019

    @SteveL-MSFT
    Member

    Personally, I'd like to consider having platyPS updated so that the default view of the parameters is similar to the use of the regex above (no need for -PrettySyntax). It was also noted that PSCX has a command to show parameters in a table that may be something we'd want as gcm -syntax -astable

  3. vexx32 commented on Jan 18, 2019

    @vexx32
    Collaborator

    That view is nice, but I think it'd be worthwhile to revisit the syntax that distinguishes mandatory and non-matching parameters.

    I also think that parameters that are both optional and part of all sets / have no explicitly declared set should be displayed apart from the main syntax diagrams to minimise confusion. So you'd have parameter set A, then parameter set B, then list any optional 'use-with-any-set' parameters below the main syntax diagrams.

    I agree the current syntax diagrams are too unclear and cluttered to be easily read. However, splitting them out as exemplified by the regex result is too space-consuming for commands with more than one or two parameter sets.

    Perhaps we could strike a balance by using a variant of format-wide to display the parameters in columns, maybe mandatory Params show at the far left, with optional parameters shown to the right of them in a consistently-indented format.

  4. SteveL-MSFT commented on Jan 22, 2019

    @SteveL-MSFT
    Member

    The webcmdlets are a good example to use to work out a generalized format that improves readability. Rain Sallow (/u/ta11ow) (@vexx32) can you draft an example of what you think it should look like?

  5. vexx32 commented on Jan 23, 2019

    @vexx32
    Collaborator

    Pulling from the web cmdlets and from New-WordCloud (because wow did I go overboard on parameters on that one), I think this is a good start:

    Invoke-WebRequest

    Invoke-WebRequest [-Uri] <uri> [-Proxy <uri>] [-ProxyCredential <pscredential>] [-ProxyUseDefaultCredentials] [-Method <WebRequestMethod>]
    
    Invoke-WebRequest [-Uri] <uri> -NoProxy [-Method <WebRequestMethod>]
    
    Invoke-WebRequest [-Uri] <uri> -CustomMethod <string> [-Proxy <uri>] [-ProxyCredential <pscredential>] [-ProxyUseDefaultCredentials] 
    
    Invoke-WebRequest [-Uri] <uri> -CustomMethod <string> -NoProxy 
    
    [-UseBasicParsing]                        [-WebSession <WebRequestSession>]                     [-SessionVariable <string>]
    [-AllowUnencryptedAuthentication]         [-Authentication <WebAuthenticationType>]             [-Credential <pscredential>]
    [-UseDefaultCredentials]                  [-CertificateThumbprint <string>]                     [-Certificate <X509Certificate>]
    [-SkipCertificateCheck]                   [-SslProtocol <WebSslProtocol>]                       [-Token <securestring>]
    [-UserAgent <string>]                     [-DisableKeepAlive]                                   [-TimeoutSec <int>]
    [-Headers <IDictionary>]                  [-MaximumRedirection <int>]                           [-MaximumRetryCount <int>]
    [-RetryIntervalSec <int>]                 [-Body <Object>]                                      [-Form <IDictionary>]
    [-ContentType <string>]                   [-TransferEncoding <string>]                          [-InFile <string>]
    [-OutFile <string>]                       [-PassThru]                                           [-Resume]
    [-PreserveAuthorizationOnRedirect]        [-SkipHeaderValidation]                               [<CommonParameters>]
    

    PSWordCloud\New-WordCloud

    New-WordCloud [-InputObject] <Object[]> [-Path] <string[]>  [-ImageSize <Size>] [-BackgroundColor <Color>]
    
    New-WordCloud [-InputObject] <Object[]> [-Path] <string[]> -Monochrome  [-ImageSize <Size>] [-BackgroundColor <Color>]
    
    New-WordCloud [-InputObject] <Object[]> [-Path] <string[]> -BackgroundImage <FileInfo> 
    
    New-WordCloud [-InputObject] <Object[]> [-Path] <string[]> -Monochrome -BackgroundImage <FileInfo> 
    
    [-ColorSet <Color[]>]              [-MaxColors <int>]                 [-FocusWord <string>]
    [-ExcludeWord <string[]>]          [-FontFamily <FontFamily>]         [-FontStyle <FontStyle>]
    [-StrokeColor <Color>]             [-StrokeWidth <double>]            [-DistanceStep <Object>]
    [-RadialGranularity <Object>]      [-OutputFormat <string>]           [-MaxUniqueWords <int>]
    [-RandomSeed <int>]                [-Padding <double>]                [-WordScale <double>]
    [-AllowOverflow]                   [-DisableWordRotation]             [-BoxCollisions]
    [-AllowStopWords]                  [-WhatIf]                          [-Confirm] 
    [<CommonParameters>]
    

    I also think that making an effort to bring clarity through color is preferable to the excessive brackets that tend to dot these diagrams... but this should be fairly simple to hammer out in code for a first iteration:

    1. Just grab each parameter set
    2. Pull out a) mandatory parameters and b) parameters specifically declared for that set, and draw them similar to current syntax diagrams to show actual command usage.
    3. Take all the parameters that are in "all sets" by virtue of not declaring a set they belong to, and give that to Format-Wide -Columns 3 essentially, displayed below all the sets. Maybe adjust number of columns if the console width is super narrow.

    Additionally, I'd ideally love to see the syntax diagrams illustrate any simple pipeline usages (from ValueFromPipeline parameters) of the command as well. For New-WordCloud, this would possibly look a bit like this:

    <Object[]> | New-WordCloud [-Path] <string[]>  [-ImageSize <Size>] [-BackgroundColor <Color>]
    
    <Object[]> | New-WordCloud [-Path] <string[]> -Monochrome  [-ImageSize <Size>] [-BackgroundColor <Color>]
    
    <Object[]> | New-WordCloud [-Path] <string[]> -BackgroundImage <FileInfo> 
    
    <Object[]> | New-WordCloud [-Path] <string[]> -Monochrome -BackgroundImage 
    

    I'm not really sure of the best way to do it with commands that may accept pipeline by property name or by value, perhaps mark them with an asterisk or a cross and note that they can be used by property name.

  6. SteveL-MSFT commented on Feb 2, 2019

    @SteveL-MSFT
    Member

    cc Michael Klement (@mklement0) on his opinion

    Agree we can defer the color separately. Rain Sallow (/u/ta11ow) (@vexx32) your proposal looks ok to me.

  7. mklement0 commented on Feb 26, 2019

    @mklement0
    Contributor

    I definitely like Rain Sallow (/u/ta11ow) (@vexx32)'s suggestions, including "bracket relief" through coloring; these issues are related:

    #6856 (show parameter-set names)
    #4135 (indicate pipeline-binding parameters)
    #4715 (indicate parameters with wildcard support)
    #4626 (indicate ValueFromRemainingArguments parameters)

  8. vexx32 commented on Feb 26, 2019

    @vexx32
    Collaborator

    Mark Kraus (@markekraus) I think we spoke briefly on Discord about this issue a couple weeks ago, from memory. Did you have any suggestions for these, since the web cmdlets are your area of expertise? Is there a more effective way of conveying the parameter sets and optional parameters, do you think?

    Steve Lee (@SteveL-MSFT) Looking at Michael Klement (@mklement0)'s links there, I definitely think we should also indicate those parameters in some fashion. Whether that's a secondary concern and should be considered separately I'm not sure.

    • Parameter set names could simply be positioned directly above each set.
    • Pipeline-binding parameters... not really sure about the suggestions, but those in the linked issue are pretty clear. I don't think the symbol suggested for by-property conveys the meaning intended very well, though.
    • Wildcard support is a bit of a funny one. Not sure if I prefer showing it in the parameter name [-Path*] or in the parameter type declaration [-Path] <string[]*> although I think I prefer the latter?
    • Remaining args is a good one to show as well, and the suggestions in that issue seem to be pretty solid.
  9. kilasuit commented on Feb 27, 2019

    @kilasuit
    CollaboratorAuthor

    So with the output there's a good reason why I suggested colour being used for mandatory or non mandatory parameters and that is primarily due to the blending text effect, which by this I mean that by this is hard to read, due to the way brackets are used, it's just something that is humanly hard to parse, or is at least for me.

    image

    To me the top line in just blends into 1 lump of text, which I need to reparse often 4/5 times before I really get which parameters are mandatory/non-mandatory/switches

    If the second version could be implemented, even with an additional switch parameter that would make it easier on first glance how I am supposed to use this command properly, reducing potential errors caused by the inability to quickly parse the requirements of the parameter, with the above showing Red for Mandatory Parameters and their expected Type, Blue for non-mandatory and their type and a golden colour for switches (I'd suggest different colours in the implementation)

  10. vexx32 commented on Feb 27, 2019

    @vexx32
    Collaborator

    We could take pointers from the developments going on with Select-String's MatchInfo objects in #8963; emit an object that when run through the default formatter outputs a colored sequence of text, but still has a very plain .ToString() method that gets the raw text.

    Ryan Yates (@kilasuit) even colouring won't save something as complicated as Invoke-WebRequest's syntax diagrams, which is why I think a reformat is a more effective first step. Colouring should definitely be sorted out as well, though, it will take the diagrams more readable overall.

  11. vexx32 commented on Jun 2, 2019

    @vexx32
    Collaborator

    Steve Lee (@SteveL-MSFT) this would be something I'd like to look at for PS7. I know you guys are talking about working the help into a separate module / making it work in markdown / both(?) so would this fall under that bundle of work, or can you point me to where this is actually put together currently so I can implement it in the current system & you can copy it to the new system as that gets completed?

  12. SteveL-MSFT commented on Jul 5, 2019

    @SteveL-MSFT
    Member

    Rain Sallow (/u/ta11ow) (@vexx32) taking some time to catch up on my GitHub notifications. I don't believe this work is blocked behind the Helpsystem as separate module/Markdown completion work. If you want to work on this as an Experimental Feature, that may be the best way to go here to get user feedback.

  13. KirkMunro commented on Sep 16, 2019

    @KirkMunro
    Contributor

    Before putting together an experimental feature, I recommend a more detailed analysis with examples of many cmdlets, showing their syntax before and after. We can only really figure out the right thing to do here by having a sample of data large enough to make that judgement, and the commands chosen for that sample should be among some of the more complicated commands (many parameter sets) so that we can see what they might look like.

    In the past I looked at this from a different perspective, and periodically I spend time thinking about it more to flush out into a potential RFC. While I don't have those thoughts all put together, I can share what I had been exploring for syntax improvements:

    SYNTAX
        Where-Object [-FilterScript] <scriptblock> [-InputObject <psobject>]
        [<CommonParameters>]
    
        Where-Object [-Property] <string> [-not] [-InputObject <psobject>]
        [<CommonParameters>]
    
        Where-Object [-Property] <string> <comparison_operator> [[-Value] <Object>]
        [-InputObject <psobject>] [<CommonParameters>]
    
    
    SYNTAX
        Get-ChildItem [<PathParameters>] [[-Filter] <string>] [-Include <string[]>] [-Exclude
        <string[]>] [-Recurse] [-Depth <uint32>] [-Force] [-Name] [-UseTransaction]
        [<ProviderParameters>] [<CommonParameters>]
    
        [<PathParameters>]
        Wildcard : [[-Path] <string[]>]
        Specific : [-LiteralPath <string[]>]
    
        [<ProviderParameters>]
        FileSystem  : [-Attributes <FlagsExpression[FileAttributes]>] [-Directory] [-File]
                      [-Hidden] [-ReadOnly] [-System]
        Certificate : [-CodeSigningCert] [-DocumentEncryptionCert] [-SSLServerAuthentication]
                      [-DnsName <DnsNameRepresentation>] [-Eku <string[]>] [-ExpiringInDays
                      <int>]
    
    
    SYNTAX
        Invoke-Command <InvokedItemParameters> [-ArgumentList <Object[]>] [-InputObject
        <PSObject>] [<InvokeTargetParameters>] [<CommonParameters>]
    
        <InvokedItemParameters>
        ScriptBlock : [-ScriptBlock] <ScriptBlock>
        File        : [-FilePath] <String>
    
        [<InvokeTargetParameters>]
        LocalComputer   : [-NoNewScope]
        PsSession       : [-Session] <PSSession[]> [<RemotingParameters>]
        RemoteComputer  : [-ComputerName] <String[]> [-Port <Int32>] [-UseSsl] [-Credential
                          <PSCredential>] [-Authentication <AuthenticationMechanism>]
                          [-SessionOption <PSSessionOption>] [-EnableNetworkAccess]
                          [-ConfigurationName <String>] [-ApplicationName <String>]
                          [-CertificateThumbprint <String>] [-InDisconnectedSession]
                          [-SessionName <String>] [<RemotingParameters>]
        Uri             : [-ConnectionUri] <Uri[]> [-AllowRedirection] [-Credential
                          <PSCredential>] [-Authentication <AuthenticationMechanism>]
                          [-SessionOption <PSSessionOption>] [-EnableNetworkAccess]
                          [-ConfigurationName <String>] [-CertificateThumbprint <String>]
                          [-InDisconnectedSession] [-SessionName <String>] [<RemotingParameters>]
        VmById          : [-VmId] <Guid[]> [-Credential] <PSCredential> [<RemotingParameters>]
        VmByName        : -VmName <String[]> [-Credential] <PSCredential> [<RemotingParameters>]
        ContainerById   : -ContainerId <String[]> [-RunAsAdministrator] [<RemotingParameters>]
        ContainerByName : -ContainerName <String[]> [-RunAsAdministrator] [<RemotingParameters>]
    
        [<RemotingParameters>]
        [-ThrottleLimit <Int32>] [-AsJob] [-JobName <String>] [-HideComputerName]
    

    Generally speaking, I was looking for ways to group parameters into subsets that are repeatedly used across parameter sets (or across subsets -- recursive grouping can happen). In the output above, my thinking was that you'd have named groups (name followed by a colon) within a subset, where you need to choose one named group and go with that (e.g. ContainerByName in the Invoke-Command syntax), or unnamed groups (e.g. RemotingParameters), which are just groups of parameters that are used in multiple parameter sets or parameter groups.

    The hard part is figuring out how to get there.

  14. 30 remaining items

  15. plastikfan commented on Feb 5, 2021

    @plastikfan

    As a result of building my own colour enhanced parameter set analysis function, I think I've found a slight issue in the result produced by the -Syntax option (I'm not 100%, because it may just simply be a problem with the parameter set definition on the function I've been testing with). I have noticed that sometimes the syntax for a particular optional parameter has the type specification defined inside the square brackets: [-Param <type>] (actually most are), but sometimes can be outside: [-Param] <type>.

    What I have also noticed (and this may be related to the above point) is that parameter can be incorrec;tly indicated to be optional in the syntax statement, but when you see the full parameter definition, you'll see that its mandatory. This can be more easily illustrated in the following output:

    gips rename-many replace-with pattern syntax

    In the syntax statement, Pattern is shown in White and inside square brackets (this is incorrect), but the in the table, you will see that Pattern is coloured red and you can see the Mandatory flag is set ✔️.

    PS: you can see that my function Get-ParameterSetInfo shows the Pattern as:

    [-Pattern <array>]

    as I would expect given the syntax statement says it optional (but actually this is wrong) as opposed to:

    [-Pattern] <array>

    the type is outside of the square brackets. Get-ParameterSetInfo is using regex replacement to repair the output (as part of the colourisation process).

    I should also state that Pattern IS mandatory in this paremeter set:

    function Rename-Many {
      [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'ReplaceWith')]
      [Alias('remy')]
      param
      (
    
        [Parameter(ParameterSetName = 'MoveToAnchor', Mandatory, Position = 0)]
        [Parameter(ParameterSetName = 'ReplaceWith', Mandatory, Position = 0)]
        [Parameter(ParameterSetName = 'MoveToStart', Mandatory, Position = 0)]
        [Parameter(ParameterSetName = 'MoveToEnd', Mandatory, Position = 0)]
        [ValidateScript( { { $(test-ValidPatternArrayParam -Arg $_ -AllowWildCard ) } })]
        [array]$Pattern,

    If you run:

    gcm Rename-Many -syntax

    you'll see this:

    λ gcm rename-many -Syntax
    
    Rename-Many [-Pattern] <array> -underscore <FileSystemInfo> [-Copy <array>] [-With <string>] [-Start] [-End] [-Paste <string>] [-Drop <string>] [-File] [-Directory] [-Except <string>] [-Include <string>] [-Whole <string>] [-Condition <scriptblock>] [-Top <int>] [-Transform <scriptblock>] [-Context <psobject>] [-Diagnose] [-WhatIf] [-Confirm] [<CommonParameters>]
    
    Rename-Many [-Pattern] <array> -underscore <FileSystemInfo> -End [-With <string>] [-Paste <string>] [-Drop <string>] [-File] [-Directory] [-Except <string>] [-Include <string>] [-Whole <string>] [-Condition <scriptblock>] [-Top <int>] [-Transform <scriptblock>] [-Context <psobject>] [-Diagnose] [-WhatIf] [-Confirm] [<CommonParameters>]
    
    Rename-Many [-Pattern] <array> -underscore <FileSystemInfo> -Start [-With <string>] [-Paste <string>] [-Drop <string>] [-File] [-Directory] [-Except <string>] [-Include <string>] [-Whole <string>] [-Condition <scriptblock>] [-Top <int>] [-Transform <scriptblock>] [-Context <psobject>] [-Diagnose] [-WhatIf] [-Confirm] [<CommonParameters>]
    
    Rename-Many [-Pattern] <array> -underscore <FileSystemInfo> -Anchor <array> [-Relation <string>] [-Copy <array>] [-With <string>] [-Paste <string>] [-Drop <string>] [-File] [-Directory] [-Except <string>] [-Include <string>] [-Whole <string>] [-Condition <scriptblock>] [-Top <int>] [-Transform <scriptblock>] [-Context <psobject>] [-Diagnose] [-WhatIf] [-Confirm] [<CommonParameters>]
    
    Rename-Many -underscore <FileSystemInfo> -Append <string> [-Copy <array>] [-File] [-Directory] [-Except <string>] [-Include <string>] [-Whole <string>] [-Condition <scriptblock>] [-Top <int>] [-Transform <scriptblock>] [-Context <psobject>] [-Diagnose] [-WhatIf] [-Confirm] [<CommonParameters>]
    
    Rename-Many -underscore <FileSystemInfo> -Prepend <string> [-Copy <array>] [-File] [-Directory] [-Except <string>] [-Include <string>] [-Whole <string>] [-Condition <scriptblock>] [-Top <int>] [-Transform <scriptblock>] [-Context <psobject>] [-Diagnose] [-WhatIf] [-Confirm] [<CommonParameters>]
    

    But the problem with this is that these parameter sets are not decorated with the parameter name; hence me building these parameter sets tools.

    If you run Kirk Munro (@KirkMunro) 's Get-CommandDetails (only the 'ReplaceWith' parameter set is shown):

    'Rename-Many' | Get-CommandDetail

    Parameter Set: ReplaceWith (Default)
    
    Syntax: Rename-Many [-Pattern] <array> -underscore <FileSystemInfo> [-Copy <array>] [-With <string>] [-Start] [-End] [-Paste <string>] [-Drop <string>] [-File] [-Directory] [-Except <string>] [-Include <string>] [-Whole <string>] [-Condition <scriptblock>] [-Top <int>] [-Transform <scriptblock>] [-Context <psobject>] [-Diagnose] [-WhatIf] [-Confirm] [<CommonParameters>]
    
    Parameters:
    Name       Type            Mandatory   Pos PipeValue PipeName Alias
    ----       ----            ---------   --- --------- -------- -----
    Pattern    Array                True     0     False    False
    underscore FileSystemInfo       True named      True    False
    Copy       Array               False named     False    False
    With       String              False named     False    False
    Start      SwitchParameter     False named     False    False
    End        SwitchParameter     False named     False    False
    Paste      String              False named     False    False
    Drop       String              False named     False    False
    File       SwitchParameter     False named     False    False
    Directory  SwitchParameter     False named     False    False
    Except     String              False named     False    False x
    Include    String              False named     False    False i
    Whole      String              False named     False    False
    Condition  ScriptBlock         False named     False    False
    Top        Int32               False named     False    False
    Transform  ScriptBlock         False named     False    False
    Context    PSObject            False named     False    False
    Diagnose   SwitchParameter     False named     False    False
    

    you can see the errorneous (or rather, yet unexplained) way that Pattern is displayed:

     [-Pattern] <array>
    

    ie the type is outside of the square brackets.

    So a question I have is why are there 2 representations of optional parameters presented by the -Syntax option? (Is this by design or a bug? Also, I'm not ruling out the possiblity that I have done something wrong in my parameter set definition)

    PS: this post is purely about the potential issue with the result presented by the -Syntax option. I just happened to notice it as a result of seeing the coloured output shown by Get-ParameterSetInfo.

    Sorry about the verboseness, I had to make sure I explained myself comprehensively and to stake my case clearly!

  16. mklement0 commented on Feb 5, 2021

    @mklement0
    Contributor

    I haven't read through your post in detail, but perhaps these pointers help:

    -Param <type> ... mandatory, non-positional parameter (requires passing with parameter name)
    [-Param <type>] ... optional, non-positional parameter
    [-Param] <type> ... mandatory, positional parameter (using the parameter name is optional, if passed in the right position among other arguments passed positionally)
    [[-Param] <type>] ... optional, positional parameter

  17. plastikfan commented on Feb 5, 2021

    @plastikfan

    Ah ok that makes a bit more sense now. I'll change my rendering to apply those rules.

  18. plastikfan commented on Apr 15, 2021

    @plastikfan

    Hi just me again. If anyone is interested, I have just published a new version of the module I've been working on which includes a finalised version of a function I call Show-ParameterSetInfo based upon Kirk Munro (@KirkMunro)'s and James Truher (@JamesWTruher)'s Get-CommandDetail function. The module (Elizium.Loopz) also contains other functions that help when working with Parameter Sets. I am still interested in the outcome of this issue and will be observing from afar. Cheers.

  19. microsoft-github-policy-service commented on Nov 16, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

  20. microsoft-github-policy-service commented on Nov 16, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

  21. microsoft-github-policy-service commented on Nov 16, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

  22. microsoft-github-policy-service commented on Nov 23, 2023

    @microsoft-github-policy-service
    Contributor

    This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-Discussionthe issue may not have a clear classification yet. The issue may generate an RFC or may be reclassifResolution-No ActivityIssue has had no activity for 6 months or moreWG-Interactive-HelpSystemhelp infrastructure and formatting of help

    Type

    No type

    Projects

    • Status
      Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions