Public/Helpers/Show-BlackCatCommands.ps1
function Show-BlackCatCommands { [CmdletBinding()] param( [Parameter(Mandatory=$false, Position=0)] [Alias("cat", "c")] [ArgumentCompleter({ param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) # Get the Public folder path $publicFolderPath = Split-Path -Parent $PSScriptRoot # Get immediate subdirectories of Public (excluding Helpers) $categories = Get-ChildItem -Path $publicFolderPath -Directory | Where-Object { $_.Name -ne 'Helpers' } | Where-Object { # Only return directories that contain at least one PowerShell script (Get-ChildItem -Path $_.FullName -Filter "*.ps1" -File).Count -gt 0 } | Select-Object -ExpandProperty Name | Where-Object { $_ -like "$wordToComplete*" } return $categories })] [string]$Category ) try { Clear-Host # The module root is two levels up from the Helpers folder (since Helpers is inside Public) $moduleRoot = Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent $psd1Path = Join-Path -Path $moduleRoot -ChildPath "BlackCat.psd1" Write-Verbose "Looking for BlackCat.psd1 at $psd1Path" if (-not (Test-Path $psd1Path)) { throw "BlackCat.psd1 not found at $psd1Path" } $moduleManifest = Import-PowerShellDataFile -Path $psd1Path if (-not $moduleManifest.ContainsKey('FileList')) { throw "No 'FileList' key found in BlackCat.psd1" } $fileList = $moduleManifest['FileList'] $logo = @" __ ) ___ | | | | ___| __ \ | __ \ / | | __| | / | / _` | __| | | / ___ __| ( < | | ( | | ____/ _/ _| \___| _|\_\ \____| \ \__,_| \__| \____/ v$script:version by Rogier Dijkman "@ Write-Host $logo -ForegroundColor Blue $results = @() $fileCount = 0 foreach ($filePath in $fileList) { if ($Category) { # Normalize path separators for comparison $normalizedCategory = $Category -replace '[\\/]', [IO.Path]::DirectorySeparatorChar if ($filePath -notlike "*$normalizedCategory*") { continue } } $fileName = [IO.Path]::GetFileNameWithoutExtension((Split-Path -Path $filePath -Leaf)) $fileCount++ # Get full path to the file $fullFilePath = Join-Path -Path $moduleRoot -ChildPath $filePath $description = "No description available" # Try to extract description from the file if (Test-Path $fullFilePath) { # First attempt to load the function and get its help try { # Get just the function name without path $functionName = [System.IO.Path]::GetFileNameWithoutExtension($fullFilePath) # Try to get help for the function (only works if loaded) $helpInfo = Get-Help -Name $functionName -ErrorAction SilentlyContinue if ($helpInfo -and $helpInfo.Synopsis) { $description = $helpInfo.Synopsis.Trim() } } catch { # Fallback to parsing the file directly Write-Verbose "Couldn't get help for $functionName, falling back to file parsing" } # If help didn't work, parse the file manually if ($description -eq "No description available") { $content = Get-Content -Path $fullFilePath -Raw # Special handling for Export-AzAccessToken.ps1 if ($fileName -eq "Export-AzAccessToken") { $description = "The Export-AzAccessToken function retrieves access tokens for specified Azure resource types and exports them to a JSON file or publishes them to a secure sharing service." } # Look for .DESCRIPTION in a comment block elseif ($content -match '<#(?:.|\n)*?\.DESCRIPTION\s*\r?\n\s*(.*?)(?:\r?\n\s*\.|\r?\n\s*\r?\n|\r?\n\s*#>|$)') { $description = $matches[1].Trim() } # Try alternative pattern for help blocks elseif ($content -match '\.DESCRIPTION\s*(.*?)(?:\r?\n\s*\.|\r?\n\s*\r?\n|$)') { $description = $matches[1].Trim() } # If no .DESCRIPTION found, try to find first comment that might serve as description elseif ($content -match '#\s*(.*?)(\r?\n|$)') { $description = $matches[1].Trim() } } # Clean up multi-line descriptions - replace newlines with spaces $description = $description -replace '\s*\r?\n\s*', ' ' # Truncate long descriptions if ($description.Length -gt 80) { $description = $description.Substring(0, 79) + "..." } } $results += [PSCustomObject]@{ Function = $fileName Description = $description } } Write-Verbose "Found $fileCount public functions" $results | Format-Table -AutoSize Write-Host "========== Summary ==========`n" -ForegroundColor Cyan Write-Host "Found $fileCount public functions`n" -ForegroundColor White } catch { Write-Error "Error processing BlackCat.psd1: $_" } } |