Thursday, May 23, 2024
HomePowershellHow one can Effectively Take away Feedback from Your PowerShell Script

How one can Effectively Take away Feedback from Your PowerShell Script


My purpose was to have a PowerShell perform that removes any remark inside my code besides assist feedback. Fortunately, with assist from Chris Dent, I created a technique that eliminates feedback from any given file and makes it manufacturing prepared. Whereas it is a part of my module builder PSPublishModule, I am attaching it if you wish to attempt it by yourself.

perform Take away-Feedback {
    <#
    .SYNOPSIS
    Take away feedback from PowerShell file

    .DESCRIPTION
    Take away feedback from PowerShell file and optionally take away empty strains
    By default feedback in param block will not be eliminated
    By default feedback earlier than param block will not be eliminated

    .PARAMETER SourceFilePath
    File path to the supply file

    .PARAMETER Content material
    Content material of the file

    .PARAMETER DestinationFilePath
    File path to the vacation spot file. If not offered, the content material shall be returned

    .PARAMETER RemoveEmptyLines
    Take away empty strains if a couple of empty line is discovered

    .PARAMETER RemoveAllEmptyLines
    Take away all empty strains from the content material

    .PARAMETER RemoveCommentsInParamBlock
    Take away feedback in param block. By default feedback in param block will not be eliminated

    .PARAMETER RemoveCommentsBeforeParamBlock
    Take away feedback earlier than param block. By default feedback earlier than param block will not be eliminated

    .EXAMPLE
    Take away-Feedback -SourceFilePath 'C:SupportGitHubPSPublishModuleExamplesTestScript.ps1' -DestinationFilePath 'C:SupportGitHubPSPublishModuleExamplesTestScript1.ps1' -RemoveAllEmptyLines -RemoveCommentsInParamBlock -RemoveCommentsBeforeParamBlock

    .NOTES
    Many of the work carried out by Chris Dent, with enhancements by Przemyslaw Klys

    #>
    [CmdletBinding(DefaultParameterSetName="FilePath")]
    param(
        [Parameter(Mandatory, ParameterSetName="FilePath")]
        [alias('FilePath', 'Path', 'LiteralPath')][string] $SourceFilePath,

        [Parameter(Mandatory, ParameterSetName="Content")][string] $Content material,

        [Parameter(ParameterSetName="Content")]
        [Parameter(ParameterSetName="FilePath")]
        [alias('Destination')][string] $DestinationFilePath,

        [Parameter(ParameterSetName="Content")]
        [Parameter(ParameterSetName="FilePath")]
        [switch] $RemoveAllEmptyLines,

        [Parameter(ParameterSetName="Content")]
        [Parameter(ParameterSetName="FilePath")]
        [switch] $RemoveEmptyLines,

        [Parameter(ParameterSetName="Content")]
        [Parameter(ParameterSetName="FilePath")]
        [switch] $RemoveCommentsInParamBlock,

        [Parameter(ParameterSetName="Content")]
        [Parameter(ParameterSetName="FilePath")]
        [switch] $RemoveCommentsBeforeParamBlock,

        [Parameter(ParameterSetName="Content")]
        [Parameter(ParameterSetName="FilePath")]
        [switch] $DoNotRemoveSignatureBlock
    )
    if ($SourceFilePath) {
        $Fullpath = Resolve-Path -LiteralPath $SourceFilePath
        $Content material = [IO.File]::ReadAllText($FullPath, [System.Text.Encoding]::UTF8)
    }

    $Tokens = $Errors = @()
    $Ast = [System.Management.Automation.Language.Parser]::ParseInput($Content material, [ref]$Tokens, [ref]$Errors)
    #$functionDefinition = $ast.Discover({ $args[0] -is [FunctionDefinitionAst] }, $false)
    $groupedTokens = $Tokens | Group-Object { $_.Extent.StartLineNumber }
    $DoNotRemove = $false
    $DoNotRemoveCommentParam = $false
    $CountParams = 0
    $ParamFound = $false
    $SignatureBlock = $false
    $toRemove = foreach ($line in $groupedTokens) {
        if ($Ast.Physique.ParamBlock.Extent.StartLineNumber -gt $line.Identify) {
            proceed
        }
        $tokens = $line.Group
        for ($i = 0; $i -lt $line.Rely; $i++) {
            $token = $tokens[$i]
            if ($token.Extent.StartOffset -lt $Ast.Physique.ParamBlock.Extent.StartOffset) {
                proceed
            }

            # Lets discover feedback between perform and param block and never take away them
            if ($token.Extent.Textual content -eq 'perform') {
                if (-not $RemoveCommentsBeforeParamBlock) {
                    $DoNotRemove = $true
                }
                proceed
            }
            if ($token.Extent.Textual content -eq 'param') {
                $ParamFound = $true
                $DoNotRemove = $false
            }
            if ($DoNotRemove) {
                proceed
            }
            # lets discover feedback between param block and finish of param block
            if ($token.Extent.Textual content -eq 'param') {
                if (-not $RemoveCommentsInParamBlock) {
                    $DoNotRemoveCommentParam = $true
                }
                proceed
            }
            if ($ParamFound -and ($token.Extent.Textual content -eq '(' -or $token.Extent.Textual content -eq '@(')) {
                $CountParams += 1
            } elseif ($ParamFound -and $token.Extent.Textual content -eq ')') {
                $CountParams -= 1
            }
            if ($ParamFound -and $token.Extent.Textual content -eq ')') {
                if ($CountParams -eq 0) {
                    $DoNotRemoveCommentParam = $false
                    $ParamFound = $false
                }
            }
            if ($DoNotRemoveCommentParam) {
                proceed
            }
            # if token not remark we go away it as is
            if ($token.Type -ne 'Remark') {
                proceed
            }

            # type of ineffective to not take away signature block if we're not eradicating feedback
            # this modifications the construction of a file and signature shall be invalid
            if ($DoNotRemoveSignatureBlock) {
                if ($token.Type -eq 'Remark' -and $token.Textual content -eq '# SIG # Start signature block') {
                    $SignatureBlock = $true
                    proceed
                }
                if ($SignatureBlock) {
                    if ($token.Type -eq 'Remark' -and $token.Textual content -eq '# SIG # Finish signature block') {
                        $SignatureBlock = $false
                    }
                    proceed
                }
            }
            $token
        }
    }
    $toRemove = $toRemove | Type-Object { $_.Extent.StartOffset } -Descending
    foreach ($token in $toRemove) {
        $StartIndex = $token.Extent.StartOffset
        $HowManyChars = $token.Extent.EndOffset - $token.Extent.StartOffset
        $content material = $content material.Take away($StartIndex, $HowManyChars)
    }
    if ($RemoveEmptyLines) {
        # Take away empty strains if a couple of empty line is discovered. If it is only one line, go away it as is
        #$Content material = $Content material -replace '(?m)^s*$', ''
        #$Content material = $Content material -replace "(`r?`n){2,}", "`r`n"
        # $Content material = $Content material -replace "(`r?`n){2,}", "`r`n`r`n"
        $Content material = $Content material -replace '(?m)^s*$', ''
        $Content material = $Content material -replace "(?:`r?`n|n|r)", "`r`n"
    }
    if ($RemoveAllEmptyLines) {
        # Take away all empty strains from the content material
        $Content material = $Content material -replace '(?m)^s*$(r?n)?', ''
    }
    if ($Content material) {
        $Content material = $Content material.Trim()
    }
    if ($DestinationFilePath)  Set-Content material -Path $DestinationFilePath -Encoding utf8
     else {
        $Content material
    }
}

This perform has a few parameters:

  • SourceFilePath – present a path to a file you need to clear up
  • Content material – alternatively to file manner, you can even present a code (for instance Get-Content material -Uncooked $FilePath)
  • DestinationFilePath – path to file the place to save lots of the cleaned-up file. If not offered, the content material shall be returned immediately as a string.
  • RemoveEmptyLines – as a part of the cleanup, it tries to take away empty strains, however provided that there’s a couple of. That is helpful in case you have assist with the perform
  • RemoveAllEmptyLines – removes all empty strains from a file
  • RemoveCommentsInParamBlock – by default, throughout cleanup, any feedback contained in the param block will not be eliminated, as these are sometimes associated to assist. However if you would like, you can even take away these with this swap.
  • RemoveCommentsBeforeParamBlock – I do not take away something between the perform and param block by default. This ensures that the assistance I create for the perform stays the place it’s. However if you wish to take away it, that is how one can repair it.
  • DoNotRemoveSignatureBlock – by default, we take away any signature from a file, however if you wish to forestall that from occurring, you should use this swap. It will not provide you with a lot as a result of the signature is not going to work after you take away something from the file anyhow – however it’s there.
RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments