functions/New-PSFunctionInfo.ps1

Function New-PSFunctionInfo {
    [cmdletbinding(SupportsShouldProcess)]
    [alias('npfi')]
    Param(
        [Parameter(
            Position = 0,
            Mandatory,
            HelpMessage = "Specify the name of the function"
        )]
        [ValidateNotNullOrEmpty()]
        [string]$Name,
        [Parameter(Mandatory, HelpMessage = "Specify the path that contains the function")]
        [ValidateNotNullOrEmpty()]
        [ValidateScript( {
            if (Test-Path $_) {
                return $True
            }
            else {
                Throw "Cannot find the specified file $_."
                return $False
            }
        })]
        [ValidatePattern("\.ps1$")]
        [string]$Path,
        [string]$Author = [System.Environment]::UserName,
        [string]$CompanyName,
        [string]$Copyright = (Get-Date).Year,
        [string]$Description,
        [ValidateNotNullOrEmpty()]
        [string]$Version = "1.0.0",
        [string[]]$Tags,
        [Parameter(HelpMessage = "Copy the metadata to the clipboard. The file is left untouched.")]
        [alias("clip")]
        [switch]$ToClipboard,
        [Parameter(HelpMessage = "Create a backup copy of the source file before inserting the metadata comment block.")]
        [switch]$Backup,
        [Parameter(HelpMessage = "Do not insert the source file path into the metadata comment block.")]
        [switch]$NoSource
    )
    Begin {
        Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($myinvocation.mycommand)"
        [guid]$Guid = $(([guid]::NewGuid()).guid)
        [string]$updated = Get-Date -Format g
    } #begin

    Process {
        Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Creating this metadata"

        if ($NoSource) {
            $src = $null
        }
        else {
            $src = $(Convert-Path $Path)
        }
        $info = @"
 
<# PSFunctionInfo
 
Version $Version
Author $Author
CompanyName $CompanyName
Copyright $Copyright
Description $Description
Guid $Guid
Tags $($Tags -join ",")
LastUpdate $Updated
Source $src
 
#>
"@


        Write-Verbose $info
        if ($ToClipboard) {
            Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Copying the metadata to clipboard"
            if ($pscmdlet.shouldprocess("function metadata", "Copy to clipboard")) {
                Set-Clipboard -Value $info
            }
        }
        else {
            #backup file if requested
            if ($Backup) {
                Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Backing up the source file $Path."
                Try {
                    backup_file -path $path
                }
                Catch {
                    Throw $_
                }
            }
            #get the contents of the script file
            Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting the file contents from $Path"

            $file = [System.Collections.Generic.list[string]]::New()
            Get-Content -Path $path | ForEach-Object {
                $file.add($_)
            }

            #find the function line
            Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Searching for Function $Name"
            $find = $file | Select-String -Pattern "^(\s+)?(F|f)unction $name(\s+|\{)?"
            if ($find.count -gt 1) {
                Write-Warning "Detected multiple matches for Function $name in $Path. Unable to insert metadata."
                #bail out
                return
            }
            elseif ($find.count -eq 1) {
                #$index = $file.findIndex( { $args[0] -match "^(\s+)?Function $name(\s+|\{)" })
                #the index for the file list will be 1 less than the pattern match
                $index = $find.Linenumber - 1
            }
            else {
                Write-Warning "Failed to find a function called $Name in $path."
                return
            }

            #find the opening { for the function
            Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting the position of the opening {"
            $i = $index
            do {
                Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Testing index $i"
                if ($file[$i] -match "\{") {
                    Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Found opening { at $i"
                    $found = $True
                }
                else {
                    Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] incrementing index"
                    $i++
                }
            } until ($found -OR $i -gt $file.count)

            if ($i -gt $file.count) {
                Write-Warning "Failed to find the opening { for Function $Name."
                return
            }

            #test for an existing PSFunctionInfo entry in the next 5 lines
            if ($file[$i..($i + 5)] | Select-String -Pattern "PSFunctionInfo" -Quiet) {
                Write-Warning "An existing PSFunctionInfo entry has been detected."
            }
            else {
                # insert after the opening {
                Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Inserting metadata at position $($i+1)"
                $file.Insert(($i + 1), $info)

                #write the new data to the file
                Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Updating $path"
                $file | Set-Content -Path $Path
            }

        } #else process the file
    } #process

    End {
        Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($myinvocation.mycommand)"
    } #end

} #close New-PSFunctionInfo