Tag Archives: Windows Terminal

Windows Terminal Fun Suprise

I saw a Tweet today from Kayla Cinnamon: https://twitter.com/cinnamon_msft/status/1455946220476657665. Here’s the Tweet.

Although she wrote to type Alt+Shift+D, she obviously didn’t mean it that way. I looked past that, although some of the comments proved that others did not. I quickly figured out what it did and then I determined how to not use that keyboard key combination. Before we see that, let’s determine what Alt+Shift+D does.

Alt+Shift+D opens up a new terminal, or rather, it duplicates the pane. If you take a look at the Settings menu you’ll quickly discover a large number of other fun surprises (a.k.a. keyboard key combinations). Someday, I’ll take the time and work through those.

Anyway, here’s what you shouldn’t do.

[PS7.1.5][C:\] Add-Type -AssemblyName System.Windows.Forms
[PS7.1.5][C:\] 1..10 | ForEach-Object {[System.Windows.Forms.SendKeys]::SendWait('%+D')}

This lovely piece of frustration — if you can sneak it into a “friend’s” profile script — will add the System.Windows.Forms assembly and then send in the Alt+Shift+D key combination for each iteration through the ForEach-Object loop. In this example, it would be a total of ten times. So it’s been said, the SendWait method includes “%” and “+” in addition to the letter “D.” As you may have already guessed, if you didn’t know, these two symbols are used for Alt and Shift, respectively. So what’s this produce? It does what a good number of people that replied to Kayla’s Tweet showed us they could do by repetitively pressing the key combination. That said, why do it manually? It’s PowerShell!

Back to when she said to “type” the keyboard command. It did make me think to do something with the string value Alt+Shift+D.

In the top-left pane, which was the only one when I started, I created a function called Alt+Shift+D. It included the two commands from earlier. Then I tested it/invoked my new function and it added the pane on the right side. Then I created an alias for my function, because who wants to type out the entirety of Alt+Shift+D each time — not me — and tested it too. It opened the bottom-left pane. If you aren’t using Windows Terminal then you should be; it continues to get better all the time.

Setting the Rounding Scale

Sometimes sharing one concept in a post, allows you to share another concept in another post. That brings us to today. This is that other post.

Originally, I had a great title for this post: It was Rounding Precision Decision. Then, for whatever reason, I went and made sure that precision was the word I was after. It wasn’t. Precision is the total number of digits in a number. Scale is the number of digits after the decimal.

Last night I decided I should add a Round parameter to a function I’m writing. This would allow the user to determine how rounding should be applied to a given number. The parameter values, as I see them now, will be 0 through 4. This is to say a numerical value may have zero decimal places up to four, depending on the person/process running the function. Neat, right? Like I sometimes do, I opened Window Terminal to start some one-off testing.

Let’s start with an ordered hash table of numeric values. As you’ll see, the values will vary in the number of decimal places from zero to five.

[PS7.1.5][C:\] $Hash = [ordered]@{'Num0' = 42; 'Num1' = 42.1; 'Num2' = 42.12; 'Num3' = 42.123; 'Num4' = 42.1234; 'Num5' = 42.12345}
[PS7.1.5][C:\] $Hash

Name               Value
----               -----
Num0               42
Num1               42.1
Num2               42.12
Num3               42.123
Num4               42.1234
Num5               42.12345
[PS7.1.5][C:\] 

While we’re here, let’s loop through the keys and values in this hash table. We’ll need this construct soon enough anyway.

[PS7.1.5][C:\] Foreach ($Key in $Hash.Keys) {"$Key`: $($Hash[$Key])"}
Num0: 42
Num1: 42.1
Num2: 42.12
Num3: 42.123
Num4: 42.1234
Num5: 42.12345
[PS7.1.5][C:\] 

That works. Now what we need to consider is that we’re going to need to iterate over $Hash multiple times, so we can apply each of the decimal values, 0 – 5 for this post. This may be confusing, but the next example should help explain how we get there.

[PS7.1.5][C:\] Foreach ($Value in 0..5) {$Value}
0
1
2
3
4
5
[PS7.1.5][C:\] Foreach ($Value in 0..5) {Foreach ($Key in $Hash.Keys) {"$Key`: $($Hash[$Key])"}}
Num0: 42
Num1: 42.1
Num2: 42.12
Num3: 42.123
Num4: 42.1234
Num5: 42.12345
Num0: 42
Num1: 42.1
Num2: 42.12
Num3: 42.123
Num4: 42.1234
Num5: 42.12345
Num0: 42
Num1: 42.1
Num2: 42.12
Num3: 42.123
Num4: 42.1234
Num5: 42.12345
Num0: 42
Num1: 42.1
Num2: 42.12
Num3: 42.123
Num4: 42.1234
Num5: 42.12345
Num0: 42
Num1: 42.1
Num2: 42.12
Num3: 42.123
Num4: 42.1234
Num5: 42.12345
Num0: 42
Num1: 42.1
Num2: 42.12
Num3: 42.123
Num4: 42.1234
Num5: 42.12345
[PS7.1.5][C:\]

Now that we have this working, let’s apply some rounding to each of the sets of numbers. Before we do that, however, I’m heading back to VSCode. Sometimes the one-off code I write gets a bit unwieldy. For reference, we’re going to use the Round method in the System.Math class, such as [math]::Round(<number>,<scale>).

$Hash = [ordered]@{
	'Num0' = 42
	'Num1' = 42.1
	'Num2' = 42.12
	'Num3' = 42.123
	'Num4' = 42.1234
	'Num5' = 42.12345
}
Foreach ($Value in 0..5) {
	"Rounding to $Value"
	Foreach ($Key in $Hash.Keys) {
		"$Key`: $([math]::Round($Hash[$Key],$Value))"
	} # End Foreach.
'--separator--'
} # End Foreach.

Rounding to 0
Num0: 42
Num1: 42
Num2: 42
Num3: 42
Num4: 42
Num5: 42
--separator--
Rounding to 1
Num0: 42
Num1: 42.1
Num2: 42.1
Num3: 42.1
Num4: 42.1
Num5: 42.1
--separator--
Rounding to 2
Num0: 42
Num1: 42.1
Num2: 42.12
Num3: 42.12
Num4: 42.12
Num5: 42.12
--separator--
Rounding to 3
Num0: 42
Num1: 42.1
Num2: 42.12
Num3: 42.123
Num4: 42.123
Num5: 42.123
--separator--
Rounding to 4
Num0: 42
Num1: 42.1
Num2: 42.12
Num3: 42.123
Num4: 42.1234
Num5: 42.1234
--separator--
Rounding to 5
Num0: 42
Num1: 42.1
Num2: 42.12
Num3: 42.123
Num4: 42.1234
Num5: 42.12345
--separator--

At first glance, this PowerShell code may look like it’s failing. Look at the “Rounding to 3” section, for instance. There are values where it appeared to round to zero, one, and two decimal places. Remember though, these numbers didn’t start with three decimals places or more. It did exactly what we asked it to do to the best of its ability. I don’t know of a way that the Round method can add zeros if we actually wanted that — let me know if you — but there’s another way!

This time, we’ll use the -f format operator and force zeros into the decimals places. I probably won’t do this in my upcoming post, but I think it’s worth seeing, as there’s value here.

Foreach ($Value in 0..5) {
	"Rounding to $Value"
	Foreach ($Key in $Hash.Keys) {
		"$Key`: $("{0:N$Value}" -f $Hash[$Key])"
	} # End Foreach.
'--separator--'
} # End Foreach.

Rounding to 0
Num0: 42
Num1: 42
Num2: 42
Num3: 42
Num4: 42
Num5: 42
--separator--
Rounding to 1
Num0: 42.0
Num1: 42.1
Num2: 42.1
Num3: 42.1
Num4: 42.1
Num5: 42.1
--separator--
Rounding to 2
Num0: 42.00
Num1: 42.10
Num2: 42.12
Num3: 42.12
Num4: 42.12
Num5: 42.12
--separator--
Rounding to 3
Num0: 42.000
Num1: 42.100
Num2: 42.120
Num3: 42.123
Num4: 42.123
Num5: 42.123
--separator--
Rounding to 4
Num0: 42.0000
Num1: 42.1000
Num2: 42.1200
Num3: 42.1230
Num4: 42.1234
Num5: 42.1234
--separator--
Rounding to 5
Num0: 42.00000
Num1: 42.10000
Num2: 42.12000
Num3: 42.12300
Num4: 42.12340
Num5: 42.12345
--separator--

And that’s, that. Back to the other post that inspired this one. See you there in time!

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.