Skip to content

Commit

Permalink
docs: Updating Splatter.Splatter.ps1 ( re #28 )
Browse files Browse the repository at this point in the history
Removing -Minify and -Compressed examples
StartAutomating authored and StartAutomating committed Sep 6, 2024
1 parent b13e08b commit 13e4981
Showing 1 changed file with 0 additions and 568 deletions.
568 changes: 0 additions & 568 deletions @.ps1
Original file line number Diff line number Diff line change
@@ -2,572 +2,4 @@

[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "", Justification="This Declares Variables for Other Scripts")]
param()
${?@}=${GetSplat}=${gSplat}={
<#
.Synopsis
Gets a splat
.Description
Gets a splat for a command
.Link
Find-Splat
.Link
Use-Splat
.Example
@{id=$pid} | Get-Splat
.Example
@{id=$Pid} | ?@ # ?@ is an alias for Get-Splat
.Example
@{id=$pid} | & ${?@} # Get-Splat as a script block
#>
[Alias('?@','gSplat')]
param(
# The command that is being splatted.
[Parameter(Mandatory=$true,Position=0)]
[PSObject[]]
$Command,

# The input object
[Parameter(Mandatory=$true,ValueFromPipeline=$true,Position=1)]
[Alias('InputObject')]
[PSObject]
$Splat,

# If set, will return regardless of if parameters map, are valid, and have enough mandatory parameters
[switch]
$Force
)
begin {
# Declare some caches:
if (-not ${script:_@p}) { ${script:_@p} = @{} } # * All Parameters
if (-not ${script:_@c}) { ${script:_@c} = @{} } # * All commands
if (-not ${script:_@mp}) { ${script:_@mp} = @{} } # * All Mandatory Parameters
if (-not ${script:_@pp}) { ${script:_@pp} = @{} } # * All Pipelined Parameters
$ValidateAttributes = {
param(
[Parameter(Mandatory)]$value,
[Parameter(Mandatory)]$attributes
)

foreach ($attr in $attributes) {
$_ = $this = $value
if ($attr -is [Management.Automation.ValidateScriptAttribute]) {
$result = . $attr.ScriptBlock
if ($result -ne $true) {
$attr
}
}
elseif ($attr -is [Management.Automation.ValidatePatternAttribute] -and
(-not [Regex]::new($attr.RegexPattern, $attr.Options, '00:00:05').IsMatch($value))
) { $attr }
elseif ($attr -is [Management.Automation.ValidateSetAttribute] -and
$attr.ValidValues -notcontains $value) { $attr }
elseif ($attr -is [Management.Automation.ValidateRangeAttribute] -and (
($value -gt $attr.MaxRange) -or ($value -lt $attr.MinRange)
)) {$attr}
}
}
}
process {

$ap,$ac,$amp = ${script:_@p},${script:_@c}, ${script:_@mp}
#region Turn dictionaries into PSObjects
if ($Splat -is [Collections.IDictionary]) {
$splat = [PSCustomObject]([Ordered]@{} + $Splat)
}
#endregion Turn dictionaries into PSObjects

$in = $Splat
foreach ($cmd in $Command) { # Walk over each command
$rc =
if ($ac.$cmd) { # use cache if available, otherwise:
$ac.$cmd
} elseif ($cmd -is [string]) { # *find it if it's a [string]
$fc = $ExecutionContext.SessionState.InvokeCommand.GetCommand($cmd,'Function,Cmdlet,ExternalScript,Alias')
$fc =
if ($fc -is [Management.Automation.AliasInfo]) {
$fc.ResolvedCommand
} else {
$fc
}
$ac.$cmd = $fc
$fc
} elseif ($cmd -is [ScriptBlock]) { # * Make a temporary command if it's a [ScriptBlock]
$hc = $cmd.GetHashCode()
$ExecutionContext.SessionState.PSVariable.Set("function:f$hc", $cmd)
$c = $ExecutionContext.SessionState.InvokeCommand.GetCommand("f$hc",'Function')
$ac.$cmd = $c
$c
} elseif ($cmd -is [Management.Automation.CommandInfo]) { # * Otherwise, use the command info
$ac.$cmd = $cmd
$cmd
}
if (-not $rc) {continue}
$cmd = $rc
$outSplat,$Invalid,$Unmapped,$paramMap,$Pipe,$NoPipe = foreach ($_ in 1..6){[ordered]@{}}
$params = [Collections.ArrayList]::new()
$props = @($in.psobject.properties)
$pc = $props.Count

if (-not ${script:_@pp}.$cmd) {
${script:_@pp}.$cmd = @(
foreach ($param in $cmd.Parameters.Values) {
foreach ($attr in $param.Attributes) {
if ($attr.ValueFromPipeline) {
$param
}
}
})
}

$cmdMd = $cmd -as [Management.Automation.CommandMetaData]
$problems = @(

foreach ($vfp in ${script:_@pp}.$cmd) {
if ($in -is $vfp.ParameterType -or
($vfp.ParameterType.IsArray -and $in -as $vfp.ParameterType)
) {
$v = $in
$badAttributes = & $ValidateAttributes $v $vfp.Attributes
if ($badAttributes) {
@{$vfp.Name=$badAttributes}
}
if (-not $badAttributes -or $Force) {
$null = $params.Add($vfp.Name)
$pipe[$vfp.Name] = $v
$outSplat[$vfp.Name] = $v
$paramMap[$vfp.Name] = $vfp.Name
$pipelineParameterSets =
@(foreach ($attr in $vfp.Attributes) {
if ($attr.ParameterSetName) { $attr.ParameterSetName}
})
}
}
}

:NextProperty foreach ($prop in $props) {
$cp=$cmd.Parameters
$pn = $prop.Name
$pv = $prop.Value
if (-not $cp) { continue }
$param = $cp.$pn
if (-not $param) {
$k = "${cmd}:$pn"
$param =
if ($ap[$k]) {
$ap[$k]
} else {
foreach ($p in $cp.Values) {
foreach ($a in $p.Aliases) {
$ap["${cmd}:$a"] = $p
}
if ($ap[$k]) { $ap[$k]; break }
}
}
}

if (-not $param) {
$pn
continue
}
$paramMap[$param.Name] = $pn
if ($params -contains $param) { continue }
$pt=$param.ParameterType
$paramSets =
@(foreach ($attr in $param.Attributes) {
if ($attr.ParameterSetName) { $attr.ParameterSetName }
})

if ($pipelineParameterSets) {
$ok = $false
foreach ($cmdPs in $paramSets) {
$ok = $ok -bor ($pipelineParameterSets -contains $cmdPs)
}
if (-not $ok -and -not $Force) { continue }
}
$v = $pv -as $pt
if (-not $v -and
($pt -eq [ScriptBlock] -or
$pt -eq [ScriptBlock[]])) {
$sb = try { foreach ($_ in $pv) { [ScriptBlock]::Create($_) }} catch {$null}
if ($sb) { $v = $sb }
}
if ($null -ne $v) {
$nv = try {
[PSVariable]::new("$pn", $v, 'Private',$param.Attributes)
} catch {
@{$pn=$_}
}
if ($nv -is [PSVariable] -or $Force) {
$null = $params.Add($param)
:CanItPipe do {
foreach ($attr in $param.Attributes) {
if ($attr.ValueFromPipeline -or $attr.ValueFromPipelineByPropertyName -and
((-not $pipelineParameterSets) -or ($pipelineParameterSets -contains $attr.ParameterSetName))
) {
$pipe[$prop.Name] = $v
break CanItPipe
}
}
$NoPipe[$prop.Name] = $v
} while ($false)
$outSplat[$prop.Name] = $v
}

if ($nv -isnot [PSVariable]) { $nv }
} else {
@{$pn = $param}
}
})


$Mandatory = @{}

foreach ($param in $cmdMd.Parameters.Values) {
foreach ($a in $param.Attributes) {
if (-not $a.Mandatory) { continue }
if ($a -isnot [Management.Automation.ParameterAttribute]) { continue }
if (-not $Mandatory[$a.ParameterSetName]) { $Mandatory[$a.ParameterSetName] = [Ordered]@{} }
$mp = ($paramMap.($param.Name))
$Mandatory[$a.ParameterSetName].($param.Name) =
if ($mp) {
if ($pipelineParameterName -contains $param.Name) {
$in
} else {
$outSplat.$mp
}
}
}
}
$amp.$cmd = $Mandatory

$mandatory = $amp.$cmd

$missingMandatory = @{}
foreach ($m in $Mandatory.GetEnumerator()) {
$missingMandatory[$m.Key] =
@(foreach ($_ in $m.value.GetEnumerator()) {
if ($null -eq $_.Value) { $_.Key }
})
}
$couldRun =
if (-not $Mandatory.Count) { $true }
elseif ($missingMandatory.'__AllParameterSets') {
$false
}
else {
foreach ($_ in $missingMandatory.GetEnumerator()) {
if (-not $_.Value) { $true;break }
}
}

if (-not $couldRun -and -not $Force) { continue }
foreach ($p in $problems) {
if ($p -is [Hashtable]) {
$Invalid += $p
} else { $Unmapped[$p] = $in.$p }
}
if ($Invalid.Count -eq 0) { $Invalid = $null }
if ($Unmapped.Count -eq 0) { $Unmapped = $null }

$realCmd =
if ($cmd -is [Management.Automation.FunctionInfo] -and
$cmd.Name.Contains($cmd.ScriptBlock.GetHashCode().ToString())) {
$cmd.ScriptBlock
} else { $cmd }

foreach($_ in ([Ordered]@{
Command = $realCmd
CouldRun = $couldRun
Invalid = $Invalid
Missing = $missingMandatory
PercentFit = $(if ($pc) {$outSplat.Count / $pc } else { 0})
Unmapped = $Unmapped
PipelineParameter = $Pipe
NonPipelineParameter = $NoPipe
}).GetEnumerator()) {
$outSplat.psobject.properties.Add([Management.Automation.PSNoteProperty]::new($_.Key,$_.Value))
}
$outSplat
}
}
}
${.@}=${UseSplat}={
<#
.Synopsis
Uses a splat.
.Description
Uses a splat to call a command.
If passed from Find-Splat,Get-Splat or Test-Splat, the command will be automatically detected.
If called as .@, this will run only provided commands
If called as *@, this will run any found commands
.Link
Get-Splat
.Link
Find-Splat
.Link
Test-Splat
.Example
@{id=$pid} | Use-Splat gps # When calling Use-Splat is globally imported
.Example
@{id=$pid} | & ${.@} gps # When calling Use-Splat is nested
.Example
@{LogName='System';InstanceId=43,44},
@{LogName='Application';InstanceId=10000,10005} |
.@ Get-EventLog # get a bunch of different log events
#>
[Alias('.@','uSplat')]
param(
# One or more commands
[Parameter(Position=0)]
[PSObject[]]
$Command,

# Any additional positional arguments that would be passed to the command
[Parameter(Position=1,ValueFromRemainingArguments)]
[PSObject[]]
$ArgumentList = @(),

# The splat
[Parameter(ValueFromPipeline=$true)]
[PSObject[]]
$Splat,

# If set, will run regardless of if parameters map, are valid, and have enough mandatory parameters.
[switch]
$Force,

# If set, will run the best fit out of multiple commands.
# The best fit is the command that will use the most of the input splat.
[Alias('BestFit','BestFitFunction', 'BF','BFF')]
[switch]
$Best,

# If set, will stream input into a single pipeline of each command.
# The non-pipeable parameters of the first input splat will be used to start the pipeline.
# By default, a command will be run once per input splat.
[Alias('Pipe')]
[switch]
$Stream)

begin {
$pipelines = @{}
}
process {
$WeTrustTheSplat = $false
if (-not $Command -and
$splat.Length -eq 1 -and
$splat[0] -is [Collections.IDictionary] -and
$Splat[0].psobject.Properties['Command']) {
$Command = $Splat[0].psobject.Properties['Command'].Value
$WeTrustTheSplat = $true
} elseif (-not $command -and $_ -is [PSObject] -and $_.Command -and $_.Splat) {
$WeTrustTheSplat = $true
$splat = $_.Splat
$command = $_.Command
}

if ($Best -and $command.Count) {
$command = $splat |
& ${?@} -Command $command |
Sort-Object PercentFit -Descending |
Select-Object -ExpandProperty Command -First 1
}

if (-not $Command) {
Write-Error -Message "No command found" -Category ObjectNotFound -ErrorId 'Use-Splat.CommandNotFound' ;return
}
#region UseTheSplat
foreach ($cmd in $Command) {
if ($WeTrustTheSplat) {
if ($cmd -is [Management.Automation.CommandInfo] -or $cmd -is [ScriptBlock]) {
foreach ($s in $splat) {
if ($argumentList) {
& $cmd @s @ArgumentList
} else {
& $cmd @s
}
}
}
} else {
$Splat |
& ${?@} $cmd -Force:$Force |
& { process {

$i = $_
$np = $i.NonPipelineParameter
$c = $_.psobject.properties['Command'].Value
if ($Stream) {
if (-not $pipelines[$c]) {

$stepScript = if ($argumentList) { {& $c @np @argumentList} } else { {& $c @np} }

$stepPipeline = $stepScript.GetSteppablePipeline()
$pipelines[$c] = $stepPipeline
$stepPipeline.Begin($true)
} else {
$stepPipeline = $pipelines[$c]
}
$stepPipeline.Process([PSCustomObject]$i.PipelineParameter)
return
}

if ($c -is [Management.Automation.CommandInfo] -or $c -is [ScriptBlock]) {
if ($ArgumentList) {
& $c @i @ArgumentList
} else {
& $c @i
}
}
}}
}
}
#endregion UseTheSplat
}

end {
if ($pipelines.Count) {
foreach ($v in $pipelines.Values) { $v.End() }
}
}
}
${??@}=${FindSplat}=${fSplat}={
<#
.Synopsis
Finds commands that can be splatted to given an input.
.Description
Finds the commands whose input parameters match an input object, and returns an [ordered] dictionary of parameters.
.Link
Get-Splat
.Link
Use-Splat
.Example
@{Id=$pid} | Find-Splat -Global
#>
[Alias('??@','fSplat')]
param(
# One or more commands.
# If not provided, commands from the current module will be searched.
# If there is no current module, all commands will be searched.
[Parameter(Position=0)]
[string[]]$Command,

# The splat
[Parameter(ValueFromPipeline=$true,Position=1)]
[Alias('InputObject')]
[PSObject]$Splat,

# If set, will look for all commands, even if Find-Splat is used within a module.
[Alias('G')][switch]$Global,

# If set, will look for commands within the current module.
# To make this work within your own module Install-Splat.
[Alias('L')][switch]$Local,

# If provided, will look for commands within any number of loaded modules.
[Alias('M')][string[]]$Module,

# If set, will return regardless of if parameters map, are valid, and have enough mandatory parameters
[switch]$Force)
begin {
$myModule = $MyInvocation.MyCommand.ScriptBlock.Module
$cmdTypes = 'Function,Cmdlet,ExternalScript,Alias'
$resolveAliases = { begin {
$n = 0
} process {
$n++
if ($t -is [int] -and $id) {
$p = $n* 100 / $t
Write-Progress "Resolving" "$_ " -PercentComplete $p -Id $id
}
if ($_.ResolvedCommand) { $_.ResolvedCommand }
else { $_ }
} end {
Write-Progress 'Resolving Aliases' 'Complete' -Id $id
} }
$filterCmds = { process {
foreach ($c in $Command) { if ($_ -like $c) { return $_ } }
} }
}
process {
if (-not $Splat) { return }
$id =[Random]::new().Next()

$commandList =
@(if (-not $Command) {
Write-Progress -Id $id -Activity 'Getting Commands' -Status ' '
if ($MyModule -and $Local) {
$myModule.ExportedCommands.Values | . $resolveAliases | Select-Object -Unique
} elseif ($module) {
foreach ($m in $Module) {
$rm = Get-Module $m
if (-not $rm) { continue }
$rm.ExportedCommands.Values | . $resolveAliases | Select-Object -Unique
}
} else {
$allcmds = @($ExecutionContext.SessionState.InvokeCommand.GetCommands('*',$cmdTypes, $true))
$t = $allcmds.Count
$allcmds |. $resolveAliases | Select-Object -Unique
}
} elseif ($module) {
foreach ($m in $Module) {
$rm = Get-Module $m
if (-not $rm) { continue }
$rm.ExportedCommands.Values |
. $resolveAliases | . $filterCmds |
Select-Object -Unique
}
} elseif ($Global) {
foreach ($c in $Command) {
$ExecutionContext.SessionState.InvokeCommand.GetCommands($c,$cmdTypes, $true)
}
} elseif ($MyModule -and $Local) {
$myModule.ExportedCommands.Values |
. $filterCmds | . $resolveAliases | Select-Object -Unique
} else {
foreach ($cmd in $Command) {
if ($cmd -is [string] -and $cmd.Contains('*')) {
$ExecutionContext.SessionState.InvokeCommand.GetCommands($cmd,$cmdTypes, $true)
} else {
$cmd
}
}
})
$psBoundParameters.Command = $commandList
if ($Splat -is [Collections.IDictionary]) {
$Splat =
if ($splat.GetType().Name -ne 'PSBoundParametersDictionary') {
[PSCustomObject]$Splat
} else {
[PSCustomObject]([Ordered]@{} + $Splat)
}
}

$c,$t= 0, $commandList.Count
foreach ($cmd in $commandList) {
if ($t -gt 1) {
$c++;$p=$c*100/$t
Write-Progress -Id $id -Activity 'Finding Splats' -Status "$cmd " -PercentComplete $p
}
$Splat |
& ${?@} $cmd -Force:$Force |
Select-Object -Property * -ExcludeProperty SyncRoot,IsSynchronized,IsReadOnly,IsFixedSize,Count |
& { process {
if ($_.PercentFit -eq 0) { return }
$_.pstypenames.clear()
$_.pstypenames.add('Find.Splat.Output')
$keys, $values = @($_.Keys), @($_.Values)
$resplat = [Ordered]@{}
for ($i=0;$i -lt $keys.count;$i++) {
$resplat[$keys[$i]] = $values[$i]
}
$_.psobject.properties.remove('Keys')
$_.psobject.properties.remove('Values')
$_.psobject.properties.Add([Management.Automation.PSNoteProperty]::new('Splat', $resplat))
$_
} }
}

Write-Progress -Id $id -Completed -Activity 'Finding Splats' -Status 'Complete!'
}
}
#endregion Splatter [ 0.5.5 ] : Simple Scripts to Supercharge Splatting (Install-Module Splatter, then Initialize-Splatter -Verb Get,Use,Find )

0 comments on commit 13e4981

Please sign in to comment.