Switch-Prompt.ps1


<#PSScriptInfo
 
.VERSION 1.2.0
 
.GUID 9582674c-0024-41d0-a3a3-393d8bf440f6
 
.AUTHOR tommymaynard
 
.COMPANYNAME
 
.COPYRIGHT
 
.TAGS Prompt
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
.PRIVATEDATA
 
#>


<#
 
.DESCRIPTION
 The Switch-Prompt advanced function can switch between a minimal, standard, custom, Linux, and a custom Linux PowerShell prompt.
 
#>
 

Param()


Function Switch-Prompt {
<#
.SYNOPSIS
    The Switch-Prompt advanced function can switch between a minimal, standard, custom, Linux, and a custom Linux PowerShell prompt.
.DESCRIPTION
    The Switch-Prompt advanced function offers several dynamic parameters. These vary based on the parameter value provided to the Type parameter. The below examples include all the possibilities.
.PARAMETER Type
    The Type parameter can accept five string parameter values. These include Minimal, Standard, Custom, Linux, and LinuxCustom. These indicate which included type of prompt will be displayed.
.PARAMETER Prompt
    The Prompt parameter is a dynamic parameter that is available when Custom is used as the value for the Type parameter. This parameter accepts a ScriptBlock parameter value.
.PARAMETER FullPath
    The FullPath parameter is a dynamic parameter that is available when either Linux or the LinuxCustom prompt are used as the value for the Type parameter. This parameter ensures the path to the current directory includes the drive letter and full path.
.PARAMETER Version
    The Version parameter is a dynamic parameter that is available when either Linux or the LinuxCustom prompt are used as the value for the Type parameter. This parameter ensures the version of PowerShell is indicated between the closing square bracket of either Linux prompt and the dollar sign ($) or hash symbol (#).
.PARAMETER UserName
    The UserName parameter is a dynamic parameter that is only available when LinuxCustom is used as the value for the Type parameter. This parameter allows a user to choose what username to display within the prompt.
.PARAMETER ComputerName
    The ComputerName parameter is a dynamic parameter that is only available when LinuxCustom is used as the value for the Type parameter. This parameter allows a user to choose what computer name to display within the prompt.
.EXAMPLE
    PS C:\Program Files\7-Zip\Lang> Switch-Prompt -Type Minimal
    PS> _
    This example switches to a minimal PowerShell prompt.
.EXAMPLE
    PS> Switch-Prompt -Type Standard
    PS C:\Program Files\7-Zip\Lang> _
    This example switches to the standard PowerShell prompt. The prompt will also be displayed if Switch-Prompt is invoked without any parameters.
.EXAMPLE
    PS C:\Program Files\7-Zip\Lang> Switch-Prompt -Type Custom
    Default (use Prompt parameter)> _
    This example switches to the custom PowerShell prompt. As the dynamic Prompt parameter wasn't included, it used the default custom prompt.
.EXAMPLE
    Default (use Prompt parameter)> Switch-Prompt -Type Custom -Prompt {'PWRSHLL > '}
    PWRSHLL > _
    This example switches to a custom defined PowerShell prompt using the Prompt parameter. It is a simple string value.
.EXAMPLE
    PWRSHLL > Switch-Prompt -Type Custom -Prompt {"$(Get-Date) > "}
    04/26/2019 21:55:56 > _
    This example switches to a custom defined PowerShell prompt using the Prompt parameter. Each time the prompt is displayed, it will include the current date and time.
.EXAMPLE
    04/26/2019 21:55:56 > Switch-Prompt -Type Custom -Prompt {(Get-Date).ToString() + " > "}
    04/26/2019 21:56:10 > _
    This example switches to a custom defined PowerShell prompt using the Prompt parameter. This example creates the same prompt as the above example; however, it does so without using a single string and the subexpression operator.
.EXAMPLE
    04/26/2019 21:56:10 > Switch-Prompt -Type Custom -Prompt {"$env:USERDOMAIN\$env:COMPUTERNAME --> "}
    MYDOMAIN\TMLAPTOP --> _
    This example switches to a custom defined PowerShell prompt using the Prompt parameter. It includes using two environmental variables within the prompt.
.EXAMPLE
    MYDOMAIN\TMLAPTOP --> Switch-Prompt -Type Custom -Prompt {"|$(Get-Date)|$env:USERDOMAIN\$env:COMPUTERNAME > "}
    |04/26/2019 21:56:22|MYDOMAIN\TMLAPTOP > _
    This example switches to a custom defined PowerShell prompt using the Prompt parameter. This example includes both the current date and time, and two environmental variables: the user's domain and the computer's name.
.EXAMPLE
    |04/26/2019 21:56:22|MYDOMAIN\TMLAPTOP > Switch-Prompt -Type Custom -Prompt {If ($env:COMPUTERNAME -match 'laptop') {"$($env:COMPUTERNAME)|LPT: "} ElseIf ($env:COMPUTERNAME -match 'desktop') {"$($env:COMPUTERNAME)|DKT: "} Else {'[--PS--]> '}}
    TMLAPTOP|LPT: _
    This example switches to a custom defined PowerShell prompt using the Prompt parameter. By using an If-ElseIf-Else statement, one of three different prompts will be displayed.
.EXAMPLE
    TMLAPTOP|LPT: Switch-Prompt -Type Custom -Prompt {If ($env:COMPUTERNAME -match 'PT0') {"$($env:COMPUTERNAME)|T0: "} ElseIf ($env:COMPUTERNAME -match 'PT1') {"$($env:COMPUTERNAME)|T1: "} Else {'[--PS--]> '}}
    [--PS--]> _
    This example switches to a custom defined PowerShell prompt using the Prompt parameter. This is an additional example of using an If language construct to determine the prompt that will be displayed.
.EXAMPLE
    [--PS--]> Switch-Prompt -Type Linux
    [tommymaynard@tmlaptop Lang]$ _
    This example switches to the Linux PowerShell prompt.
.EXAMPLE
    [tommymaynard@tmlaptop Lang]$ Switch-Prompt -Type Linux -FullPath -Version
    [tommymaynard@tmlaptop c/Program Files/7-Zip/Lang]5.1.1$ _
    This example switches to the Linux PowerShell prompt and includes the full path and version. The FullPath and Version parameters can be used together, or independently.
.EXAMPLE
    [tommymaynard@tmlaptop c/Program Files/7-Zip/Lang]5.1.1$ Switch-Prompt -Type LinuxCustom -FullPath
    [fake_user@fake_computer c/Program Files/7-Zip/Lang]$ _
    This example switches to the custom Linux PowerShell prompt and included the fullpath. As the UserName and ComputerName parameters were not included, it defaults to fake_user as the UserName and fake_computer as the ComputerName.
.EXAMPLE
    [fake_user@fake_computer c/Program Files/7-Zip/Lang]$ Switch-Prompt -Type LinuxCustom -UserName tm -ComputerName srvx -Version
    [tm@srvx Lang]5.1.1$ _
    This example switches to the custom Linux PowerShell prompt and includes the version. Additionally, it includes a custom username and computer name.
.NOTES
    Name: Switch-Prompt
    Author: Tommy Maynard
    Comments: This function creates varying dynamic parameters when Custom, Linux, or LinuxCustom is used as the value for the Type parameter. These may include Prompt, FullPath, Version, UserName, and ComputerName. Please see the examples.
    Last Edit: 03/29/2019 [1.0.0], 04/10/2019 [1.1.0], 04/27/2019 [1.2.0]
    Version: 1.1.0
        - Added Minimal prompt type.
    Version: 1.2.0
        - Added loop to remove previously existing PS default parameter values: $PSDefaultParameterValues.
        - Segregated some code from not running unless -like 'Linux*'.
        - Added Custom prompt type that creates a dynamic prompt parameter (as ScriptBlock).
        - Commented out modifications to the WindowTitle, as it was only modified by the Linux* prompts (and therefore never cleared/change with other prompts).
#>

    Param(
        [Parameter()]
        [ValidateSet('Minimal','Standard','Custom','Linux','LinuxCustom')]
        [string]$Type = 'Standard'
    )

    DynamicParam {
        $SingleAttribute = New-Object System.Management.Automation.ParameterAttribute
        $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
        $AttributeCollection.Add($SingleAttribute)
        $ParamDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
        Switch ($PSBoundParameters) {
            {$_['Type'] -eq 'Custom'} {
                $PromptParameter = New-Object System.Management.Automation.RuntimeDefinedParameter('Prompt',[scriptblock],$AttributeCollection)
                $PromptParameter.Value = {'Default (use Prompt parameter)> '}
                $ParamDictionary.Add('Prompt',$PromptParameter)
            } # End Action.
            {$_['Type'] -eq 'LinuxCustom'} {
                $UserParameter = New-Object System.Management.Automation.RuntimeDefinedParameter('UserName',[string],$AttributeCollection)
                $UserParameter.Value = 'fake_user'
                $ParamDictionary.Add('UserName',$UserParameter)
                $ComputerParameter = New-Object System.Management.Automation.RuntimeDefinedParameter('ComputerName',[string],$AttributeCollection)
                $ComputerParameter.Value = 'fake_computer'
                $ParamDictionary.Add('ComputerName',$ComputerParameter)
            } # End Action.
            {$_['Type'] -eq 'Linux' -or $_['Type'] -eq 'LinuxCustom'} {
                $FullPathParameter = New-Object System.Management.Automation.RuntimeDefinedParameter('FullPath',[switch],$AttributeCollection)
                $ParamDictionary.Add('FullPath',$FullPathParameter)
                $VersionParameter = New-Object System.Management.Automation.RuntimeDefinedParameter('Version',[switch],$AttributeCollection)
                $ParamDictionary.Add('Version',$VersionParameter)
            } # End Action.
        } # End Switch.
        return $ParamDictionary
    } # End DynamicParam.

    Begin {
        #region Remove default parameters.
        'type','prompt','username','computername','fullpath','version' | ForEach-Object {
            $PSDefaultParameterValues.Remove("prompt:$_")
        } # End ForEach-Object.
        #endregion.
    } # End Begin.

    Process {
        #region Add relavant default parameters.
        $PSDefaultParameterValues.Add('prompt:type',$Type)

        If ($PSBoundParameters['Type'] -eq 'Custom') {
            $PSDefaultParameterValues.Add('prompt:prompt',$ParamDictionary.Prompt.Value)
        } # End If.

        If ($PSBoundParameters['Type'] -eq 'LinuxCustom') {
            $PSDefaultParameterValues.Add('prompt:username',$ParamDictionary.UserName.Value)
            $PSDefaultParameterValues.Add('prompt:computername',$ParamDictionary.ComputerName.Value)
        } # End If.
        
        If ($PSBoundParameters['FullPath'] -eq $true) {
            $PSDefaultParameterValues.Add('prompt:fullpath',$true)
        } Else {
            $PSDefaultParameterValues.Add('prompt:fullpath',$false)
        } # End If-Else.

        If ($PSBoundParameters['Version'] -eq $true) {
            $PSDefaultParameterValues.Add('prompt:version',$true)
        } Else {
            $PSDefaultParameterValues.Add('prompt:version',$false)
        } # End If-Else.
        #endregion.
    } # End Process.

    End {
        #region Create prompt.
        Function Global:Prompt {
            Param (
            )

            Begin {
            } # End Begin.

            Process {
                #region Determine host for WindowTitle.
                Switch ($Host.Name) {
                    'ConsoleHost' {$HostName = 'consolehost'; break}
                    'Windows PowerShell ISE Host' {$HostName = 'ise'; break}
                    'Visual Studio Code Host' {$HostName = 'vscode'; break}
                    default {$HostName = $Host.Name.ToLower()}
                } # End Switch.
                #endregion.

                If ($PSDefaultParameterValues['prompt:type'] -like 'Linux*') {
                    #region Determine Admin/Root and set symbol.
                    If ($PSVersionTable.Platform -eq 'Unix') {
                        If ((id -u) -eq 0) {
                            $Symbol = '#'
                        } Else {
                            $Symbol = '$'
                        } # End If-Else.
                    } ElseIf ($PSVersionTable.PSVersion.Major -le 5 -or $PSVersionTable.Platform -eq 'Win32NT') {
                        If ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups -match 'S-1-5-32-544')) {
                            $Symbol = '#'
                        } Else {
                            $Symbol = '$'
                        } # End If-Else.
                    } # End If-ElseIf-Else.
                    #endregion.

                    #region Write Path to Location as /.../...
                    If ($PWD.Path -eq $env:USERPROFILE) {
                        $Location = '/~'
                    } ElseIf ($PWD.Path -like "*$env:USERPROFILE*") {
                        $Location = "/$($PWD.Path -replace ($env:USERPROFILE -replace '\\','\\'),'~' -replace '\\','/')"
                    } Else {
                        $Location = "$(($PWD.Path -replace '\\','/' -split ':')[-1])"
                    } # End If-ElseIf.
                    #endregion.

                    #region Determine file system location.
                    $Location = "$((Get-Location).Drive.Name.ToLower())$Location"
                    #endregion.

                    #region Shorten path.
                    If (-Not($PSDefaultParameterValues['prompt:fullpath'])) {
                        $Location = ($Location -split '/')[-1]
                        # Fix path if too short.
                        If ($Location.Length -eq 0) {
                            $Location = '/'
                        } # End If.
                    } # End If.
                    #endregion.

                    #region Determine PowerShell version.
                    If ($PSDefaultParameterValues['prompt:version']) {
                        If ($PSVersionTable.PSVersion.Major -le 5) {
                            $PSVer = "$($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor).$($PSVersionTable.PSVersion.Build)"
                        } ElseIf ($PSVersionTable.PSVersion.Major -ge 6) {
                            $PSVer = "$($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor).$($PSVersionTable.PSVersion.Patch)"
                        } # End If-ElseIf.
                        $PSVer = $PSVer.Substring(0,5)
                    } Else {
                        $PSVer = $null
                    } # End If-Else.
                    #endregion.

                    #region Determine if in the debugger.
                    If (Test-Path -Path Variable:/PSDebugContext) {
                        $DebugStart = '[DBG]: '
                        $DebugEnd = ']'
                    } # End If.
                    #endregion.
                } # End If.

                #region Determine Real vs. Fake prompt.
                If ($PSDefaultParameterValues['prompt:type'] -eq 'Minimal') {
                    'PS> '

                } ElseIf ($PSDefaultParameterValues['prompt:type'] -eq 'Standard') {    
                    "PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) "

                } ElseIf ($PSDefaultParameterValues['prompt:type'] -eq 'Custom') {
                    & $PSDefaultParameterValues['prompt:prompt']

                } ElseIf ($PSDefaultParameterValues['prompt:type'] -eq 'Linux') {
                    # Actual prompt and title.
                    $UserComputer = "$($env:USERNAME.ToLower())@$($env:COMPUTERNAME.ToLower())" 
                    # $Host.UI.RawUI.WindowTitle = "$HostName $PSver`: $DebugStart[$UserComputer $Location]$DebugEnd$Symbol"
                    "$DebugStart[$UserComputer $Location]$DebugEnd$PSVer$Symbol "

                } ElseIf ($PSDefaultParameterValues['prompt:type'] -eq 'LinuxCustom') {
                    # Alternate prompt and title.
                    $UserName = $PSDefaultParameterValues['prompt:username']
                    $ComputerName = $PSDefaultParameterValues['prompt:computername']
                    $UserComputer = "$UserName@$ComputerName"
                    # $Host.UI.RawUI.WindowTitle = "$HostName $PSver`: [$UserComputer $Location]$Symbol"
                    "$DebugStart[$UserComputer $Location]$DebugEnd$PSVer$Symbol "
                } # End If-ElseIf-ElseIf.
                #endregion.
            } # End Process.

            End {
            } # End End.
        } # End Function: prompt.
        #endregion.
    } # End End.
} # End Function: Switch-Prompt.