`4` is actually defined as CMYK according to ITU-T Rec. T.416:
> A parameter substring for values 38 or 48 may be divided by one or more separators (03/10) into parameter elements,
> denoted as Pe. The format of such a parameter sub-string is indicated as:
>
> Pe : P ...
>
> Each parameter element consists of zero, one or more bit combinations from 03/00 to 03/09, representing the digits
> 0 to 9. An empty parameter element represents a default value for this parameter element. Empty parameter elements at
> the end of the parameter substring need not be included.
>
> The first parameter element indicates a choice between:
>
> 0 implementation defined (only applicable for the character foreground colour)
> 1 transparent;
> 2 direct colour in RGB space;
> 3 direct colour in CMY space;
> 4 direct colour in CMYK space;
> 5 indexed colour.
refs: 6e9a22e199 (commitcomment-79669016)
This commit extends the sgr color parser to support a wezterm
extension that I just made up:
```
printf "\e[48:4:255:0:0:60mhello\e0m"
```
The `4` is wezterm specific and denotes 4 channel color, in this case
RGBA. red is 255, green is 0, blue is 0 and alpha is 60; the values are
interpreted as u8 values.
CSI 38 (fg), 48 (bg) and 58 (underline) support this.
refs: https://github.com/wez/wezterm/issues/2313
This doesn't really change any behavior, but adjusts the types
such that CSIs that set colors have the potential to track the
alpha channel and that can make it through to the GUI/render layer.
This reduces the resident memory by another ~10% because it avoids
keeping as many runs of whitespace.
Runtime for `time cat enwiki8.wiki` is still ~11-12s, resident: 530K
refs: https://github.com/wez/wezterm/issues/1626
The previous commit added the option to convert the storage to
the cluster format. That saves memory as rows are moved to scrollback,
but makes scrolling back more expensive due to that conversion.
This commit adds a fast(ish) path for the common case of simply
appending text to a new line before it gets scrolled: the default
format for lines in the screen is now the cluster format and,
provided that the cursor moves from left to right as text is
emitted, can simply append to the cluster storage in-place
and avoids a conversion when the line is moved to scrollback.
This improves the throughput of `time cat enwiki8.wiki` so
that the runtime is typically around 11-12s (compared to 9-10s
before introducing cluster storage). However, this is often
a deal of variance in the measured time and I believe that
that is due to the renderer triggering conversions back to
the vec storage and introducing slowdowns from the render side.
That's what I'll investigate next.
Previously this would create a new String because it had to, but
with the clustered storage we may be able to simply reference the
existing string as a str reference, so allow for that.
Adds the option to use an alternative clusted line storage for
the cells component of the line.
This structure is not optimal for mutation, but is better structured
for:
* matching/extracting textual content
* using less memory than the prior simple vector
For some contrast: the line "hello" occupies 5 Cells in the cell based
storage; that 5 discrete Cells each with their own tiny string
and a copy of their attributes.
The clustered version of the line stores one copy of the cell
attributes, the string "hello" and some small (almost constant size)
overhead for some metadata. For simple lines of ascii text, the
clustered version is smaller as there are fewer copies of the cell
attributes. Over the span of a large scrollback and typical terminal
display composition, this saving is anticipated to be significant.
The clustered version is also cheaper to search as it doesn't require
building a copy of the search text for each line (provided the line is
already in clustered form).
This commit introduces the capability: none of the internals request the
new form yet, and there are likely a few call sites that need to be
tweaked to avoid coersion from clustered to vector form.
While profiling `time cat bigfile` I noted that a big chunk of the
time is spent computing widths, so I wanted to dig into a bit.
After playing around with a few options, I settled on the approach
in this commit.
The key observations:
* WcWidth::from_char performs a series of binary searches.
The fast path was for ASCII, but anything outside that range
suffered in terms of latency.
* Binary search does a lot more work than a simple table lookup,
so it is desirable to use a lookup, and moreso to combine the
different tables into a single table so that classification
is an O(1) super fast lookup in the most common cases.
Here's some benchmarking results comparing the prior implementation
(grapheme_column_width) against this new pre-computed table
implementation (grapheme_column_width_tbl).
The ASCII case is more than 5x faster than before at a reasonably snappy
~3.5ns, with the more complex cases being closer to a constant ~20ns
down from 120ns in some cases.
There are changes here to widechar_width.rs that should get
upstreamed.
```
column_width ASCII/grapheme_column_width
time: [23.413 ns 23.432 ns 23.451 ns]
column_width ASCII/grapheme_column_width_tbl
time: [3.4066 ns 3.4092 ns 3.4121 ns]
column_width variation selector/grapheme_column_width
time: [119.99 ns 120.13 ns 120.28 ns]
column_width variation selector/grapheme_column_width_tbl
time: [21.185 ns 21.253 ns 21.346 ns]
column_width variation selector unicode 14/grapheme_column_width
time: [119.44 ns 119.56 ns 119.69 ns]
column_width variation selector unicode 14/grapheme_column_width_tbl
time: [21.214 ns 21.236 ns 21.264 ns]
column_width WidenedIn9/grapheme_column_width
time: [99.652 ns 99.905 ns 100.18 ns]
column_width WidenedIn9/grapheme_column_width_tbl
time: [21.394 ns 21.419 ns 21.446 ns]
column_width Unassigned/grapheme_column_width
time: [82.767 ns 82.843 ns 82.926 ns]
column_width Unassigned/grapheme_column_width_tbl
time: [24.230 ns 24.319 ns 24.428 ns]
```
Here's the benchmark summary after cleaning this diff up ready
to commit; it shows ~70-80% improvement in these cases:
```
; cargo criterion -- column_width
column_width ASCII/grapheme_column_width
time: [3.4237 ns 3.4347 ns 3.4463 ns]
change: [-85.401% -85.353% -85.302%] (p = 0.00 < 0.05)
Performance has improved.
column_width variation selector/grapheme_column_width
time: [20.918 ns 20.935 ns 20.957 ns]
change: [-82.562% -82.384% -82.152%] (p = 0.00 < 0.05)
Performance has improved.
column_width variation selector unicode 14/grapheme_column_width
time: [21.190 ns 21.210 ns 21.233 ns]
change: [-82.294% -82.261% -82.224%] (p = 0.00 < 0.05)
Performance has improved.
column_width WidenedIn9/grapheme_column_width
time: [21.603 ns 21.630 ns 21.662 ns]
change: [-78.429% -78.375% -78.322%] (p = 0.00 < 0.05)
Performance has improved.
column_width Unassigned/grapheme_column_width
time: [23.283 ns 23.355 ns 23.435 ns]
change: [-71.826% -71.734% -71.641%] (p = 0.00 < 0.05)
Performance has improved.
```
This enables tentative support for https://sw.kovidgoyal.net/kitty/keyboard-protocol
It's only been lightly tested with the notcurses-input program and
eyeballed against a few random keypresses in kitty running
`printf "\x1b[=11u" ; od -c`
I tried with neovim, but it doesn't seem like the version available
in Fedora 36 supports this yet.
refs: https://github.com/wez/wezterm/issues/1141
The `File` variant for background layers may now be an object
that specifes a speed factor. That factor is applied to the
animation frame durations in the loaded image, allowing the
playback rate to be adjusted.
Avoid using serde for mapping between Lua and Rust for the `Config`
struct.
This improves the build speed of the config crate by 2x; it goes down
from 30 seconds to 9 seconds on my 5950x.
Also ensure the rust backtrace is printed by the fuzzer
for some reason, cargo-fuzz doesn't do this automatically, which limits
its out-of-the-box utility.
refs: https://github.com/wez/wezterm/pull/1986