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

Increase UX of Crescendo-generated cmdlets #191

Closed
steviecoaster opened this issue Apr 28, 2023 · 7 comments
Closed

Increase UX of Crescendo-generated cmdlets #191

steviecoaster opened this issue Apr 28, 2023 · 7 comments
Labels
Issue-Enhancement New feature or request Issue-Triaged issue was read and triaged Resolution-Fixed This issue was fixed

Comments

@steviecoaster
Copy link

Summary of the new feature / enhancement

Crescendo is a fantastic tool for quickly generating PowerShell code for a native command, however there are some long-standing PowerShell user-experience considerations that need to be addressed. Most of this has to do with adding the ability to do filtering within the generated Cmdlet, without the need to pipe to something like Where-Object or Select-Object.

Take for example the Get-Service Cmdlet. I don't have to do something like Get-Service | Where-Object $_.Name -eq 'BITS', I can simply call Get-Service and provide either the service name or DisplayName. This is just one of a very long line of examples of native functionality that exists today.

This same user experience does not exist in Crescendo for a generated native command wrapper. What I would propose is that we add something to the Schema that allows for parameters added to the Native Command's function be passed to a handler. If no handler has been provided, or you have opted to skip an OutputHandler via your json configuration then we should prevent the filter parameters from being extended from the schema onto the generated command. This could be provided potentially by a flag applied in schema (maybe, the implementation details here are something to discuss and figure out what works best; both from an authoring perspective as well as from a end user point of view).

As an example, here's a handler I have for parsing vagrant box list:

function parseVagrantBox {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory)]
        [Object[]]
        $Lines,

        [Parameter()]
        [String]
        $Name
    )
    process {

        $Boxes = [System.Collections.Generic.List[pscustomobject]]::new()
        $Lines | Foreach-Object {
            $null = $_ -match '(?<name>([\w\/]+))\s+\((?<provider>(\w+)),\s(?<version>(\d.+))\)'

           $b = [pscustomObject]@{
                Name     = $matches.name
                Provider = $matches.provider
                Version  = [version]$matches.version
            }

            $Boxes.Add($b)
        }

        if(-not $Name){
            return $Boxes
        }

        else {
           $r = $Boxes | Where-Object { $_.Name -eq $Name}
           if(-not $r){
               Write-Warning "Box not found!"
           }
           else {
               return $r
           }
        }
    }
}

On a command-line outside of my module I can see that things work as expected:

$lines = vagrant box list
. ./parseVagrantBox.ps1
parseVagrantBox -Lines $lines

Name                       Provider   Version
----                       --------   -------
StefanScherer/windows_2019 virtualbox 2021.5.15
ubuntu/trusty64            virtualbox 20190514.0.0
ubuntu/xenial64            virtualbox 20211001.0.0
Additionally, I can filter this:
parseVagrantBox -Lines $lines -Name 'ubuntu/xenial64'

Name            Provider   Version
----            --------   -------
ubuntu/xenial64 virtualbox 20211001.0.0

My error handling works as well:

 parseVagrantBox -Lines $lines -Name 'ubuntu/wefwefewf'
WARNING: Box not found!

However, when I run this in the context of the generated Crescendo module, my filter/error logic falls apart:

Get-VagrantBox

Name                       Provider   Version
----                       --------   -------
StefanScherer/windows_2019 virtualbox 2021.5.15
ubuntu/trusty64            virtualbox 20190514.0.0
ubuntu/xenial64            virtualbox 20211001.0.0

Get-VagrantBox -Name 'ubuntu/xenial64'

Name                       Provider   Version
----                       --------   -------
StefanScherer/windows_2019 virtualbox 2021.5.15
ubuntu/trusty64            virtualbox 20190514.0.0
ubuntu/xenial64            virtualbox 20211001.0.0

Get-VagrantBox -Name 'uowejfi'        

Name                       Provider   Version
----                       --------   -------
StefanScherer/windows_2019 virtualbox 2021.5.15
ubuntu/trusty64            virtualbox 20190514.0.0
ubuntu/xenial64            virtualbox 20211001.0.0

I've put the full Crescendo module code in a gist if anyone finds it useful to see exactly how I've configured things.

Proposed technical implementation details (optional)

No response

@steviecoaster steviecoaster added the Issue-Enhancement New feature or request label Apr 28, 2023
@steviecoaster
Copy link
Author

@theJasonHelmick per our conversation at PowerShell Summit 2023, I've put this issue in here for now. I will update with what I think would be a good example of a Crescendo schema that would support this flow later once I have a bit more time to think on it a bit.

@JamesWTruher
Copy link
Member

There might be a couple of different possible approaches here. One is as you suggest and pass values to the output handler, another would be to just have a parameter type which is not passed to the executable but still available to the handler. For example, if you have a [parameter()]$Name which is not destined for the native tool as a parameter, $Name is still defined and you could reference $Name in your handler.

in either case, we'll need to add a property to the parameter (in the parameter map) which basically says "don't give this to the native exe". I have a feeling that the later is going to be less complicated then adding parameters to the call of the output handler.

@steviecoaster
Copy link
Author

I agree that I believe the latter is going to be better approach here. Thanks for your input @JamesWTruher!

@theJasonHelmick
Copy link
Collaborator

Thank you @steviecoaster for the suggestion - let us investigate and discuss this more.

@theJasonHelmick theJasonHelmick added the Issue-Triaged issue was read and triaged label May 25, 2023
@theJasonHelmick theJasonHelmick added this to the Investigating milestone May 25, 2023
@theJasonHelmick
Copy link
Collaborator

theJasonHelmick commented Jun 1, 2023

@steviecoaster thank you for this suggestion - we are looking to include this in a future release.

@JamesWTruher
Copy link
Member

should be addressed in commit f2a1208

@JamesWTruher JamesWTruher added the Resolution-Fixed This issue was fixed label Jul 5, 2023
@theJasonHelmick
Copy link
Collaborator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Enhancement New feature or request Issue-Triaged issue was read and triaged Resolution-Fixed This issue was fixed
Projects
None yet
Development

No branches or pull requests

3 participants