Desktop/Public/Format-Tree.ps1
|
# src/Public/Format-Tree.ps1 <# .SYNOPSIS Formats tree records into a visual tree representation. .DESCRIPTION The Format-Tree cmdlet takes ShowTree.TreeRecord objects (typically from Invoke-TreeTraversal) and renders them into string representations based on the specified mode and style. .PARAMETER InputObject The tree records to format. Usually piped from Get-TreeItem. .PARAMETER Mode The formatting mode ('Normal', 'Tree', 'List'). .PARAMETER Ascii Uses ASCII characters for tree connectors. .PARAMETER Colorize Enables ANSI color coding in the output. .PARAMETER ShowTargets Displays symlink and junction targets. .PARAMETER GapPolicy Controls gap lines between items. .PARAMETER StyleProfile A custom style profile or path to a style profile to use for formatting. .EXAMPLE Get-TreeItem -Path . | Format-Tree -Mode Normal -Colorize Retrieves tree items for the current directory and formats them in Normal mode with color. .LINK Show-Tree Get-TreeItem #> function Format-Tree { [CmdletBinding()] param( [Parameter(ValueFromPipeline)] [object] $InputObject, [ValidateSet('Normal', 'Tree', 'List')] [string] $Mode = 'Normal', [switch] $Colorize, [switch] $ShowTargets, [switch] $Ascii, [ValidateSet('None', 'Tree', 'Show')] [string] $GapPolicy = 'Show', [object] $StyleProfile ) begin { if (-not $PSBoundParameters.ContainsKey('Debug')) { $DebugPreference = $PSCmdlet.GetVariableValue('DebugPreference') } if (-not $PSBoundParameters.ContainsKey('Verbose')) { $VerbosePreference = $PSCmdlet.GetVariableValue('VerbosePreference') } $resolvedStyleProfile = if ($StyleProfile) { if ($StyleProfile -is [string]) { Get-ShowTreeStyleProfile -Path $StyleProfile } else { $StyleProfile } } else { Get-ActiveShowTreeStyleProfile } $uiErrors = $resolvedStyleProfile.UIStrings.Errors $reset = (&{if($Colorize){$resolvedStyleProfile.Reset}else{''}}) $dim = (&{if($Colorize){$resolvedStyleProfile.Dim}else{''}}) } process { foreach ($record in $InputObject) { if (-not $record) { continue } if ($record.PSTypeNames -notcontains 'ShowTree.TreeRecord') { throw $uiErrors.InvalidFormatInput } switch ($record.RecordType) { 'Item' { $item = $record.TreeItem $layout = $record.TreeLayout if ($null -eq $item) { continue } if ($null -eq $layout -or $layout.PSTypeNames -notcontains 'ShowTree.TreeLayout') { throw ($uiErrors.MissingMetadata -f $item.Name) } $prefixes = '' foreach ($ancestorIsLast in @($layout.AncestorIsLastSibling)) { $prefixes += Get-Connector ` -Type Prefix ` -Mode $Mode ` -Ascii:$Ascii ` -IsLast:$ancestorIsLast ` -StyleProfile $resolvedStyleProfile } $noSpan = $false if ($Mode -eq 'Tree' -and -not $item.IsContainer) { $noSpan = -not $layout.HasLaterSiblingDirectory } $connector = Get-Connector ` -Type ((&{if($item.IsContainer){'Directory'}else{'File'}})) ` -Mode $Mode ` -Ascii:$Ascii ` -IsLast:$layout.IsLastSibling ` -NoSpan:$noSpan ` -StyleProfile $resolvedStyleProfile $style = Get-ItemStyle ` -Item $item ` -Colorize:$Colorize ` -StyleProfile $resolvedStyleProfile $targetText = '' if ($ShowTargets -and $item.IsLink -and $item.Link.Target) { $targetSuffix = $item.Link.Target if ($Colorize -and $item.Link.TargetMetadata) { $targetStyleItem = [PSCustomObject]@{ PSTypeName = 'ShowTree.TreeItem' IsContainer = $item.Link.TargetMetadata.IsContainer States = @() Native = [PSCustomObject]@{ FileAttributes = $item.Link.TargetMetadata.Attributes } } $targetStyle = Get-ItemStyle ` -Item $targetStyleItem ` -Colorize:$Colorize ` -StyleProfile $resolvedStyleProfile $targetSuffix = "$($targetStyle.Ansi)$($item.Link.Target)$reset" } $targetText = " ${dim}->${reset} $targetSuffix" } Write-Output "${dim}${prefixes}${dim}${connector}${reset}$($style.Ansi)$($item.Name)$reset$targetText".TrimEnd() } 'Gap' { if ($GapPolicy -eq 'None') { continue } $layout = $record.TreeLayout if (-not $layout -or $layout.PSTypeNames -notcontains 'ShowTree.TreeLayout') { throw $uiErrors.MissingGapMetadata } $prefixes = '' foreach ($ancestorIsLast in @($layout.AncestorIsLastSibling)) { $prefixes += Get-Connector ` -Type Prefix ` -Mode $Mode ` -Ascii:$Ascii ` -IsLast:$ancestorIsLast ` -StyleProfile $resolvedStyleProfile } $gapConnector = Get-Connector ` -Type Gap ` -Mode $Mode ` -Ascii:$Ascii ` -StyleProfile $resolvedStyleProfile Write-Output "${dim}${prefixes}${gapConnector}${reset}".TrimEnd() } } } } } |