We're working on a little shell utility that displays paths in a menu. Some of these paths can get rather long, so I cooked up this little regular expression to shorten them. It's a replacement, so you call it like this:
static string PathShortener(string path)
{
const string pattern = @"^(\w+:|\\)(\\[^\\]+\\[^\\]+\\).*(\\[^\\]+\\[^\\]+)$";
const string replacement = "$1$2...$3";
if (Regex.IsMatch(path, pattern))
{
return Regex.Replace(path, pattern, replacement);
}
else
{
return path;
}
}
So, for these paths:
C:\Documents and Settings\jatwood\My Documents\Visual Studio 2005\SimpleEncryption\UnitTests\UnitTests.vb \\wumpus\public\Hilo Deliverables\Hilo Final\Introduction\Code\Intro\App_Themes\cellphone\photo-small.jpg
The result is:
C:\Documents and Settings\jatwood\...\UnitTests\UnitTests.vb \\wumpus\public\...\cellphone\photo-small.jpg
The general strategy is to keep the first two folders at the beginning, replace the middle with an ellipsis, and leave the final folder and filename on the end.
After spending an hour dinking around with this and testing it on a bunch of paths, a colleague pointed me to the Windows API call PathCompactPathEx, which (almost) does the same thing. Doh!
[DllImport("shlwapi.dll", CharSet = CharSet.Auto)]
static extern bool PathCompactPathEx([Out] StringBuilder pszOut, string szPath, int cchMax, int dwFlags);
static string PathShortener(string path, int length)
{
StringBuilder sb = new StringBuilder();
PathCompactPathEx(sb, path, length, 0);
return sb.ToString();
}
As you can see from the API definition for PathCompactPathEx, this works a little differently. It lets you set an absolute length for the path, and displays as many characters as it can with a "best fit" placement of the ellipsis. Here's the output for our two paths:
C:\Documents and Settings\jatwood...\UnitTests.vb \\wumpus\public\Hilo Deliverab...\photo-small.jpg
So, which to choose? CompactPathEx guarantees that the paths will always be exactly (x) characters while displaying as much as it can, but it may not be able to split cleanly. My regex always splits cleanly, but makes no guarantees on length.
And obviously, if you're not running Windows, or if you don't care for p/invoke, the API call is clearly out.
Posted by Jeff Atwood View blog reactions
« Open Source: Free as in "Free" My Love/Hate relationship with ClearType »
Dude?! Is that C# code on your blog? ;)
Haacked on August 2, 2006 02:48 PMYep. I am bilingual now.
VB is still better, though. I also prefer Pepsi.
http://www.codinghorror.com/blog/archives/000519.html
Jeff Atwood on August 2, 2006 03:01 PMCould I suggest tweaking the replacement string so that it uses three rather than two dots? As it stands, the resulting abbreviated path looks just a little too much like a proper path.
Keith Gaughan on August 2, 2006 03:20 PMGo w/ the regex, a little more platform independent... if any at all.
Alex on August 2, 2006 03:52 PMI would go with PathCompactPathEx.
Reasons:
1. it probably fine tuned and debugged, and works with stuff you don't even think about.
They probably fixed bugs you are only now starting to encounter. For instance it might handle forward slash as path separator, which is valid, but you regexp does not handle :-)
2. using the standard API would make your application more consistent with the system and all the other applications using it, which is a good thing (unless the system thing is not really-reall bad, which I don't think is the case)
If you are using WinForms (it isn't clear), you can use the StringTrimming property of a StringFormat object to control how text is written using Graphics.DrawString().
StringTrimming.EllipsisPath is probably making use of PathCompactPathEx under the hood.
I'm not suggesting it is a better solution than the other 2, just mentioning it as available option in the specific Graphics drawing scenario.
Joshua Flanagan on August 2, 2006 04:48 PMAh, this takes me back - this task was my very first attempt at programming way back when I was doing my thesis on VAX/VMS and was a biologist not an IT developer.
I used it to get the prompt to display the current directory.
I probably would not have consciously remembered this outside of reading this article.
Paul Coddington on August 2, 2006 09:11 PMThat's actually a very useful function, I remember kludging many a solution to this in pre-.NET apps (i.e. no native regex support).
I do have to call you on one thing though: your routine name is a noun, not a verb!
Aaron G on August 3, 2006 07:45 AMHi,
I agree with Mihai: Consistency is key here. Whenever you want to do something and the Windows API provides a solution for it, you should go with that. Because, once everyone does that, every application works the same which is good for general usability (lower learning curve).
Now I agree that shortening paths is something with a lower impact on usabliity than, say, file open dialogs, but aonsistency still is a nice thing to get.
And imagine Microsoft doing something fancy to that routine in the future (maybe a genious will find a whole new (and better) way for shortening paths or maybe windows will begin interpreting control sequences in character strings put to labels for example to display additonal UI (maybe a tooltip or something) so the whole path can be displayed after all (just speculating here. I'm not saying it's an intelligent thing to do).
If you use this routine, you will automatically be able to take advantage of such changes.
Philip
PS: Your captcha is broken: It's always the same word I have to enter (orange) - even with different browsers, so it's no cookie thing
> Your captcha is broken: It's always the same word I have to enter (orange) - even with different browsers, so it's no cookie thing.
Really? Are you sure you're not a robot? Have you checked recently? ;)
Jeff Atwood on August 4, 2006 02:22 AMJeff,
yes, I'm sure. It's always the same word. Even after cleaning the cookies, the word stays the same. But seeing the pictures URL, I guess it's indended.
I guess the spammers tools are too simplistic to even attempt to break the captcha. Probably because each site would require a different sort of processing which is just too expensive to do with all the non-captcha'd blogs out there.
Nice idea.
I guess even "Please type gnegg blow" would do it.
At least for now.
Philip
Philip Hofstetter on August 4, 2006 04:20 AMJeff,
I think I understand more quickly that an abbreviated path is being displayed when I see a directory name that seems cut short by the ellipses. Looks like the Windows API method would do that in a larger percentage of the cases...
/k
Kurtiss on August 4, 2006 06:30 AMPepsi?
Philistine!
| Content (c) 2008 Jeff Atwood. Logo image used with permission of the author. (c) 1993 Steven C. McConnell. All Rights Reserved. |