Now that I'm creating the inputs dynamically, it doesn't help to have a class for labeled inputs.
And `self._inputs_by_letter[component_letter] = labeled_inputs[-1].query_one(Input)` failed, because it's not mounted yet.
It didn't actually cause an error at runtime because
format_from_extension just uses os.path.splitext, which uses os.fspath
which converts Path objects to path strings.
I had kept these around because several of these I'll want to use,
and the auto-import feature wasn't working, but I've since found a fix
for that (in 453111269e).
I'm also adding rich here to fix auto-imports from rich.
This brings it down from around 20 seconds to less than a second,
for moderately sized documents (i.e. default size).
For larger documents, it can still be slow.
It's still O(n^2) complexity, but more specifically, it's
(n^2 - n) / 2 iterations instead of n^2.
I don't know much about the performance of `enumerate()` or slicing.
It handles the pathological character grid test case SVG I devised,
as well as loading the SVG as saved by the app.
It's a little weird that I managed to get the pathological case working
before the simple rigid grid, but it was what I was shooting for,
and the main problem with the rigid grid was the spanned rects,
which I didn't think of when making the test case SVG.
It does have one problem left; characters that are wider than a cell,
when saved as SVG, take up two cells, but in my SVG loading code,
they're just placed in one cell, so, when saving and loading,
it shifts content to the right of the wide character rightwards,
expanding the region of the background from the wide character's cell.
But it converges now.
It turns out the background rects can span multiple cells, so I have to
pivot strategy here.
Instead of removing any outliers, remove any containers, i.e. rects that
visually (not structurally) contain other rects.
This doesn't yet fill in multiple cells when a rect is spanned.
- DRY: Make decode_based_on_file_extension use format_from_extension.
- If you try to load .html, .htm, .svg, (or ._rich_console_markup) file,
show an error instead of loading as text. The text would be much
larger than a document you saved in this format, and it wouldn't give
you what you expect, unless you're wanting to load an arbitrary text
file for viewing, and for some reason choose this program to do it.
Within the span of like a day I forgot that FIGlet fonts can be
proportional and came back to this code and was confused why charWidth
needs to be a dictionary. Well it doesn't NEED to be, it could be
implemented differently, for instance by fixing the height first,
it wouldn't need to calculate a number of spaces for the blank lines —
but how it's implemented, the width fixup could be disabled, and the
height fixup would still work. So even though the code would be a little
simpler, I'm not sure it would be better that way.
- UnicodeDecodeError was caught in a more general error handler;
now it's allowed to reach the more specific handler.
- UnidentifiedImageError and FormatReadNotSupported were missing return;
now it's not caught there so it doesn't need to, as the exception will
interrupt the control flow.