Utils/expand.ps1

Register-GnuUtil @{
    Name          = 'expand'
    Category      = 'Text processing'
    Synopsis      = 'Convert tabs to spaces.'
    Usage         = @('expand [OPTION]... [FILE]...')
    Description   = @('Convert tabs in each FILE to spaces, writing to standard output.', '', 'With no FILE, or when FILE is -, read standard input.')
    FileOperands  = $true
    NumericOption = 't'
    Options       = @(
        @{ Short = 'i'; Long = 'initial'; Help = 'do not convert tabs after non blanks' }
        @{ Short = 't'; Long = 'tabs'; Arg = 'LIST'; Multi = $true; Help = 'use comma separated list of tab positions. The last specified position can be prefixed with ''/'' to specify a tab size to use after the last explicitly specified tab stop. Also a prefix of ''+'' can be used to align remaining tab stops relative to the last specified tab stop instead of the first column' }
    )
    Notes         = @('-t N (or -N) sets tabs N characters apart, instead of the default of 8.')
}



function script:ConvertTo-GnuExpandedLine {
    <#
    .SYNOPSIS
    Expands the tabs of one line.
    #>

    param(
        [Parameter(Mandatory)][AllowEmptyString()][string]$Line,
        [Parameter(Mandatory)][hashtable]$TabStops,
        [switch]$Initial
    )

    if ($Line.IndexOf("`t", [System.StringComparison]::Ordinal) -lt 0) { return $Line }
    $builder = New-Object System.Text.StringBuilder
    $column = 0
    $leading = $true
    foreach ($char in $Line.ToCharArray()) {
        if ($char -eq "`t" -and (-not $Initial -or $leading)) {
            $next = Get-GnuNextTabStop -TabStops $TabStops -Column $column
            if ($next -lt 0) { $next = $column + 1 }   # GNU: past the last stop a tab becomes one space
            [void]$builder.Append(' ', $next - $column)
            $column = $next
            continue
        }
        if ($char -ne ' ' -and $char -ne "`t") { $leading = $false }
        if ([int]$char -eq 8) { if ($column -gt 0) { $column-- } }
        else { $column++ }
        [void]$builder.Append($char)
    }
    $builder.ToString()
}