functions/Copy-HelpExample.ps1
|
function Copy-HelpExample { [cmdletbinding()] [alias('che')] param( [Parameter( Position = 0, Mandatory, HelpMessage = 'Enter the name of the PowerShell command' )] [ValidateScript({ if (Get-Command $_) { $True } else { throw "Can't find a command called $_" } })] [string]$Name, [Parameter( HelpMessage = 'Gets help that explains how the cmdlet works in the specified provider path. Enter a PowerShell provider path.' )] [ValidateScript({ Test-Path $_ })] [string]$Path ) dynamicparam { if ($IsWindows -or ($PSEdition -eq 'Desktop')) { #The dynamic parameter name $paramName = 'UseGridView' #define a parameter attribute object $attributes = New-Object System.Management.Automation.ParameterAttribute $attributes.HelpMessage = 'Select help examples using Out-GridView.' #define a collection for attributes $attributeCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute] $attributeCollection.Add($attributes) #define an alias $alias = [System.Management.Automation.AliasAttribute]::new('ogv') $attributeCollection.Add($alias) #define the dynamic param $dynParam1 = New-Object -Type System.Management.Automation.RuntimeDefinedParameter($paramName, [Switch], $attributeCollection) #create array of dynamic parameters $paramDictionary = New-Object -Type System.Management.Automation.RuntimeDefinedParameterDictionary $paramDictionary.Add($paramName, $dynParam1) #use the array return $paramDictionary } #if } #dynamic param begin { Write-Verbose "Starting $($MyInvocation.MyCommand)" Write-Verbose "Running under PowerShell version $($PSVersionTable.PSVersion)" #A regex pattern to strip off prompts, comments and empty lines from the code sample $rx = [System.Text.RegularExpressions.Regex]::new('(PS.*>)|(#.*)|(^\s$)', 'Multiline') #8 July 2026 Added to parse code samples from PowerShell 7 help #[regex]$codeRx = '(?<=powershell\n).*(?=\n```)' $codeRx = [System.Text.RegularExpressions.Regex]::new('(?<=powershell\n).*(?=\n```)', 'Multiline') #adjust PSBoundParameters $PSBoundParameters.Add('Examples', $True) if ($PSBoundParameters.ContainsKey('UseGridView')) { #remove this parameter from PSBoundParameters because it doesn't belong to Get-Help [void]($PSBoundParameters.Remove('UseGridView')) #set a flag $ogv = $True } } #begin process { Write-Verbose "Getting help examples for $Name" $help = Get-Help @PSBoundParameters if ($help.examples.example.count -gt 0) { #8 July 2026 Help in PowerShell 7 is structured differently if ($help.examples.example.code -match "\w+") { $choices = $help.examples.example | Select-Object -Property Title, @{Name = 'CodeSample'; Expression = { ($rx.replace($_.code, '')).trim() } } } elseif ($help.examples.example.introduction -match "```powershell" ) { $choices = $help.examples.example | Select-Object -Property Title, @{Name = 'CodeSample'; Expression = { ($codeRx.Match($_.introduction.text)).value.trim() } } } #force the ISE to use Out-GridView if ($ogv -or ($host.name -match 'PowerShell ISE')) { Write-Verbose 'Launching Out-GridView' $choices | Out-GridView -Title 'Select one or more code samples to copy' -PassThru | ForEach-Object { $_.CodeSample } | Set-Clipboard } #if GridView else { #Use console menu $hash = @{} $head = @" $([char]0x1b)[1;4mCode Samples$([char]0x1b)[0m Each help example is numbered to the left. At the prompt below, select the code samples you want to copy to the clipboard. Separate multiple values with a comma. Some example code includes the output. "@ $head for ($i = 0; $i -lt $choices.count; $i++) { <# 8 July 2026 Some help files put the code sample in the remarks or introduction. this may be more of an issue in PowerShell 7 #> if ($choices[$i].CodeSample) { "`r" "$([char]0x1b)[96m[$($i+1)]$([char]0x1b)[0m $($choices[$i].title.trim())" "`r" " $($choices[$i].CodeSample)" #add the sample to the temporary hashtable $hash.add(($i + 1).ToString(), $choices[$i].CodeSample) } } if ($hash.Keys.count -gt 0) { #prompt the user for a choice $r = Read-Host "`n$([char]0x1b)[38;5;46mPlease select items to copy to the clipboard by number. Separate multiple entries with a comma. Press Enter alone to cancel$([char]0x1b)[0m" if ($r -match ',') { $items = $r.split(',') } elseif ($r -match '\d') { $items = $r } else { Write-Verbose 'You must have cancelled.' } #initialize a list to hold the choices $select = [System.Collections.Generic.List[string]]::new() if ($items) { foreach ($item in $items) { Write-Verbose "getting item $item" $select.add($hash.item($item)) } } #copy all the selections to the clipboard $select | Set-Clipboard } else { Write-Warning "This command doesn't have code examples that you can copy with this command." } } #use console } #if help examples found else { Write-Warning "No help or examples found for $Name" } } #process end { Write-Verbose "Ending $($MyInvocation.MyCommand)" } #end } #end function |