1+ function Format-OneLine {
2+ <#
3+ . SYNOPSIS
4+ Format the given object as a single-line string.
5+
6+ . DESCRIPTION
7+ Format the given object as a single-line string. Will recurse into
8+ objects up to the given depth. Special exception for PSVariables, they
9+ will render even at depth 0, allowing. Only outputs on pipeline-end
10+ because it uses a pipeline-accumulator hack. This allows you to pipe
11+ multiple objects into Format-OneLine and have them all output as a
12+ single shared line. See example for the usefulness of these foibles WRT
13+ Get-Variable.
14+
15+ . EXAMPLE
16+ ```powershell
17+ $foo = 'bar'; $baz = 'quux'
18+ Get-Variable foo, baz | Format-OneLine
19+ # returns "foo: bar; baz: quux"
20+ ```
21+ #>
22+ [OutputType ([string ])]
23+ [CmdletBinding ()]
24+ param (
25+ [Parameter (ValueFromPipeline , Position = 0 )]
26+ [object ] $InputObject ,
27+
28+ # Depth to search to. Note that PSVariables are still iterated at depth 0, so that a pipeline of GetVariables
29+ [int ] $Depth = 1 ,
30+
31+ # Include the key/value pairs for null or otherwise empty objects.
32+ [switch ] $ShowEmpty ,
33+
34+ # Wrap nested HashTables/PSObjects in `{}`
35+ [switch ] $DoBraceNestedTables
36+ )
37+ begin {
38+ $accumulator = [Collections.ArrayList ]::new()
39+ }
40+ process {
41+ $accumulator.Add ($InputObject ) | Out-Null
42+ }
43+ end {
44+ $obj = if ($accumulator.Count -gt 1 ) {
45+ $accumulator
46+ } else {
47+ # unwrap single-element ArrayList.
48+ $accumulator | Select-Object - First 1
49+ }
50+ Format-OneLineRecursive $obj $Depth $Depth - ShowEmpty:$ShowEmpty - DoBraceNestedTables:$DoBraceNestedTables
51+ }
52+ }
53+
54+
55+ Export-ModuleMember - Function *
56+
57+
58+ # private function below
59+ function Format-OneLineRecursive {
60+ <#
61+ . SYNOPSIS
62+ Recursive internal implementation of Format-OneLine with extra needed parameter(s).
63+ #>
64+ [OutputType ([string ])]
65+ [CmdletBinding ()]
66+ param (
67+ [Parameter (ValueFromPipeline , Position = 0 )]
68+ [object ] $InputObject ,
69+
70+ # Initial search depth. Used to compare against current depth for DoBraceNestedTables.
71+ [Parameter (Position = 1 )]
72+ [int ] $StartingDepth = 1 ,
73+
74+ # Current depth. Note that PSVariables are still iterated at depth 0, so that a pipeline of GetVariables
75+ [Parameter (Position = 2 )]
76+ [int ] $CurrentDepth = $StartingDepth ,
77+
78+ # Include the key/value pairs for null or otherwise empty objects.
79+ [switch ] $ShowEmpty ,
80+
81+ # Wrap nested HashTables/PSObjects in `{}`
82+ [switch ] $DoBraceNestedTables
83+ )
84+ begin {
85+ $paramTable = @ {StartingDepth = $StartingDepth ; ShowEmpty = $ShowEmpty ; DoBraceNestedTables = $DoBraceNestedTables }
86+ }
87+ process {
88+ $resultList = [Collections.ArrayList ]::new()
89+ foreach ($item in $InputObject ) {
90+ Write-Verbose " Object '$item ', CurrentDepth '$CurrentDepth ',"
91+ # if the input object is a dictionary, convert it to a PSCustomObject so we can use its properties.
92+ # this is useful for converting HashTables to objects.
93+ if ($item -is [System.Collections.IDictionary ]) {
94+ $item = [PSCustomObject ]$item
95+ }
96+
97+ $result = if ($null -eq $item ) {
98+ $null
99+ } elseif ($item -is [Management.Automation.PSVariable ] -and $CurrentDepth -ge 0 ) {
100+ " $ ( $item.Name ) : $ ( Format-OneLineRecursive $item.Value - CurrentDepth($CurrentDepth - 1 ) @paramTable ) "
101+ } elseif ($CurrentDepth -le 0 ) {
102+ # anything recursive above this line must have a depth-check to prevent infinite recursion.
103+ $item.ToString ()
104+ } elseif ($item -is [Collections.IEnumerable ]) {
105+ # if it's an IEnumerable, use its items
106+ ($item |
107+ ForEach-Object {
108+ if ($ShowEmpty -or $_ ) {
109+ Format-OneLineRecursive $_ - CurrentDepth ($CurrentDepth - 1 ) @paramTable
110+ }
111+ }
112+ ) -join ' ; '
113+ } elseif ($item -is [Management.Automation.PSObject ]) {
114+ # if it's a PSObject, use its properties
115+ $psObjectRendered = ($item.PSObject.Properties |
116+ ForEach-Object {
117+ if ($ShowEmpty -or $_.Value ) {
118+ " $ ( $_.Name ) : $ ( Format-OneLineRecursive $_.Value - CurrentDepth ($CurrentDepth - 1 ) @paramTable ) "
119+ }
120+ }
121+ ) -join ' ; '
122+ if ($DoBraceNestedTables -and $CurrentDepth -ne $StartingDepth ) {
123+ $psObjectRendered = " {$psObjectRendered }"
124+ }
125+ # output
126+ $psObjectRendered
127+ } else {
128+ # if it's not a PSObject or IDictionary, just use ToString()
129+ $item.ToString ()
130+ }
131+ # replace excess whitespace/newlines with a single space.
132+ $resultList.Add (($result -replace ' \s+' , ' ' )) | Out-Null
133+ }
134+ # Then output.
135+ $resultList -join ' ; '
136+ }
137+ }
0 commit comments