Public/Install/Uninstall-PwshProfile.ps1

function Uninstall-PwshProfile {
    <#
    .SYNOPSIS
        Removes the ScrewCitySoftware.PwshProfile bootstrap block from a profile file.
 
    .DESCRIPTION
        Deletes the marker-wrapped managed block that Install-PwshProfile writes (the module
        import plus the Initialize-PwshProfile call between the conda-style sentinels),
        preserving every other line in the file. It is the counterpart to Install-PwshProfile;
        to merely change settings, re-run Install instead (it rewrites the block in place).
 
        This touches ONLY the profile file. It does NOT uninstall any tools, Nerd Fonts, or
        PowerShell modules that were installed during setup — removing the bootstrap simply stops
        the module from initializing on future sessions.
 
        Only the marker-delimited block is removed. A hand-written, unmanaged
        'Import-Module ScrewCitySoftware.PwshProfile' (with no markers) is left untouched, since it
        is your own code rather than the managed injection.
 
        Supports -WhatIf / -Confirm; the single write is the only mutating action and is fully gated.
        Throws if -Path is a directory.
 
        Returns one [pscustomobject] with Path, Action ('Removed' | 'NotInstalled'), and Changed
        ([bool]).
 
    .PARAMETER Path
        The profile file to clean. Defaults to $PROFILE (current user, current host) — the same
        default as Install-PwshProfile. $PROFILE is host-specific.
 
    .PARAMETER PassThru
        Emit the result object. By default the command returns nothing.
 
    .EXAMPLE
        Uninstall-PwshProfile
 
        Removes the managed bootstrap block from $PROFILE, leaving any other profile code intact.
 
    .EXAMPLE
        Uninstall-PwshProfile -Path $PROFILE.CurrentUserAllHosts -WhatIf
 
        Previews removing the block from the all-hosts profile without changing anything.
 
    .NOTES
        $PROFILE is host-specific (VS Code and ISE use different files). The file is rewritten as
        UTF-8 without a BOM. If removing the block leaves the file empty, the (empty) file is left
        in place rather than deleted.
 
        Under -WhatIf the returned object describes the action that *would* be taken (e.g.
        Action = 'Removed', Changed = $true) — the write is skipped, so the result reflects intent,
        not a change that happened.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string]$Path = $PROFILE,

        [Parameter()]
        [switch]$PassThru
    )

    if (Test-Path -LiteralPath $Path -PathType Container) {
        throw "Uninstall-PwshProfile: '$Path' is a directory, not a profile file."
    }

    $marker = Get-PwshProfileMarker

    $result = [pscustomobject]@{
        Path    = $Path
        Action  = 'NotInstalled'
        Changed = $false
    }

    if (Test-Path -LiteralPath $Path -PathType Leaf) {
        $existing = Get-Content -LiteralPath $Path -Raw -Encoding utf8
        if ($null -eq $existing) { $existing = '' }

        # Match the managed block and consume its closing line terminator plus one optional blank
        # separator line (the gap Install inserts above existing content), leaving everything else
        # — and the user's line endings — intact. An empty replacement avoids regex $-substitution.
        $pattern = '(?s)' + [regex]::Escape($marker.Open) + '.*?' + [regex]::Escape($marker.Close) + '\r?\n?(\r?\n)?'
        $new = [regex]::Replace($existing, $pattern, '')

        if ($new -ne $existing) {
            if ($PSCmdlet.ShouldProcess($Path, 'Remove ScrewCitySoftware.PwshProfile bootstrap')) {
                Set-Content -LiteralPath $Path -Value $new -Encoding utf8 -NoNewline
            }
            $result.Action = 'Removed'
            $result.Changed = $true
        }
        elseif ($existing -match '(?im)^\s*Import-Module\s+ScrewCitySoftware\.PwshProfile\b') {
            Write-Verbose "Uninstall-PwshProfile: found a hand-written import (no managed block) in '$Path'; left untouched."
        }
    }

    if (-not $WhatIfPreference -and (Get-Command Format-SpectrePanel -ErrorAction SilentlyContinue)) {
        if ($result.Action -eq 'Removed') {
            $color = 'Green'
            $msg = 'Bootstrap removed. Installed tools and fonts were left untouched.'
        }
        else {
            $color = 'Yellow'
            $msg = 'No managed bootstrap block found — nothing to remove.'
        }
        if (Get-Command Write-SpectreHost -ErrorAction SilentlyContinue) { Write-SpectreHost '' }
        "[$color]$msg[/]`n[grey]$($result.Path)[/]" | Format-SpectrePanel -Header 'Uninstall' -Border Rounded -Color $color -Expand | Out-Host
    }

    if ($PassThru) { $result }
}