NOTE: This breaks lots of internal APIs, many of which are actually
exposed as public API. `brick` does not break, but client code that
depends on constants containing escape sequences will need to adapt.
There's really no point in using `[Char]` here. The first thing the code
did was convert all the bytes individually to `Char` and putting them
into a linked list. Then, when actually parsing utf-8, it turns those
`Char`s back into `Word8`s. All the other code is generally concerned
with bytes and goes out of its way to deal with `[Char]` instead. The
code is now simpler and much faster.
Overall this gives another order of magnitude speedup over the previous
speedup totalling roughly a 200x speedup over 2 commits ago for the
300KB case (it's less for smaller cases and much more for larger cases,
because we already made one `n^2` algorithm `n`).
This does not fix the polynomial time complexity, but at this point we
can comfortably paste a low number of megabytes into the terminal and
process it reasonably quickly. This is sufficient to support small file
uploads via bracketed paste.
Some timing:
* 100KB: unmeasurable by hand (basically instant)
* 1000KB: 2 seconds
* 1500KB: 3 seconds
* 2000KB: 5 seconds
* 3000KB: 10 seconds
* 4000KB: 17 seconds
Integral types like Char and Int benefit a lot from UNPACK. For these,
there is also very little reason to use lazy fields, especially in this
codebase where most computations don't need laziness.
The current algorithm has polynomial time complexity. The new algorithm
runs in linear time and is generally much more efficient because it
operates on packed byte strings instead of linked lists of Char.
Some timing:
* 100KB: 1 second
* 200KB: 2.5 seconds
* 300KB: 4 seconds
* 400KB: 7 seconds
* 500KB: 12 seconds
* 600KB: 16 seconds
* 700KB: 22 seconds
As we can see, it's still `O(n^2)` overall, probably because of the
calls to `bracketedPasteFinished`. I'll investigate that next. The
constant factor overall is much lower now:
```
Before: 2.866E-6n^3 - 1.784E-4n^2 + 0.114n - 2.622
After: -1.389E-8n^3 + 5.53E-5n^2 - 1.604E-3n + 0.273
```
This change removes the aforementioned instances because they were
misbehaved; merging Attr and MaybeDefault values with these instances
resulted in field value losses. For example, before this change,
(defAttr `withForeColor` blue) <> (defAttr `withBackColor` green)
would result in just
(defAttr `withBackColor` green)
because the instances were designed to favor the right-hand arguments'
fields even if they had not been explicitly set (a consequence of the
MaybeDefault Semigroup instance). While that behavior was sensible
specifically in the context of Graphics.Vty.Inline, it wasn't a useful
user-facing API and it made for surprising instance behavior. Since
there is actually no good way to handle this in a Semigroup instance for
Attr -- some choices have to be made about how to merge two attributes'
foreground colors, and that won't be much better than what we had -- the
instance was just removed. I suspect that the risk of this impacting
users negatively is very low, given that the instance behavior was not
very useful.