Format-Splat.psm1
Write-Verbose 'Importing from [C:\MyProjects\Format-Splat\Format-Splat\private]' Write-Verbose 'Importing from [C:\MyProjects\Format-Splat\Format-Splat\public]' # .\Format-Splat\public\Format-Splat.ps1 function Format-Splat { <# .DESCRIPTION formats a function call into a splatted call .EXAMPLE $text = 'Copy-Item -Path $path -Destination c:\temp -Force' PS> Format-Splat $text $item = @{ Path = $path Destination = 'c:\temp' Force = $true } Copy-Item @item #> [OutPutType('System.String')] [Cmdletbinding()] param ( # The text to format into an appropriate splat command [parameter( Mandatory, Position = 0, ValueFromPipeline )] [string] $InputObject ) $script = [scriptblock]::Create($InputObject) $ast = $script.ast $command = $ast | Select-AST -Type CommandAst $parameters = [ordered]@{} $currentParameter = $null $function = '' $parent = $null $other = @() $mode = 'function' foreach ($token in $command.CommandElements) { if ($null -ne $parent -and $parent -ne $token.Parent) { continue } switch ($mode) { 'function' { if ($token -is [System.Management.Automation.Language.StringConstantExpressionAst]) { $function = $token.Value $mode = 'parameter' $parent = $token.Parent } } 'value' { if ($token -is [System.Management.Automation.Language.StringConstantExpressionAst]) { $parameters[$currentParameter] = "'{0}'" -f $token.Value } elseif (-not($token -is [System.Management.Automation.Language.CommandParameterAst])) { $parameters[$currentParameter] = $token.Extent } $currentParameter = $null $mode = 'parameter' } 'parameter' { if ($token -is [System.Management.Automation.Language.CommandParameterAst]) { $currentParameter = $token.ParameterName $parameters[$currentParameter] = '$true' $mode = 'value' } else { $other += $token.Extent } } } } if ($parameters.count -lt 1) { return $InputObject } $output = @() $splatName = $function -split '-' | Select-Object -Last 1 $splatName = $splatName.substring(0, 1).tolower() + $splatName.substring(1) $output += '${0} = @{{' -f $splatName foreach ($node in $parameters.GetEnumerator()) { $paramName = $node.Name.substring(0, 1).toUpper() + $node.Name.substring(1) $output += ' {0} = {1}' -f $paramName, $Node.Value } $output += '}' if ($other.count -gt 0) { $output += '{0} {1} @{2}' -f $function, ($other -join ' '), $splatName } else { $output += '{0} @{1}' -f $function, $splatName } $output | Out-String -Width 1000 } # .\Format-Splat\public\Format-VSCodeSplat.ps1 function Format-VSCodeSplat { <# .DESCRIPTION Takes the selected function with parameters and creates the needed splat call .EXAMPLE Copy-Item -Path $path -Destination c:\temp -Force $item = @{ Path = $path Destination = 'c:\temp' Force = $true } Copy-Item @item #> [Cmdletbinding()] param ( # VSCode context [Microsoft.PowerShell.EditorServices.Extensions.EditorContext] $context ) try { if ($null -ne $context) { $text = $context.CurrentFile.GetText($context.SelectedRange) | Out-String $output = Format-Splat -InputObject $text if ($output) { $context.CurrentFile.InsertText($output, $context.SelectedRange) } } } catch { $pseditor.window.ShowWarningMessage($PSitem.ToString()) } } if ($psEditor) { $EditorCommand = @{ Name = 'Invoke-VSSplat' DisplayName = 'Refactor: splat parameters for cmdlet' Function = 'Format-VSCodeSplat' SuppressOutput = $true } Register-EditorCommand @EditorCommand } Write-Verbose 'Importing from [C:\MyProjects\Format-Splat\Format-Splat\classes]' |