Switch-Prompt.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315

<#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.