Files
PowerShell-PSReadLine/GenerateFunctionHelp.ps1
T
Jason Shirk 416ca3e4e3 Rename Microsoft.PowerShell.PSReadline.dll
To work around PowerShell Core not loading the dll from the same
directory as PSReadLine.psd1, I've renamed the dll.
2017-12-01 17:05:43 -08:00

213 lines
6.5 KiB
PowerShell

param(
$Configuration = 'Release',
[Parameter(Mandatory)]
$OutFile
)
$errorActionPreference = "Stop"
$ourAssembly = "$PSScriptRoot\PSReadLine\bin\$Configuration\Microsoft.PowerShell.PSReadLine2.dll"
$t ='Microsoft.PowerShell.PSConsoleReadLine' -as [type]
if ($null -ne $t -and $t.Assembly.Location -ne $ourAssembly)
{
# Make sure we're runnning in a non-interactive session by relaunching
powershell -NoProfile -NonInteractive -File $PSCommandPath $Configuration $OutFile
exit $LASTEXITCODE
}
try {
Import-Module "$PSScriptRoot\bin\$Configuration\PSReadLine\PSReadLine.psd1"
$helpContent = [xml](Get-Content "$PSScriptRoot\PSReadLine\bin\$Configuration\Microsoft.PowerShell.PSReadLine.xml")
Set-PSReadLineOption -EditMode Windows
$cmdKeyBindings = Get-PSReadLineKeyHandler -Bound
Set-PSReadLineOption -EditMode Emacs
$emacsKeyBindings = Get-PSReadLineKeyHandler -Bound
Set-PSReadLineOption -EditMode Vi
$viKeyBindings = Get-PSReadLineKeyHandler -Bound
$bindableFunctionsFromReflection = ((Get-Command Set-PSReadLineKeyHandler).Parameters['Function'].Attributes).ValidValues
[enum]::GetNames([Microsoft.PowerShell.KeyHandlerGroup]) |
ForEach-Object { '{0},{1}' -f $_,[Microsoft.PowerShell.KeyHandler]::GetGroupingDescription($_) } |
ForEach-Object { $groupingDescriptions = @{} } { $k,$v = $_ -split ',',2; $groupingDescriptions[$k] = $v }
class BindableFunction
{
[string]$Function
[string]$Description
[string[]]$CmdBindings = @()
[string[]]$EmacsBindings = @()
[string[]]$ViInsBindings = @()
[string[]]$ViCmdBindings = @()
# Can't use the following type because it's not loaded at parse time
<#[Microsoft.PowerShell.KeyHandlerGroup]#>[object]$Group
}
$allFunctions = @{}
foreach ($fn in $bindableFunctionsFromReflection)
{
$bindableFn = [BindableFunction]::new()
$bindableFn.Function = $fn
$bindableFn.Group = [Microsoft.PowerShell.PSConsoleReadLine]::GetDisplayGrouping($fn)
$allFunctions[$fn] = $bindableFn
}
foreach ($member in $helpContent.doc.members.member)
{
$re = [regex]'^M:Microsoft\.PowerShell\.PSConsoleReadLine\.([a-zA-Z]+)\(System\.Nullable\{System\.ConsoleKeyInfo\},System.Object\)$'
$name = $member.GetAttribute('name')
if ($name -match $re)
{
$fn = $matches[1]
$bindableFn = $allFunctions[$fn]
if ($null -eq $bindableFn) { continue }
$summary = $member.summary
if ($summary -is [System.Xml.XmlElement])
{
# Special case to handle a cref, this is not generic code
$parts = foreach ($c in $summary.ChildNodes)
{
if ($c -is [System.Xml.XmlText])
{
$c.InnerText
}
elseif ($c -is [System.Xml.XmlElement])
{
$null = $c.cref -match $re
$matches[1]
}
}
$summary = $parts -join ''
}
$bindableFn.Description = $summary.Trim()
}
}
foreach ($binding in $cmdKeyBindings)
{
$allFunctions[$binding.Function].CmdBindings += $binding.Key
}
foreach ($binding in $emacsKeyBindings)
{
$allFunctions[$binding.Function].EmacsBindings += $binding.Key
}
foreach ($binding in $viKeyBindings)
{
$mode = if ($binding.Key[0] -eq '<') { 'ViCmdBindings' } else { 'ViInsBindings' }
# Some vi functions are private but are stil reported by Get-PSReadLineKeyHandler
$bindableFn = $allFunctions[$binding.Function]
if ($null -ne $bindableFn)
{
$bindableFn.$mode += $binding.Key
}
}
$indent = " "
$maxWidth = 90
$allFunctions.Values |
Group-Object -Property Group |
Sort-Object {[Microsoft.PowerShell.KeyHandlerGroup]$_.Name} |
ForEach-Object {
$label = $groupingDescriptions[$_.Name]
" {0}`n {1}`n" -f $label, ('-' * $label.Length)
$_.Group | Sort-Object Function | ForEach-Object {
$desc = $_.Description -replace "`n",'' -replace " +"," "
if ($desc.Length - $indent.Length -gt $maxWidth)
{
# Wrap the text
$sb = [System.Text.StringBuilder]::new()
$col = $indent.Length
$words = $desc -split ' '
foreach ($word in $words)
{
if ($col + $word.Length -gt $maxWidth)
{
$null = $sb.Append("`n$indent")
$col = $indent.Length
}
$col += ($word.Length + 1)
$null = $sb.Append($word)
$null = $sb.Append(" ")
}
$null = $sb.Remove($sb.Length - 1, 1)
$desc = $sb.ToString()
}
$sb = [System.Text.StringBuilder]::new()
$null = if ($_.CmdBindings.Length -gt 0) {
$sb.Append($indent)
$sb.Append("Cmd: <")
$sb.Append($_.CmdBindings -join '>, <')
$sb.Append('>')
}
$null = if ($_.EmacsBindings.Length -gt 0) {
if ($sb.Length -gt 0) { $sb.AppendLine() }
$sb.Append($indent)
$sb.Append("Emacs: <")
$sb.Append($_.EmacsBindings -join '>, <')
$sb.Append('>')
}
$null = if ($_.ViInsBindings.Length -gt 0) {
if ($sb.Length -gt 0) { $sb.AppendLine() }
$sb.Append($indent)
$sb.Append("Vi insert mode: <")
$sb.Append($_.ViInsBindings -join '>, <')
$sb.Append('>')
}
$null = if ($_.ViCmdBindings.Length -gt 0) {
if ($sb.Length -gt 0) { $sb.AppendLine() }
$sb.Append($indent)
$sb.Append("Vi command mode: ")
$sb.Append($_.ViCmdBindings -join ', ')
}
if ($sb.Length -eq 0)
{
$bindings = "${indent}Function is unbound."
}
else {
$bindings = $sb.ToString()
}
" {0}:`n`n{1}{2}`n`n{3}`n" -f $_.Function, $indent, $desc, $bindings
}
} | Out-File -LiteralPath $OutFile -Encoding ascii
} catch
{
& {
[Microsoft.PowerShell.PSConsoleReadLine].Assembly.Location | Out-String
$_ | Out-String
$_.Exception | Out-String
$_.Exception.StackTrace | Out-String
$_.Exception.InnerException | Out-String
$_.Exception.InnerException.StackTrace | Out-String
} | Out-Host
exit 1
}
exit 0