Functions/GenXdev.Coding.Templating/Remove-DoubleEmptyLines.ps1
|
################################################################################ <# .SYNOPSIS Removes double (consecutive) empty lines from a code string, optionally reformatting the output. .DESCRIPTION Cleans up source code or text by collapsing consecutive blank lines into a single empty line. This improves readability and follows common code formatting conventions. When the -Reformat switch is specified, additional formatting rules are applied to normalize the code structure. .LICENSE Copyright (C) 2026 René Vaessen / GenXdev This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. .PARAMETER code The source code or text string to process. Multiple consecutive empty lines within this text will be collapsed to a single empty line. .PARAMETER Reformat When specified, applies additional formatting rules beyond just removing double empty lines, such as normalizing indentation and spacing patterns. .EXAMPLE $cleanCode = $sourceCode | Remove-DoubleEmptyLines Pipes source code through the function to remove consecutive blank lines. .EXAMPLE Remove-DoubleEmptyLines -code $sourceCode -Reformat Removes double empty lines and applies additional formatting. #> function Remove-DoubleEmptyLines { [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [OutputType([string])] param( ########################################################################### [Parameter( Mandatory = $true, Position = 0, ValueFromPipeline = $false, HelpMessage = 'The source code or text string to process for ' + 'double empty line removal' )] [string] $code, ########################################################################### [Parameter( Mandatory = $false, ValueFromPipeline = $false, HelpMessage = 'Apply additional formatting rules beyond ' + 'double empty line removal' )] [switch] $Reformat ) begin { $sb = [System.Text.StringBuilder]::new() } process { $lines = $code.Replace("`r", "`n").Split("`n", [System.StringSplitOptions]::RemoveEmptyEntries); $lastNonEmptyLine = [string]::Empty $previousLastNonEmptyLine = [string]::Empty $lastLineWasEmpty = $false $hadSameLineStart = $false for ($i = 0; $i -lt $lines.Count; $i++) { $line = $lines[$i].TrimEnd() $isEmptyLine = [string]::IsNullOrWhiteSpace($line) $isOpeningBrace = $line.Trim().EndsWith("{") $isClosingBrace = $line.Trim().EndsWith("}") $isLastLine = ($i -eq $lines.Count - 1) # determine if next line is empty or closing brace $nextLineIsEmpty = $false $nextLineIsClosingBrace = $false if ($i + 1 -lt $lines.Count) { $nextLine = $lines[$i + 1].TrimEnd() $nextLineIsEmpty = [string]::IsNullOrWhiteSpace($nextLine) $nextLineIsClosingBrace = $nextLine.Trim().StartsWith("}") } $previousLastNonEmptyLine = $lastNonEmptyLine $lastNonEmptyLine = if (-not $isEmptyLine) { $line } else { $lastNonEmptyLine } # handle empty lines if ($isEmptyLine) { # skip empty lines at the end of the file if ($isLastLine) { continue } # rule 2: never output empty line before closing brace if ($nextLineIsClosingBrace) { # skip this empty line continue } # rule 3: never output two empty lines in a row if ($lastLineWasEmpty) { # skip this empty line continue } # output single empty line $null = $sb.Append("`r`n") $lastLineWasEmpty = $true } else { if ($Reformat) { $hadSameLineStart = $false if ($previousLastNonEmptyLine.Trim().Length -gt 4 -and $lastNonEmptyLine.Trim().Length -gt 4) { if ($previousLastNonEmptyLine.Trim().Substring(0, 4) -eq $lastNonEmptyLine.Trim().Substring(0, 4)) { while ($sb.Length -ge 0 -and ("`r`n `t".IndexOf($sb[$sb.Length - 1]) -ge 0)) { $null = $sb.Remove($sb.Length - 1, 1) } $null = $sb.Append("`r`n") $hadSameLineStart = $true } } if ((-not $lastLineWasEmpty) -and (-not $hadSameLineStart) -and (-not $isOpeningBrace) -and (-not $isLastLine) -and (-not $isClosingBrace)) { $null = $sb.Append("`r`n") } } if ($isOpeningBrace -and ((-not $nextLineIsEmpty) -or ($nextLine.Trim().EndsWith("{"))) -and (-not $isLastLine)) { $null = $sb.Append("`r`n") } # output non-empty line if ($isLastLine) { $null = $sb.Append($line) } else { $null = $sb.Append($line).Append("`r`n") } $lastLineWasEmpty = $false if ($isOpeningBrace -and (-not $nextLineIsEmpty) -and -not $isLastLine) { $null = $sb.Append("`r`n") $lastLineWasEmpty = $true } } } } end { Microsoft.PowerShell.Utility\Write-Output ($sb.ToString()) } } ################################################################################ |