Indent.psm1
|
function Indent { <# .SYNOPSIS Indents each line of a string or text input. .DESCRIPTION The Indent function adds the specified indentation to every line in a multiline string. It processes input from the pipeline and supports custom indent strings and counts. Empty lines can be optionally indented or left as-is. .PARAMETER s The string to indent. Accepts pipeline input and can be empty. .PARAMETER Count The number of indent units to add to each line; default 2. Must be positive. .PARAMETER Indent The string to use as one indent unit. Default is a single space " ". Can be any string (e.g., "`t" for tabs, " " for two spaces, ">" for arrows). .PARAMETER RegexThreshold The length threshold for using regex-based processing. Default 16384. If the input string is shorter than this threshold, regex replacement is used; otherwise, line-by-line processing is used to avoid memory overhead. .PARAMETER IndentEmptyLines If specified, empty lines will also receive indentation. By default, empty lines are returned as-is without indentation. .PARAMETER TrimInput If specified, trailing whitespace is removed from each input string before processing. .EXAMPLE "xy", " yz", "", "zx `nz" | Indent -Count 1 -Indent " " -TrimInput # indent inputs with a single tab character after trimming whitespace from the # right of each; literal output below # xy # yz # # zx # z .INPUTS System.String. You can (and most likely will) pipe strings to this function. .OUTPUTS System.String. Returns indented string lines. .LINK https://github.com/jonathandung/Indent .LINK https://www.powershellgallery.com/packages/Indent .LINK https://jonathandung.github.io/Indent .NOTES This function makes use of System.IO.StringReader to achieve efficient line-by-line processing and avoid memory overhead. #> [CmdletBinding()] param( [Parameter( Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName )][AllowEmptyString()][string]$s, [Parameter(Position = 1)][ValidateRange(1, [int]::MaxValue)][int]$Count = 2, [ValidateRange(1, [int]::MaxValue)][int]$RegexThreshold = 16384, [ValidateNotNullOrEmpty()][string]$Indent = " ", [switch]$IndentEmptyLines, [switch]$TrimInput ) begin { $i = $Indent * $Count $M = [System.Text.RegularExpressions.RegexOptions]::Multiline if ($IndentEmptyLines) { $p = '^' $e = $i } else { $p = '^(?=.)' $e = "" } } process { if ($TrimInput) {$s = $s.TrimEnd()} if ("" -eq $s) {return $e} if ($s.Length -lt $RegexThreshold) {return [Regex]::Replace($s, $p, $i, $M)} $r = [System.IO.StringReader]::new($s) if ($IndentEmptyLines) { while ($null -ne ($l = $r.ReadLine())) {"$i$l"} } else { while ($null -ne ($l = $r.ReadLine())) {if ($l -eq "") {""} else {"$i$l"}} } } } filter IndentFilter { <# .SYNOPSIS Indents each pipeline input by two spaces as if it were a single line. .DESCRIPTION This filter version is faster than the function version, but only applies to the above call pattern. Unlike Indent, it only applies the indentation to the first line and does not split multiline strings into individual lines automatically. Thus, it is only useful for Cmdlets that stream lines, which are still numerous. .EXAMPLE "1", "2", "3" | Indent # is equivalent to: "1", "2", "3" | IndentFilter .LINK https://github.com/jonathandung/Indent .LINK https://www.powershellgallery.com/packages/Indent .LINK https://jonathandung.github.io/Indent #> if ($_ -eq "") {""} else {" $_"} } |