libs/phwriter/phwriter.psm1
using module .\cmdlets\New-Paragraph.psm1 using module .\cmdlets\Format-StringWithCharSpacesAndHyphens.psm1 using module .\cmdlets\New-ColorConsole.psm1 # From psparagraph module # Add-Type -TypeDefinition @" # using System; # using System.Text; # public class Indenter # { # public static string NewIndent(int position, int indent, string str) # { # var StringBuilder = new StringBuilder(); # var words = str.Split(' '); # int currentLineLength = 0; # StringBuilder.Append(' ', indent); # foreach (var word in words) # { # if (currentLineLength + word.Length > position) # { # StringBuilder.AppendLine(); # StringBuilder.Append(' ', indent); # currentLineLength = 0; # } # StringBuilder.Append(word); # StringBuilder.Append(' '); # currentLineLength += word.Length + 1; # } # return StringBuilder.ToString(); # } # } # "@ # function New-Paragraph() { # [CmdletBinding()] # [OutputType([string])] # param( # [ # Parameter( # Mandatory = $true # ) # ][int]$position, # [ # Parameter( # Mandatory = $true # ) # ][int]$indent, # [ # Parameter( # Mandatory = $true # ) # ] # [string]$string # ) # return [Indenter]::NewIndent($position, $indent, $string) # } $script:__phwriter = @{ rootpath = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition } # *============================================= # Function: Write-PHAsciiLogo # Description: Displays an ASCII art logo for the PHWriter module. # Parameters: None # Returns: None # *--------------------------------------------- function Write-PHAsciiLogo { param( [parameter(mandatory = $true, HelpMessage = "Sets the Name of the module for the logo display.")] [string]$Name, # Default module name if not provided [parameter(mandatory = $false, HelpMessage = "Sets a custom logo for the module display.")] [string]$CustomLogo = $null # Optional custom logo, if provided ) $logoLines = @() # if no name provided and custom logo is not set, use default logo if(!$CustomLogo) { $Name_Spaced = Format-StringWithCharSpacesAndHyphens -InputString "-$Name-" # Format the name with spaces and hyphens # Elements $top_border = "`▫▫▫▫▫▫▫▫════════════════════════════════════════════════════════▫▫▫▫▫▫═╗" $bottom_border = "`▫▫▫▫▫▫▫▫════════════════════════════════════════════════════════▫▫▫▫▫▫═╝" [int]$padding_left = ($top_border.Length) - ($top_border.Length / 2 ) - ($Name_Spaced.Length / 2) - 1 # Calculate padding for left side [int]$padding_right = $null if ($Name.Length % 2 -eq 0) { # write-host "Value is even" $padding_right = $padding_left - 1 # If even, add one more space to the right } if ($Name.Length % 2 -eq 1) { # write-host "Value is odd" $padding_right = $padding_left + 1 # If odd, keep it the same as left } # Populate the logo lines $logoLines = @( $top_border, "░$("░" * $padding_left)$Name_Spaced$("░" * ($padding_right))╢", $bottom_border ) } else { # If a custom logo is provided, split it into lines $logoLines = $CustomLogo -split "`n" # Split the custom logo into # lines based on new line characters # Ensure each line is trimmed to remove any leading/trailing whitespace $logoLines = $logoLines | ForEach-Object { $_.Trim() } # Add borders to the custom logo lines } foreach ($line in $logoLines) { [console]::writeline("$($line)") } [console]::write("`n") # Add a new line for spacing after the logo } # *============================================= # Function: New-PHWriter # Description: Generates formatted help text for PowerShell cmdlets with custom layouts and coloring. # Parameters: # - ParamTable: An array of hashtables defining cmdlet parameters. # - Padding: Number of spaces for padding between columns. # - Indent: Number of spaces for left indentation of each line. # Returns: None # *--------------------------------------------- function New-PHWriter { [CmdletBinding()] # Enables common cmdlet parameters like -Verbose, -Debug, etc. param( [Parameter(Mandatory = $false, HelpMessage = "JsonImporter object to import json data from file.")] [string]$JsonFile, # Default module name for the logo [Parameter(HelpMessage = "Sets the Name of the default logo to display. default: 'P H W R I T E R'.")] [string]$Name, # Default to the current command name props: 'ModuleName', 'Cmdlet', 'Description' [Parameter(Mandatory = $false, HelpMessage = "Name & Description of the cmdlet to display version information.")] [pscustomobject]$CommandInfo, # ParamTable is a mandatory parameter that accepts an array of hashtables. # Each hashtable defines a parameter for which help text will be generated. [Parameter(Mandatory = $false, HelpMessage = "An array of hashtables defining help parameters.")] [array]$ParamTable, [Parameter(Mandatory = $false, HelpMessage = "Example cmdlet cmdlet calls.")] [string[]]$Examples, # Optional examples for the cmdlet, default is an empty array [Parameter(Mandatory = $false, HelpMessage = "Version of the cmdlet to display.")] [string]$Version, # Default version of the cmdlet # Padding specifies the number of spaces between the parameter alias/name, type, and description. # This helps in aligning columns for a clean look. [Parameter(HelpMessage = "Number of spaces for padding between columns.")] [int]$Padding = 3, # Default padding of 4 spaces # Indent specifies the left padding for each line of the help output. # This indents the entire help block from the left edge of the console. [Parameter(HelpMessage = "Number of spaces for left indentation of each line.")] [int]$Indent = 1, # Default indent of 4 spaces [Parameter(HelpMessage = "Sets a custom logo for the module display. If not provided, a default logo will be used.")] [string]$CustomLogo = $null, # Optional custom logo, if provided [parameter(HelpMessage = "Display Help for the cmdlet.")] [switch]$Help ) Process { if(!$version){ $Version = '1.0.0' # Default version if not provided } # Create an indentation string based on the Indent parameter. $indentString = " " * $Indent if(!$Description){$Description = "-"} $ParamTable = @( @{ name = "Name" param = "n|Name" type = "String" description = "Sets the Name of the default logo to display. Default: 'P H W R I T E R'." inline = $false }, @{ name = "c|CommandInfo" param = "CommandInfo" type = "hashtable" description = "cmdlet, synopsis, and Description of the cmdlet to display version information." inline = $false }, @{ name = "ParamTable" param = "p|ParamTable" type = "Hashtable[]" description = "An array of hashtables defining help parameters." inline = $false }, @{ name = "Examples" param = "e|Examples" type = "string[]" description = "Example cmdlet cmdlet calls." inline = $false }, @{ name = "Version" param = "v|Version" type = "String" description = "Version of the cmdlet to display." inline = $false }, @{ name = "Padding" param = "pad|Padding" type = "Int" description = "Number of spaces for padding between columns." inline = $false }, @{ name = "Indent" param = "i|Indent" type = "Int" description = "Number of spaces for left indentation of each line." inline = $false }, @{ name = "CustomLogo" param = "CustomLogo" type = "String" description = "Sets a custom logo for the module display. If not provided, a default logo will be used." inline = $false }, @{ name = "Help" param = "h|Help" type = "Switch" description = "Display Help for the cmdlet." inline = $false } ) $phwriter_commandinfo = @{ cmdlet = "New-PHWriter"; synopsis = "New-PHWriter [-HelpTable <Hashtable[]>] [-Padding <Int>] [-Indent <Int>]"; description = "This cmdlet generates formatted help text for PowerShell cmdlets with custom layouts and coloring, mimicking the output of the 'help' command. It supports custom layouts, coloring, and inline/newline descriptions." source = "https://gitlab.com/phellams/phwriter/blob/main/README.md" } $phwriter_examples = @( 'New-PHWriter -Help', 'New-PHWriter -Name "PHWriter" -ComandInfo [Hashtable] -ParamTable [HashTable[]] -Version [String] -Padding [int] -Indent [int]', 'New-PHWriter -Name "PHWriter" -ComandInfo [Hashtable] -ParamTable [HashTable[]] -version [String] -Padding [int] -Indent [int]' ) if($Help){ # If the Help switch is set, display the help information and exit. New-PHWriter -Name 'PHWRITER' -CommandInfo $phwriter_commandinfo -ParamTable $phwriter_ParamTable -Padding 4 -Indent 2 ` -CustomLogo $CustomLogo -Version '0.3.5' -Examples $phwriter_examples [console]::write("`n") # Add a new line for spacing after the return } #TODO: examples paths with double // replace with / # Load JSON data if a JsonFile is provided [pscustomobject]$jsonData = $null if ($JsonFile) { $jsonFile_FullPath = Get-ChildItem -Path $JsonFile | Select-Object -First 1 if ($null -ne $jsonFile_FullPath) { try { # Get Property $jsonFile_FullPath = Get-ChildItem -Path $JsonFile | Select-Object -First 1 $jsonData = ConvertFrom-Json $(get-content -Path $jsonFile_FullPath.FullName -raw) -AsHashtable # Override parameters with JSON data if they exist if ($jsonData.name) { $Name = $jsonData.name } else { throw "Name is required." } if ($jsonData.commandinfo) { $CommandInfo = $jsonData.commandinfo } else { throw "CommandInfo is required." } if ($jsonData.paramtable) { $ParamTable = $jsonData.paramtable } if ($jsonData.examples) { $Examples = $jsonData.examples } if ($jsonData.version ) { $Version = $jsonData.version } if ($jsonData.padding) { $Padding = $jsonData.padding } if ($jsonData.indent) { $Indent = $jsonData.indent } if ($jsonData.customlogo) { $CustomLogo = $jsonData.customlogo } } catch { Write-Warning "Failed to parse JSON file: $_" exit } } else { Write-Warning "JSON file not found: $JsonFile" exit } } # Fallback to default name if not provided if (!$name -or !$jsonfile) { $name = 'PHW' } # Display the ASCII logo at the top of the help output. if(!$CustomLogo -or !$JsonFile) { Write-PHAsciiLogo -Name $name} else{ Write-PHAsciiLogo -CustomLogo $CustomLogo -Name $name } $section_char = "$(csole -String "◉" -color darkgreen -format bold, italic)" $header_char = "$(csole -String "▶" -color darkgreen -format bold, italic)" #NOTE: change write-host to New-ColorConsole 4bit color with formatting # Display the module version information. [console]::write("$indentString $(csole -s "MODULE " -color gray) $(csole -s $Name -color cyan -bgcolor gray)") [console]::write("$indentString$header_char $(csole -s "CMDLET" -color gray) $(csole -s $($CommandInfo.cmdlet) -color cyan -bgcolor gray)") [console]::write("$indentString$header_char $(csole -s "VERSION" -color gray) $(csole -s "v$Version" -color DarkMagenta -bgcolor gray)") [console]::write("`n`n") # Add a new line for spacing # Display the SYNOPSIS section, outlining the basic usage of the cmdlet. [console]::write("$indentString$section_char$(csole -s "SYNTAX" -color Yellow -format bold,underline)`n`n") #[console]::write("$indentString $(csole -string "$($CommandInfo.synopsis)" -color white)") New-Paragraph -position 100 -indent $indentString+2 -string "$(csole -s "$($CommandInfo.synopsis)" -color white)" [console]::write("`n`n") # Add a new line for spacing # Display a general DESCRIPTION of what this cmdlet does. [console]::write("$indentString$section_char$(csole -s "DESCRIPTION" -color Yellow -format bold,underline)`n`n") #[console]::write("$(csole -s "$indentString $($CommandInfo.description)" -color white)") New-Paragraph -position 100 -indent $indentString+2 -string "$(csole -s "$($CommandInfo.description)" -color white)" [console]::write("`n`n") # Add a new line for spacing # Display the PARAMETERS section header. if (!$ParamTable -or $ParamTable.Count -eq 0) { Write-Warning "No parameters provided in ParamTable. Skipping parameter display." return }else{ [console]::write("$indentString$section_char$(csole -s PARAMETERS -color Yellow -format bold,underline)") [console]::write("`n`n") } # --- Calculate maximum lengths for alignment --- $maxParamLength = 0 $maxTypeLength = 0 foreach ($paramInfo in $ParamTable) { # Validate that all required properties are present. if (-not ($paramInfo.name -and $paramInfo.param -and $paramInfo.type -and $paramInfo.description)) { Write-Warning "Skipping an entry in ParamTable due to missing required properties (Name, Param, Type, Description, Inline)." continue } # Calculate length for the parameter alias/name part (e.g., "-p|Path"). # Add 1 for the leading hyphen and 1 for the space after. $currentParamLength = ("-{0}" -f $paramInfo.param).Length + 1 # +1 for the space after alias # Calculate length for the type part (e.g., "[string]"). $currentTypeLength = ("[{0}]" -f $paramInfo.type).Length if ($currentParamLength -gt $maxParamLength) { $maxParamLength = $currentParamLength } if ($currentTypeLength -gt $maxTypeLength) { $maxTypeLength = $currentTypeLength } } # --- Iterate and display with calculated padding --- foreach ($paramInfo in $ParamTable) { # Re-validate in case some entries were skipped during length calculation. if (-not ($paramInfo.name -and $paramInfo.param -and $paramInfo.type -and $paramInfo.description)) { continue # Skip if invalid } # Extract properties from the current hashtable for easier access. $paramName = $paramInfo.name $paramAlias = $paramInfo.param $paramType = $paramInfo.type $paramDescription = $paramInfo.description $required = $paramInfo.required -or $false # Default to false if not specified if ($required) { $required_text = "$(csole -string "(Req) " -color red)"; } # Append "(Req)" if required else { $required_text = ""; } # No text if not required $paramInline = [bool]$paramInfo.inline # Ensure Inline is treated as a boolean # Format the parameter alias/name part, applying padding. $formattedParamAlias = ("-{0}" -f $paramAlias).PadRight($maxParamLength + $Padding) # Format the type part, applying padding. $formattedParamType = ("[{0}]" -f $paramType).PadRight($maxTypeLength + $Padding) # Output the indented parameter line. [console]::write("$indentString $(csole -s "$formattedParamAlias" -color DarkMagenta)") [console]::write("$(csole -s $formattedParamType -color DarkCyan) $required_text") [console]::write("$(csole -s " $paramName" -color White)") # Handle the description display based on the 'Inline' property. if ($paramInline) { # If Inline is true, append the description on the same line. [console]::write("$(csole -s " $paramDescription" -color Gray)") } else { # If Inline is false, start the description on a new line with indentation. [console]::write("`n") # Ensure a new line after the parameter name # Calculate the indentation for the description based on the overall indent and column widths. $descriptionIndent = $indentString + (" " * ($maxParamLength + $maxTypeLength + (2 * $Padding) + 1)) # +1 for the space after param name [console]::write("$descriptionIndent $(csole -s " $paramDescription" -color Gray)") } [console]::write("`n") # Add a new line for spacing between different parameters } #TODO: Implement examples for cmdlet parameters [console]::write("$indentString$section_char$(csole -s "EXAMPLES" -color White -format bold,underline)`n") foreach ($example in $Examples) { [console]::write("`n$indentString$(" "* 3)$(csole -s "$($example.replace("//","/"))" -color Gray)") # Add a new line after each example for better readability [console]::write("`n") # Add a new line for spacing } # Output at the end github docs LINK [console]::write("`n") [console]::write("$indentString ★ Docs: $(csole -s "$($CommandInfo.source)" -format bold,underline -c darkcyan) for more info") [console]::write("`n`n") # Add a new line for spacing } } $cmdlet_config = @{ function = @( 'New-PHWriter', 'Write-PHAsciiLogo' ) alias = @() } Export-ModuleMember @cmdlet_config |