Tag Archives: prompt

Switch-Prompt 1.2.0


Notice: The following post was originally published on another website. As the post is no longer accessible, it is being republished here on tommymaynard.com. The post was originally published on April 29, 2019.


Back toward the end of March 2019, I published a script to the PowerShell Gallery called Switch-Prompt. It’s a function, packaged as a .ps1 file, that allows a user to switch their prompt between the standard-issued, Microsoft Prompt, a Linux look-alike prompt, and a customizable Linux look-alike prompt. I wrote about it right here, on tommymaynard.com.

I indicated in that article that that version was the one. Yeah, so that didn’t last long. Well, as of today and version 1.1.0, it now includes a minimal prompt, as well. You know, this guy: PS>. I’ve taken 1.0.0 to 1.1.0 — wait, timeout — I just had another idea. Here we go again, we’re moving this up to version 1.2.0. This is going to be the one, and I may just really mean it this time.

You couldn’t tell, but the time between the first two paragraphs and this one was a few days. It’s worth it, as the Switch-Prompt function is now at version 1.2.0 and it’s awesome. And to think, I thought I was done back at 1.0.0; I should’ve known. But seriously, this is the last prompt you’re ever going to need and I suspect, that this is the last time I’ll need to make changes — it does everything! It’s come a really long way. It can create a minimal prompt, a standard prompt, a Linux prompt, a customizable Linux prompt, and now, a completely custom prompt. Anything you want! All you have to do is place your code in a ScriptBlock. We’ll see some examples.

Before we see how it can be used, let’s get it installed. It’s available in the PowerShell Gallery, so the below command will get the newest version installed for the current user. Use the Force switch parameter if you’ve installed a previous version, and also use the Verbose switch parameter, so you know what’s taking place during its installation. It’s not a requirement, but it can be a learning experience for a process that produces no output by default.

PS C:\Program Files\7-Zip> Install-Script -Name Switch-Prompt -Scope CurrentUser

Because the script is delivered as a function in a script file (a .ps1), you’re required to dot-source the script in order to add the function to the current session (notice the dot before the script’s path). This will need to be done every time a new session begins and you want to use the function. To avoid that, it’s best to add the below command to a profile script that executes at the start of every new PowerShell session. If you choose to obtain the Switch-Prompt another way, then here’s the main page for it on the PowerShell Gallery: https://www.powershellgallery.com/packages/Switch-Prompt/1.2.0.

PS> . C:\Users\tommymaynard\Documents\WindowsPowerShell\Scripts\Switch-Prompt.ps1

If you’re dot sourcing the script file from your profile script, such as we’ve done above, then be sure to include your Switch-Prompt command there, as well. You’ll see plenty of examples below and even more in the function’s comment-based help. On that note, instead of explaining all the Switch-Prompt options, I’m opting to copy in some of the comment-based help’s examples. In this first example, we’ll see how to switch to a minimal prompt. This was the 1.1.0 update — big whoop now, as you’ll soon see.

PS C:\Program Files\7-Zip\Lang> Switch-Prompt -Type Minimal
PS> 
PS> 

Next, we’ll move from the minimal prompt back to the default, standard prompt. This is the default action when the Type parameter and a value are not included. Therefore, using -Type Standard isn’t actually necessary to recreate the Standard prompt.

PS> Switch-Prompt -Type Standard
PS C:\Program Files\7-Zip\Lang>
PS C:\Program Files\7-Zip\Lang>

From here, we’ll try out the new Custom type prompt. If the Prompt parameter and value aren’t included, Switch-Prompt uses its built-in default, which actually indicates to use the Prompt parameter. Doing so — using that Prompt parameter — is what sets this type, and its possibilities, apart. We’ll see that after this first example.

PS C:\Program Files\7-Zip\Lang> Switch-Prompt -Type Custom
Default (use Prompt parameter)>
Default (use Prompt parameter)> 

In this example, we create a simple static — and you’ll see what I mean in a moment — prompt. It’s a simple text-based prompt.

Default (use Prompt parameter)> Switch-Prompt -Type Custom -Prompt {'PWRSHLL > '}
PWRSHLL >
PWRSHLL >

Next, we’ll start adding some dynamic elements to our prompt. This example includes the current date and time, each time the prompt is written. It’s about now that you should recognize that the Switch-Prompt’s dynamic parameter, Prompt, requires a ScriptBlock parameter value. Ensure you’re using the opening and closing curly braces, whether or not you use a static or dynamic prompt.

PWRSHLL > Switch-Prompt -Type Custom -Prompt {"$(Get-Date) > "}
04/26/2019 21:55:56 >
04/26/2019 21:55:57 >

In this example, we’ll use some environmental variables to help create our prompt.

04/26/2019 21:56:10 > Switch-Prompt -Type Custom -Prompt {"$env:USERDOMAIN\$env:COMPUTERNAME --> "}
MYDOMAIN\TMLAPTOP -->
MYDOMAIN\TMLAPTOP --> 

This will be the final example for this article. This also uses the Custom Type, but now we’ll include an If-ElseIf-Else construct as the value for our Prompt parameter. When using a ScriptBlock parameter value, there’s really nothing we can’t dream up for our prompt. Just remember that you may need to use the ToString() method if your commands are not inside a quoted string (which forces a string). Be sure to see one of the other Get-Date examples, from the function’s comment-based help, where this is shown.

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: 

We haven’t covered it here with examples, so be sure to check out the Linux and LinuxCustom Types, as well. Switch-Prompt includes 14 comment-based help examples. Additionally, there were some examples in this first article: https://tommymaynard.com/linux-prompt-x/. What you’re looking for is likely in one of these two places, and if not, there’s probably enough in there to inspire you to come up with something unique. For real, I think I’m done at 1.2.0, but only time will tell.

Linux Prompt X


Notice: The following post was originally published on another website. As the post is no longer accessible, it is being republished here on tommymaynard.com. The post was originally published on March 30, 2019.


Note: Because this is republished post, I know there is an update coming on this topic. Be sure to watch for this on Wednesday, February 17, 2021. I will do my best to remember to link to it once it is available.

“This is the one.” -Me (about ten seconds before starting this article)

For a decent amount of time now, I’ve used a personalized prompt. On several occasions even, I’ve written and shared it with the PowerShell community. Well, I’m about to do the same thing today. That said, I’ve never quite felt what I’m feeling now. After all those iterations, I feel that this version — version X (ten) — is what I was always after. It makes sense on Windows and Linux, and it provides everything I could want in a prompt.

For full disclosure, I’ve actually… said that last sentence before.

Let me explain a bit about it for those that may be new. I’ve always appreciated the Unix/Linux prompt, as it includes with it, the user name, the host/computer name, and often, an indication of whether or not I’m running as root ($ vs. # [# is root/admin]). Over time, I brought this and more into my prompt on Windows. It was the Linux prompt on Windows. And now, it’s even the Linux prompt on Linux, too. You know, that whole PowerShell Core, cross-platform thing. No kidding, but I was actually kind of surprised when I installed PowerShell Core for the first time and it used the same, standard PowerShell prompt. I suppose it’s something we’ve come to expect, however.

Before we discuss how to get the code, let’s discuss what I’ve done. I’ve now included everything, inside of a single advanced function called Switch-Prompt. If you run it with just the command name, you’ll get the standard, PowerShell prompt. That’s because the default value for the Type parameter is “Standard.” It can also be run using that parameter and parameter value, as seen in the below example.

PS > Switch-Prompt -Type Standard
PS C:\Program Files\7-Zip\Lang>

When using the Type parameter value of “Standard,” the prompt will look and function just as it typically does in PowerShell. Until Switch-Prompt is invoked again, this will be the prompt each time a new prompt is created (Enter is pressed).

The fun begins when we change out the “Standard” parameter value to “Linux.” This prompt will … well, let me just show you.

PS > Switch-Prompt -Type Linux
[tommymaynard@tmlaptop Lang]$ Switch-Prompt
PS C:\Program Files\7-Zip\Lang>

This option will create the prompt as open square bracket, current user name, @ symbol, current computer name, current directory, close square bracket, and either a dollar sign ($) or hash symbol (#). Remember, the hash symbol indicates that the user is running as root, or admin and the dollar sign indicates that the user is running as a normal user.

Using “Linux” as the value for the Type parameter creates two dynamic parameters. The FullPath parameter will include the full path to the current directory, and the Version parameter will include the version of PowerShell between the closing square bracket and the dollar sign or hash symbol. These two parameters can be used one at a time, or together — it makes no difference. In the below examples, I’ve pressed Enter a couple of times between commands, so you can see that the new prompt stays around until Switch-Prompt is invoked again, in a different manner than it was previously.

PS C:\Program Files\7-Zip\Lang> Switch-Prompt -Type Linux
[tommymaynard@tmlaptop Lang]$
[tommymaynard@tmlaptop Lang]$
[tommymaynard@tmlaptop Lang]$ Switch-Prompt -Type Linux -FullPath
[tommymaynard@tmlaptop c/Program Files/7-Zip/Lang]$
[tommymaynard@tmlaptop c/Program Files/7-Zip/Lang]$
[tommymaynard@tmlaptop c/Program Files/7-Zip/Lang]$ Switch-Prompt -Type Linux -Version
[tommymaynard@tmlaptop Lang]5.1.1$
[tommymaynard@tmlaptop Lang]5.1.1$
[tommymaynard@tmlaptop Lang]5.1.1$ Switch-Prompt -Type Linux -FullPath -Version
[tommymaynard@tmlaptop c/Program Files/7-Zip/Lang]5.1.1$
[tommymaynard@tmlaptop c/Program Files/7-Zip/Lang]5.1.1$

At an earlier time in this prompt’s development, I opted to have it allow me to choose the username and computer name. That’s still with us. When we use “LinuxCustom” as the value for the Type parameter, we get even more dynamic parameters. We still have FullPath and Version, but now, we also have UserName and ComputerName. Unlike FullPath and Version, these are not switch parameters; they require a value to be included along with them. Take a look at these final examples, and then you can get the code for yourself!

[tommymaynard@tmlaptop c/Program Files/7-Zip/Lang]5.1.1$ Switch-Prompt -Type LinuxCustom
[fake_user@fake_computer Lang]$
[fake_user@fake_computer Lang]$
[fake_user@fake_computer Lang]$ Switch-Prompt -Type LinuxCustom -UserName tm
[tm@fake_computer Lang]$
[tm@fake_computer Lang]$
[tm@fake_computer Lang]$ Switch-Prompt -Type LinuxCustom -UserName tm -ComputerName srvx
[tm@srvx Lang]$
[tm@srvx Lang]$
[tm@srvx Lang]$ Switch-Prompt -Type LinuxCustom -UserName tm -ComputerName srvx -FullPath -Version
[tm@srvx c/Program Files/7-Zip/Lang]5.1.1$

Now, it’s time for you to try it out yourself. In the past, I opted to save it in a public Gist, but this time, I think it’s good enough to go straight to the PowerShell Gallery. Here’s the Switch-Prompt’s page on the gallery, and here’s the command to issue in PowerShell to install it on your computer, as the current user. Remember, it’s a script, not a module. Therefore, you need to dot-source it, to use it, which is something that could be easily added to your profile script. That command is below, as well.

PS > Install-Script -Name Switch-Prompt -Scope CurrentUser
PS > . "$HOME\Documents\WindowsPowerShell\Scripts\Switch-Prompt.ps1"

Be sure to swap out “WindowsPowerShell” for “PowerShell” in the above path, if you installed it using PowerShell Core. It works there too! Even in the recently released 6.2 version.

Dynamic PowerShell Version in Windows Terminal Tabs Part II

Maybe no one noticed. Or, maybe they did and just didn’t say anything. As you’ll see, I’ve written a quick fix to a post I wrote last week.

I shouldn’t have, but back in Part I, I put reliance on my prompt function for the Windows Terminal tab titles. This means that I have to ensure that I never change my prompt function. If I do, it’s very possible that adding the version of PowerShell to the tab titles will break. This isn’t good. That dependence, while it works just fine now, could become a problem in time.

Knowing that, let’s remove it. Let’s get the version in the Windows Terminal tab titles from something other than my prompt. Let’s put it where it belongs, on the version itself — on the $PSVersionTable automatic variable. My prompt Itself uses that, so why shouldn’t this Windows Terminal tab title code, too? This makes much more sense than coupling the tab titles with my prompt function.

$Host.UI.RawUI.WindowTitle = "$($Host.UI.RawUI.WindowTitle) $($PSVersionTable.PSVersion.ToString())"

The tabs look exactly like they did before, but now my prompt function doesn’t play into the versions making their way to the tabs at all. Altering the prompt doesn’t matter now, or now, at any time in the future.

Dynamic PowerShell Version in Windows Terminal Tabs

There’s a Part II to this post now, be sure to read it after you’ve read this post.

I find myself inside the Window Terminal’s JSON Settings file each time I update the version of PowerShell on my system. That includes non-preview and preview versions of PowerShell. Well, as of today, that’s changed. Previously I would install an updated version, jump into the JSON Settings file, and modify the Name and TabTitle properties of the corresponding profile. I’ve long wanted the version number on the Tab and so I was hard coding the values. No longer.

Let’s take a look at my prompt function. It’s mostly the default one, with some slight changes. Here’s the prompt code from my $PROFILE. Preview version or not, they both use the same $PROFILE script; therefore, they use the same prompt function.

Function Prompt {
    "$("[PS$($PSVersionTable.PSVersion.ToString())][$($executionContext.SessionState.Path.CurrentLocation)]" * ($nestedPromptLevel + 1)) ";
    # .Link
    # https://go.microsoft.com/fwlink/?LinkID=225750
    # .ExternalHelp System.Management.Automation.dll-help.xml
} # End Function: Prompt.

Here’s how the prompt renders in both the non-preview and preview versions of PowerShell.



What I do, and you’ll see it momentarily is extract the version number — “7.1.3” and “7.2.0-preview.4” from the above prompts and write them to the WindowTitle along with what was already there (the word “PowerShell”). The below code is beneath the Prompt function in my $PROFILE script.

$Prompt = prompt
$Host.UI.RawUI.WindowTitle = "$($Host.UI.RawUI.WindowTitle) $(($Prompt.Split('][').TrimStart('[PS')[0]))"

First, it captures the prompt into a variable called Prompt. Then it manipulates the contents of the variable until we only have what we want. This first thing it does consists of splitting the prompt string at the back-to-back closing and opening square brackets: “][“. In the case of the non-preview prompt, this leaves me with two strings: [PS7.1.3 and C:\]. Next, it trims off the [PS from the start of the first of the two strings. As you can tell, we only have an interest in our first string — the value in the zero index: [0]. Once’s the parsing is complete, our value is appended to the existing value in the WindowTitle property and it is all written back to the WindowTitle property.

It’s from here forward that the title includes not just the word “PowerShell,” but also the version. That’s it. A little extra work now to remove all the work from later on.

There’s a Part II to this post now, be sure to read it.

Change Prompt on Module Import

To me, my PowerShell prompt is quite important. I’ve written about it nine times already. While I’m not going to write about it again, so much, I am going to focus on an updated prompt I’ve created for a recent project. I couldn’t help but take a few things into this project from my prompt, and that’s why that’s been mentioned.

I recently received a screen capture from someone running into a problem using one of the tools I’ve written. Sure, it needs some error checking, I won’t deny that, but it was a very obscure and unforeseen problem. You know, how we often find out about error conditions.

This tool, or function, can be run on an Amazon Web Services EC2 instance within a project, to determine the status of its partner EC2 instance. When it works, it returns the status of the other instance, to include things like running, stopping, stopped, etc. There’s also a couple other companion functions that can start and stop the partner instance. The second of the two machines has very high specifications, and so we ask that our users shut down those secondary instances when they’re not running experiments. They pricey.

The problem is that when I look at this error, the prompt doesn’t tell me enough. I can only tell it’s PowerShell — the PS in the prompt — and the current path — some of which has been hidden in this first image. I want more information without having to ask the user, and so I’ve added that in.  Here’s the default prompt up close.

The new prompt includes the username (to the left of the @), the computer name (to the right of the @), the project name (while it’s not in this example, it’s normally a part of the computer name), the path, and whether the user is an admin (#) or not ($). Now, when I receive a PowerShell screen capture, I already have a few of my first questions answered.

All of the functions, such as the one that was run that generated this error, are a part of the same PowerShell module. There’s somewhere near 20 of them so far, and I keep finding reasons to add new ones. If you don’t know, creating a PowerShell script module that includes a module manifest file (a .psd1), allows one to include scripts that execute just before a module is imported. This, whether the module is imported manually using Import-Module, or by invoking a function from within the module, when the module hasn’t yet been imported.

Let’s take a look at my SetPrompt.ps1 script file that executes when my PowerShell module is imported.

Function prompt {
    # Determine Admin; set Symbol variable.
    If ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups -match 'S-1-5-32-544')) {
        $Symbol = '#'} Else {$Symbol = '$'
    }

    # Create prompt.
    "[$($env:USERNAME.ToLower())@$($env:COMPUTERNAME.ToLower()) $($executionContext.SessionState.Path.CurrentLocation)]$Symbol "
} # End Function: prompt.

With this script in place and a ScriptsToProcess entry in the module’s manifest file, pointing to this file, I can be ensured that the user’s prompt will change the moment my module is imported. From here on out, I can rest assured that if a user — of these machines at least — sends us a screen capture that it’ll include relevant pieces of information I would have had to ask for, had this prompt not been in place.

There’s a final thought here. When the user is done with this PowerShell module, they’re still going to have this prompt. In my case, it’s perfectly suitable because my users won’t be in PowerShell, unless they’re issuing commands from the module. At least, I can’t imagine they will be. The only other thoughts I’ve had about this “problem” would be to (1) teach users to remove the module, and have code in the prompt monitor whether the module is loaded or not, and revert the prompt if the module is removed, or (2) revert the prompt if a command outside of my module is invoked.

That’s it for today. I don’t have it shown here, but it’s neat to see the prompt alter itself when the module is loaded. Something to keep in mind, if you find yourself in a similar situation.

Update: I was annoyed that $HOME, or C:\Users\tommymaynard, was being displayed as the full path, so I made some additional modifications to the prompt that’s being used for this project. It’ll now look like this, when at C:\Users\tommymaynard (or another user’s home directory).

Here’s the new prompt function, to include a better layout.

Function prompt {
    # Determine Admin; set Symbol variable.
    If ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups -match 'S-1-5-32-544')) {
        $Symbol = '#'
    } Else {
        $Symbol = '$'
    }

    If ((Get-Location).Path -eq $env:USERPROFILE) {
        $Path = '~'
    } Else {
        $Path = (Get-Location).Path
    }

    # Create prompt.
    "[$($env:USERNAME.ToLower())@$($env:COMPUTERNAME.ToLower()) $Path]$Symbol "
} # End Function: prompt.

Linux Prompt on Windows – Part IX

In the last installment of this series, just published a day ago, I mentioned that I’d like to be able to pass in the fake username and computer name to my prompt function, instead of relying on a hard coded value. Let’s back up, but seriously, only for a second. There’s only so much I’m willing to repeat if you’re starting to read this series at the ninth installment. You can use the links at the very bottom to easily access any of the previous posts.

My prompt function includes my real username and computer name. At times, I like to switch it to a fake username and computer name, so that screen captures won’t include my real information. These hard coded, fake username and computer name values are inside my prompt function as “tommymaynard@cpux1789.” Until now, I wasn’t able to choose the fake username and computer name, and that’s why we’re here today. I’ve added a way to make these values dynamic. I’ve included everything you’d need to copy to your $PROFILE script in order to use this same prompt function. I warn you however, once you start using it, you may not want switch back. And that’s fine, because it just got better.

Here’s an example, before I include the current prompt code. Do notice that the new UserName and ComputerName parameters are completely ignored when the Type parameter value is “Real.” This is because they are not needed in order to use the real username and computer name.

Unfortunately, the Set-Prompt function didn’t feel like a job for ParameterSets. I imagine I could have accomplished “adding” the UserName and ComputerName parameters, when the Type parameter had a value of “Fake,” using dynamic parameters; however, that’s just way too much involvement for now, and would likely bring little return on the invested time. I can be happy with this, at the moment.

Here’s the newest version. Copy it to your $PROFILE script and try it out! You will need a fake, default username and computer name. Toward the bottom of the code, inside the parameter section of the Set-Prompt function, swap out “tommymaynard” for your default, fake username, and “cpux1789,” with your default, fake computer name.

https://gist.github.com/tommymaynard/0dc88b5927ab5f63ee4738d87252fd63

Part VIII | Part VII | Part VI | Part V | Part IV | Part III | Part II | Part I

Linux Prompt on Windows – Part VIII

Update: There’s a part nine, now.

This, is the topic that will never die.

I’m literally about to begin the eighth installment on this topic. There’s no question about it, I love my prompt. In the last installment, we added a more complete PowerShell version number to the prompt, and the entire version number to the WindowTitle. We also added a Type parameter to the prompt function. This allowed me to manually (yuck) edit my function’s Type parameter default value between “Real” and “Fake.” Well, those days are done.

As of now, I’ve removed the default assignment of the Type parameter ([string]$Type = ‘Real’) in the below prompt function. Instead, I added a second function. It’s toward the bottom of the included code, so let’s meet down there.

https://gist.github.com/tommymaynard/4a544e89f71c00abf3611eb18971c71e

Hello again.

The additional function is called Set-Prompt. As the prompt function and this function are in my $PROFILE script, I can expect that they’re both loaded into memory each time a PowerShell host program is opened. In addition to loading the Set-Prompt function into memory, my $PROFILE script also invokes the function. Even though Set-Prompt has a default value for the Type parameter (much like the prompt function had previously), I still pass the “Real” parameter value to the Type parameter.

What this provides is an assurance that my prompt will always be real (include my real username and computer name), when I open a new PowerShell host. If I want to change it to my fake username and computer name for a screen recording, or screen captures, I simply run the below command. The Set-Prompt function doesn’t truly interact with the prompt function. What it does instead, is it updates the $PSDefaultParameterValues variable, so that every time the prompt function is invoked (each new prompt is created), it includes the correct Type parameter value even though we don’t actually see it entered.

Set-Prompt -Type Fake

Since I can’t seem to get away from adding more to my prompt function and this topic, perhaps we’ll do a ninth installment. I would kind of like a way to pass in the fake username and computer name, too. As of now, those values are still hard coded in the prompt function.

Update: I decided to add a graphic to this post. In the below image, although it looks like two different consoles, we’re actually working in the same PowerShell console. In each instance where it was necessary I hid a portion of the computer name. This may actually assist in seeing the real vs. the fake prompt, as I hid a part of my real computer name. The red line helps to indicate the same command in each image.

Part VII | Part VI | Part V | Part IV | Part III | Part II | Part I

Return to Home with cd

I’ve been working in Git Bash a decent amount of my time recently, and I’ve found myself becoming used to using the cd command to return to my home directory (/c/Users/tommymaynard). Did you know you could do that? In that shell, as well as my Cygwin shell, it’s possible. I even fired up my Ubuntu Linux VM and tried it in the Terminal there, as well, and as expected, it works there too.

The cd alias in Windows PowerShell (that’s 5.1), which resolves to the Set-Location cmdlet, doesn’t do the same thing. Therefore, I made a quick modification to the Set-Location function I keep in my $PROFILE script. I’ll include it below, and then discuss it.

# Set-Location runs Push-Location, creates cd <blank> to $HOME (~).
Function Set-Location {
    Param (
        [string]$Path
    )

    If ($Path) {
        Push-Location -Path $Path
    } Else {
        Push-Location -Path ~
    }
}

My Set-Location function, just like the original cmdlet, accepts a path in order to know where in the file system to move the user. If the function is invoked without a path, however, it’ll now move the user to their $HOME directory (C:\Users\<username>\). So you’re aware, Push-Location puts the current location on the stack and then changes location to that which was specified. Again, it’ll move to $HOME, or ~, or C:\Users\<username>, which are all the same, if nothing is specified for the path parameter.

Here’s the a small portion of the help notes from the Push-Location cmdlet: “The Push-Location cmdlet adds, or pushes, the current location onto a location stack. If you specify a path, this cmdlet pushes the current location onto a location stack and then changes the current location to the location specified by the path.” Using my Set-Location function allows me to always use Pop-Location, or the popd alias, to return to my previous location in the file system.

In closing, I do want to mention that using cd by itself in PowerShell 6.0.2 on Windows, and PowerShell 6.0.0-alpha on Linux, works just like it does in Git Bash, Cygwin, and the Terminal on Ubuntu. Without an argument, it’ll automatically move you to your home directory, just like it does now, in my, Windows PowerShell 5.1.

Someone was paying attention.

Linux Prompt on Windows – Part VII

Notes: There have been updates to this post since it was first published. See those notes near the bottom of the post.

There no huge changes between the most current version of my Linux prompt and this one, but it has changed. Because of that, I’ve decided a new post is in order. All the other related posts are linked below.

I took a brief look, and here’s what’s changed between this version and the last.

– There’s a $CustomPrompt variable. You can manually set this to either “real” or “fake.” If it’s “real,” it’ll use the true user and computer name in the prompt. If it’s “fake,” it will allow you to use your own fake user and computer name. In this case, it’ll use whatever has been assigned to the $UserComputer variable. Enter the fake user and computer name as <username>@<computername>. As you can see in the code, it currently says tommymaynard@cpux1789. I tend to use this for demos and screen captures where I don’t want my true username and computer name included.

– The other update here was a modification to the version number. Previously we’d have 2.0, 5.1, and 6.0 at the end of our prompt, and in the WindowTitle. Since the release of 6.0.2, the prompt now includes the first digit of the build, or patch number (it was changed to patch in 6.0). The WindowTitle, however, will include the full patch, or build number. Take a look at this screen capture.

I get the feeling someone might see all this code and think the prompt will load too slowly. It doesn’t. But as proof, I’ve included a quick Gif of the prompt in action. Maybe it’s slower than it should be, but even if it is, I bet you can’t tell. Each time a new prompt appears (Enter key is pressed), the below prompt function code has executed. Yeah, it’s not slow, so no worries on the prompt function length (60ish lines).

And without wasting any more of your time, here’s the prompt code. Drop it into your $PROFILE .ps1 file and give it a run. Like me, you just might find out you want it everywhere.

https://gist.github.com/tommymaynard/7f5907c9a4952a7f77b02c85801d3653

Update I: After posting my prompt function, I noticed something that didn’t make sense any longer. The variable assignment of $UserComputer was outside of the real/fake If-ElseIf statement. Therefore, that assignment was moved into the If portion, as it only needs to be set if the prompt is going to use the the real username and computer name.

Update II: I grew tired of the mid function $CustomPrompt variable assignment, and instead opted for a Type parameter that took care of this assignment. While you can’t pass the parameter value at run time, it’s better than burying the variable assignment deep in the prompt. Due to this, there were a few changes that had to be made to the If and ElseIf conditions. This was nothing more that changing $CustomPrompt to $Type (the newly added parameter).

Update III: Yes, another update (to the above code). Previously the switch statement that determined the host for the WindowTitle didn’t have a default value. That’s to say that if you were using a host other than the ConsoleHost, the Windows PowerShell ISE Host, or the Visual Studio Code Host, it would enter nothing in the WindowTitle before the PowerShell version number. Now, it’ll enter $Host.Name… whatever that ends up being.

Update IV: I removed my code and embedded the GitHub Gist where I’ve been keeping my prompt (outside of my $PROFILE script, of course).

Part VI | Part V | Part IV | Part III | Part II | Part I

Clear Screen After Every Command

Here we go again. I just rescued another draft post, fixed it up enough to share, and published it. Again, this was one of those posts that just never made it past my drafts for one reason or another. I think I figured out what I wasn’t doing correctly, so I’m ready to hand it off.

Never know when I’m going to get inspired to write. Well, I just did and I’m not even sure how it started. All of sudden, I began thinking about ways in which to mess with someone using PowerShell. Perhaps it’s that April Fool’s Day just passed. It’s actually coming, this post is so overdue. I thought to myself, can I get the ConsoleHost to clear each time something is entered? Yeah, of course I can: the prompt function. Been here, done that, just not with such cruel, and obnoxious intentions.

Now to figure it out, for you (and next April Fool’s Day, perhaps). The idea is not to completely modify the prompt function, so as to tip off the user. Instead, the idea is to get their prompt — customized or not — and stuff a Clear-Host command to the end of it. That’s right, every time they enter a command and the prompt is redrawn, it’ll clear the host. Ha! Let’s do this. Yeah, let’s.

How you’re going to get on to your friend’s computer to do this, is up to you. That’s not what I’m here for, just remember your buddy is going to need to spend at least some time in the PowerShell console. Your click-next admin buddies aren’t going to see (or appreciate) this prompt function.

First, we need to get the content that makes up their prompt. It doesn’t matter if it’s been customized or not. Here’s the full command to do that. This command will assign the prompt’s ScriptBlock property to the $CurrentPrompt variable. Additionally, it will pass the value to the ToString() method.

PS MyPrompt > $CurrentPrompt = (Get-Command -Name prompt).ScriptBlock.ToString()

Let’s take a look at the contents of the $CurrentPrompt variable. If you didn’t notice already, you’ll be able to tell that I started with a custom prompt.

PS MyPrompt > $CurrentPrompt
    'PS MyPrompt > '

Next, we’ll create a $NewPrompt variable. Notice that this code includes the $CurrentPrompt variable we created in the first step. This is how we can ensure the prompt has the same look, whether it’s been customized or not. The difference now, is that we’ve added a Clear-Host command inside there. So mean. And Awesome.

PS MyPrompt > $NewPrompt = "$($CurrentPrompt)Clear-Host"

This final command will overwrite the current prompt function with our modification.

Set-Content -Path Function:\prompt -Value $NewPrompt

In closing, I want to provide the full code I used for testing. This contains four different clean prompts, as well as the code we saw above to make the modifications. The first prompt is the one I use on a daily basis and discussed several times around here — it’s my Linux lookalike prompt. Anyway, this will give you some test code to copy to your system and play with. Have fun, then torture your coworkers, but I didn’t say that.

Function Prompt {
	(Get-PSProvider -PSProvider FileSystem).Home = $env:USERPROFILE

	# Determine if Admin and set Symbol variable.
	If ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups -match 'S-1-5-32-544')) {
		$Symbol = '#'
	} Else {
		$Symbol = '$'
	}
	 
	# Write Path to Location Variable 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])"
	}

	# 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 {}
	}

    # Determine PowerShell version.
    $PSVer = "$($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)"

	# Create and write Prompt; Write WindowTitle.
    $UserComputer = "$($env:USERNAME.ToLower())@$($env:COMPUTERNAME.ToLower())" 
    $Location = "$((Get-Location).Drive.Name.ToLower())$Location"

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

    # Actual prompt and title.
    $Host.UI.RawUI.WindowTitle = "$HostName $PSver`: $DebugStart[$UserComputer $Location]$DebugEnd$Symbol"
    "$DebugStart[$UserComputer $Location]$DebugEnd$PSVer$Symbol "
}

Function prompt {
    "PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) "
}

Function prompt {
    'PS > '
}

Function prompt {
    'PS MyPrompt > '
}

Get-ChildItem # Verify no Clear-Host command included.

$CurrentPrompt = (Get-Command -Name prompt).ScriptBlock.ToString()

$CurrentPrompt
	
$NewPrompt = "$($CurrentPrompt)Clear-Host"

Set-Content -Path Function:\prompt -Value $NewPrompt

Get-ChildItem # Verify Clear-Host command included.