Types/OpenPackage.View/Tree.txt.ps1

<#
.SYNOPSIS
    Shows a text package tree
.DESCRIPTION
    Shows a package tree as text.
#>

[OutputType('text/plain')]
param(
# Any input
[Parameter(ValueFromPipeline)]
[Alias('Package')]
[PSObject]
$InputObject,
    
# The file pattern. All files that match this pattern will be urn.
[string]
$FilePattern = '.',

# The symbol used for roots of the tree
[string]
$RootSymbol = '╮',

# The symbol used for branches of the tree
[string]
$BranchSymbol = "─",

# The number of characters a branch should take
[int]
$BranchSize = 2,

# The symbol used for a leaf of the tree.
[string]
$LeafSymbol = '├'
)

$allInput = @($input)
if ((-not $allInput) -and $InputObject) {
    $allInput += $InputObject
}

filter toIndex {
    $in = $_
    
    if ($in -is [Collections.IDictionary]) {        
        $in.GetEnumerator() | . toIndex            
    } elseif ($in.Key -is [string]) {
        $depth++    
        if ($in.Value -is  [Collections.IDictionary]) {
            
            '' + (
                (' ' * ($BranchSize + $LeafSymbol.Length + $RootSymbol.Length - 1)) * (
                    $depth - 1
                )
            ) + $LeafSymbol + (
                $BranchSymbol * $BranchSize
            ) + $RootSymbol + ' ' + $in.Key

            $in.Value | . toIndex            
        } else {
            (
                ' ' * ($BranchSize + $LeafSymbol.Length + $RootSymbol.Length - 1)
            ) * ($depth - 1) + $LeafSymbol + $in.Key
        }
        $depth--
    }
    
}


foreach ($in in $allInput) {
    if (-not $in.GetTree) {
        continue
    }
    $fileTree = $in.GetTree($FilePattern)
    @(
        $depth = 0
        $fileTree | toIndex        
    ) -join [Environment]::NewLine |
        Add-Member NoteProperty Package $in -Force -PassThru |
        Add-Member NoteProperty FilePattern $in -Force -PassThru |
        . {
            process {
                $_.pstypenames.add('text/plain')
                $_
            }
        }
}