Commands/Interpreters/Invoke-Interpreter.ps.ps1
function Invoke-Interpreter { <# .SYNOPSIS Invokes Interpreters .DESCRIPTION Invokes an Interpreter. This command is not used directly, it is used by creating an alias to invoke-interpreter. This will happen automatically as you attempt to use commands that have an associated interpreter. #> param() # Store myInvocation (we'll need it often) $myInv = $MyInvocation # Determine the invocation name $invocationName = $MyInvocation.InvocationName # If we do not have the correct invocation name, that's because the call operator is being used # Unfortunately, this makes this more complicated, as we have to go looking if ($invocationName -in '.', '&') { # Starting off by picking the words after the invocation $myLine = $myInv.Line.Substring($myInv.OffsetInLine) -replace '^\s{0,}' $MyWords = @($myLine -split '\s{1,}') # If the first word is a variable if ($MyWords[0] -match '^\$(?<v>\w+)') { $firstWordVariableValue = $ExecutionContext.SessionState.PSVariable.Get($matches.0 -replace '^\$').Value # and it has a value if ($firstWordVariableValue) { # use that as the InvocationName. $invocationName = $firstWordVariableValue } } # If the first word is not a variable, elseif ($MyWords[0] -match '^(?<w>\w+)') { # see if it's an alias $firstWordAlias = $ExecutionContext.SessionState.InvokeCommand.GetCommand($mywords[0], 'Alias') if ($firstWordAlias.ReferencedCommand -ne $myInv.MyCommand.Name) { # and use the referenced command as the invocation name. $invocationName = $firstWordAlias } } } # Return if we were called by our real name. return if $invocationName -eq $myInv.MyCommand.Name # If there are no interpreters, obviously return. return if -not $PSInterpreters # If we cannot find mappings return if -not $PSInterpreters.ForFile $interpreterForFiles = $PSInterpreters.ForFile($invocationName) # or don't find a mapping, return. if (-not $interpreterForFiles -and $invocationName -notmatch '[\&\.]') { $nameIsAlias = Get-Alias -Name $InvocationName if ($nameIsAlias.ReferencedCommand.Name -ne $myInv.MyCommand.Name) { $invocationName = $nameIsAlias.ReferencedCommand.Name $interpreterForFiles = $PSInterpreters.ForFile($nameIsAlias.ReferencedCommand) } } return if -not $interpreterForFiles # There can be more than one potential interpreter for each file :NextInterpreter foreach ($interpreterForFile in $interpreterForFiles) { $interpreterCommand, $leadingArgs = $interpreterForFile.Interpreter # If there was no interpreter command, return. continue if -not $interpreterCommand # Now things get a little more complicated. # Since many things that will interpret our arguments will _not_ be PowerShell, we want to conver them $convertedArguments = @( # Unless, of course, the interpreter is native PowerShell, # which we can know if .HasPowerShellInterpreter is true if ($interpreterForFile.HasPowerShellInterpreter) { $args | . { process { $_ } } } else { # If it does not have a PowerShell interpreter, $args | . { process { # Then non-string arguments should become JSON if ($_ -isnot [string]) { ConvertTo-Json -InputObject $_ -Depth 100 } else { $_ } } } }) # We want to use splatting for both sets of arguments, # so force leading args into an array $leadingArgs = @($leadingArgs) # If there were leading args if ($leadingArgs) { # append the invocation name to the array $leadingArgs += @($invocationName) } else { # otherwise, the invocation name is the only leading argument (and we do not want blanks) $leadingArgs = @($invocationName) } # Just before we run, see if we have any parsers for the command $ParsersForCommand = $PSParser.ForCommand($invocationName) # If we do, we'll pipe to Out-Parser. if ($ParsersForCommand) { if ($MyInvocation.ExpectingInput) { $input | & $interpreterCommand @leadingArgs @convertedArguments | Out-Parser -CommandLine $invocationName } else { & $interpreterCommand @leadingArgs @convertedArguments | Out-Parser -CommandLine $invocationName } } else { if ($MyInvocation.ExpectingInput) { $input | & $interpreterCommand @leadingArgs @convertedArguments } else { & $interpreterCommand @leadingArgs @convertedArguments } } } } |