powershell indentation
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 depth?
For example, I have:
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"
}
Write-Host "Start of myscript"
Write-Host "End of myscript"
The output of the script will be :
Start of myscript Start of myfn Start of myfnNested End of myFnNested End of myFn End of myscript
What I want to achieve is this output :
Start of mysc开发者_开发知识库ript Start of myfn Start of myfnNested End of myFnNested End of myFn End of myscript
As I don't want to hardly code the number of spaces (since I does not know the depth level in complex script). How can I simply reach my goal ?
Maybe something like this?
function myFn()
{
Indent()
Write-Host "Start of myfn"
myFnNested()
Write-Host "End of myfn"
UnIndent()
}
function myFnNested()
{
Indent()
Write-Host "Start of myFnNested"
Write-Host "End of myFnNested"
UnIndent()
}
Write-Host "Start of myscript"
Write-Host "End of myscript"
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 ;-)
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.)
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.
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
}
加载中,请稍侯......
精彩评论