Contents:
One more unintended thing arose from another post.
I was looking for a way to fit a lot of lengthy paths into console screen by removing less important parts. “Ellipsis” is a standard name for such a thing. You’re dealing with it every time you’re looking at “…” in place of something too long to fit into borders.
Here is my implementation for PowerShell.
Let’s say we have a string “C:\Windows\System32 The most trivial approach is to cut (50-3)/2 characters from left and right sides of a string, join them like After little research in Google, I found not so many solutions. With only one worth to be noted (no surprises, since it may seem trivial). But instead of just reimplementing it in PowerShell, I decided to do my own from scratch.
The code is available on GitHub and below is some kind of description. You may need to check the code first, since I’m not providing it here.
The main idea looks like this:
Back to our example. If we split the path string by directory separator “\“, we will get following array of string segments:
“C:“, “Windows”, “System32”, “WindowsPowerShell”, “v1.0”, “Modules”, “WindowsErrorReporting”, “WindowsErrorReporting.psm1”
Now we can fit them into output string step by step, checking if we are still fit into bounds. For a decision which segment should be added next, we have few options: we may prefer output string to be ellipsed approximately in the middle visually (by number of characters), or we may prefer to keep similar number of segments on the left and on the right. The resulting code is providing both options but let’s just count segments for this example.
* When both sides are empty, 0.5 is a good assumption for a proportion.
** 3 is for ellipsis, 1 is for separator, and the other number is for string length.
The output is In this example we end up with 0 characters left. In case there is still free space left, algorithm can do few things: leave it as is and return shorter string, or add a part of next segment to left or right side of ellipsis. In “auto” mode it will decide based on proportion from the last step. By default, algorithm prefers left side as containing more useful information.
In this example we have chosen every next segment by comparing proportion to 0.5 (less or equal - choose left, otherwise right). We could also target not only middle point, but any arbitrary point actually, in case we would like to see more of the tail or the head of the string.
In case we prefer to compare string lengths rather than segment numbers, the algorithm looks exactly the same, with an exception of counters “Left” and “Right” being filled differently.
It looks overengineered. Am I sure that it will work properly?
First of all, I added debug output, that produces a table, similar to the one above and checked my math in various cases. You can turn it on with And then I added Pester tests to be sure that I have documented behaviour for every function parameter.
I’m aware that there is a lot of array manipulations in code that can be avoided. At the moment, this code fits my requirements and I’m pretty happy with it. I may do some updates and performance estimation in the future, but for now I need to move on.
After getting a working function, I thought that it’s a good candidate to learn about PowerShell module release process.
For now I have Pester tests and I will add Appveyor support shortly after (Update: added). I may also release it in the PowerShell Gallery if I get some positive feedback. Do you want it to be available from Install-Module?
One conscious decision I’ve made is that I will not optimize the workflow for PowerShell v2.0. But single-file version compatible with v2.0 is provided at least.
Once again, everything is available on GitHub.
$left + "..." + $right
and get C:\Windows\System32\Wind...dowsErrorReporting.psm1
. It works and may even be good enough in a lot of cases. But what I don’t like about it is that it is unaware of folder and file name borders, cutting right in the middle, and can be misleading sometimes.
Make it work
Step
Left
Right
L/(L+R)
Free space
Next segment
Fit
Free space after
1
0
0
0.5 *
50
left: “C:”
Yes
50-2-1-3 = 44 **
2
1
0
1
44
right: “WindowsErrorReporting.psm1”
Yes
44-26-1 = 17
3
1
1
0.5
17
left: “Windows”
Yes
17-7-1 = 9
4
2
1
0.667
9
right: “WindowsErrorReporting”
No
9
9
left: “System32”
Yes
9-8-1 = 0
C:\Windows\System32\...\WindowsErrorReporting.psm1
. We end up with left side having two more segments (3) than the right side (1), even though we tried to keep them equal. That’s because we also tried to fit as much segments as possible (checked other side after fitting failure). The resulting code has a strict mode that will not switch to opposite side when facing limitations (as in step 4) and will give C:\Windows\...\WindowsErrorReporting.psm1
as output.
Make it right
$DebugPreference = 'Continue'
:
> Format-Ellipsis 'C:\Windows\System32\WindowsPowerShell\v1.0\Modules​\WindowsErrorReporting​\WindowsErrorReporting.psm1' 50 -by 'count'
DEBUG: 0 | 0 | 0,5 | 46 | 47 | ...
DEBUG: 1 | 0 | 1 | 43 | 44 | C:\...
DEBUG: 1 | 1 | 0,5 | 16 | 17 | C:\...\WindowsErrorReporting.psm1
DEBUG: 2 | 1 | 0,66667 | 8 | 9 | C:\Windows\...\WindowsErrorReporting.psm1
DEBUG: 3 | 1 | 0,75 | -1 | 0 | C:\Windows\System32\...\WindowsErrorReporting.psm1
DEBUG:
--------------------------------------------------
C:\Windows\System32\...\WindowsErrorReporting.psm1
Make it fast
The module
Where to get it