Instead of handwriting the help text, which was time consuming and
prone to errors, I'm finally using the help parameter in
parser.add_argument. betterhelp will render and colorize this for
some good-looking automatic help text.
The make_helptext function is still extremely long and would be nice
to refactor, but I've been sitting on this commit for a few weeks now
and I want to get my git repositories back in sync.
Formerly I was normalizing backslash to forwardslash on unix, which is
bad. Then I removed the function because I thought normpath was the
right tool for the job. Now I'm finding a few situations I just want to
norm the sep again.
In spinal.walk sorting is optional because there I prioritize
configurability and speed, but for pathclass.walk I think it
makes sense to prioritize comfort and just-works results.
I was inspired by the idea of "making impossible states impossible"
and using a data model that accurately represents what we intend for
it to represent. Instead of storing the path as a string where "it's
a string but actually you're supposed to know that the parts between
os.seps are different parts and the first one is special and...", we
can use a data model that directly says that. Storing the path as a
tuple of (Drive, Part, Part) helps me focus on the semantics of the
Path as a collection of parts joined by the os.sep.
Furthermore, storing the path as a string made some operations slow.
Every time we call one of the os.path functions with a string, it
has to do a lot of normalization and edge-case handling even when we
know it wouldn't be needed. By storing the path as a tuple, we can
instantly get the drive name, parent dir name, and basename without
asking os.path to split it for us every single time. It also makes
relative path / common ancestor checks a lot easier to understand.
Fewer operations need to go into the slow functions.