I\'m writing a large script that deploys an application. This script is based on several nested function calls.
Is there any way to \"ident\" the output based on the dep
You can override Write-Host
to write your indents before calling the original with the '&' operator and the namespace. You might be able to derive the amount of indentation from the current stack scope, but a global variable gives you more control.
$global:writeHostIndent
function Write-Host
{
Microsoft.PowerShell.Utility\Write-Host (' ' * $global:writeHostIndent) -NoNewline
& 'Microsoft.PowerShell.Utility\Write-Host' $args
}
You can use Console.CursorLeft to set its position. Be aware that write-output will reset any custom location, so you need to reset it after each output. Here is a sample:
$i = 0 function Indent() { [console]::CursorLeft += 2 $i = [console]::CursorLeft $i } function UnIndent() { if($i -gt 0) { $i -= 2 } [console]::CursorLeft = $i $i } function WriteIndent([string]$s) { [console]::CursorLeft += $i write-host $s # Reset indent, as write-host will set cursor to indent 0 [console]::CursorLeft += $i } function myFnNested() { $i = Indent WriteIndent "Start of myFnNested" WriteIndent "End of myFnNested" $i = UnIndent } function myFn() { $i = Indent WriteIndent "Start of myfn" myFnNested WriteIndent "End of myfn" $i = UnIndent } WriteIndent "Start of myscript" myFn WriteIndent "End of myscript"
Output:
PS C:\scripting> .\Indent-Output.ps1 Start of myscript Start of myfn Start of myFnNested End of myFnNested End of myfn End of myscript
Write a DEBUG function. Two arguments, one is a flag that takes Start, Stop, or Note; the other argument should be the debug text. (I'd use 1, -1, and 0 for the flag, then you can just add the flag to a Indent variable to set increment depth. Stupid but good enough for debugging.)
You could use a wrapper function around write-host
which used $MyInvocation
to determine the stack depth to create a number of spaces to prefix the message.
Combine this with the -scope ‹n›
parameter of Get-Variable
to pull out each calling level… something like the showstack
function adapted from Windows PowerShell In Action (Payette, 1st Ed):
function ShowStack {
trap { continue; }
0..100 | Foreach-Object {
(Get-Variable -scope $_ 'MyInvocation').Value.PositionMessage -replace "`n"
}
}
You'll need the maximum value of $_
in the pipeline before Get-Variable
fails for scope count being too high.
Check out this script http://poshcode.org/scripts/3386.html
If you load up that Write-Verbose wrapper, you can set $WriteHostAutoIndent = $true
and then just call Write-Host and it will be indented based on stack depth. So given these functions as you defined them originally:
function myFn()
{
Write-Host "Start of myfn"
myFnNested
Write-Host "End of myfn"
}
function myFnNested()
{
Write-Host "Start of myFnNested"
Write-Host "End of myFnNested"
}
With no changes, you can just dot-source a script file with that Write-Host wrapper function in it:
C:\PS> . C:\Users\Jaykul\Documents\WindowsPowerShell\PoshCode\3386.ps1
And then merely set the preference variable before you call your function:
C:\PS> $WriteHostAutoIndent = $true
C:\PS> myFn
Start of myfn
Start of myFnNested
End of myFnNested
End of myfn
Beautiful indented output, like magic ;-)
I used another line of thinking. I set a count variable that is incremented at the start of the function and then used the following code to pad the line I was writing:
write-host ($string).PadLeft( ($string).length + (2 * $count) )
This will indent two spaces for every recursion.