Given a sequence like this, where the `ESC [ K` sequence is
emitted at the last column when wrap_next=true:
\u001b[47;30m 17:24:50 \u001b[0m\u001b[K
rather than treating the column as out of bounds, we'd clear the
final cell.
refs: #3548
The server-side ownership of the palette is a stumbling block for
many users, so let's fix it.
This commit allows the client to pass its configured palette to
the server when it connects, and when the config is changed.
That palette takes precedence over the palette from the server config.
However, if the remote application uses any escape sequences that
redefine the color palette, the color palette that was active at
that point in time is forked and use as the basis, and will remain
the active palette until the palette is reset via escape sequences.
refs: https://github.com/wez/wezterm/issues/2686
refs: https://github.com/wez/wezterm/issues/3397
* Translate from File to EncodedFile as needed
* Adopt blob leases in the mux server
* Fix an issue where the first image sent by the mux server would
be replaced on the client by its background image, if configured.
Removed the ImageData::id field to resolve this: you should use
the hash field instead to identify and disambiguate images.
Bumped the termwiz API version because this is conceptually
a breaking change to the API
refs: https://github.com/wez/wezterm/issues/3343
Really, this is adjusting the logical line breaking behavior, or the
lack thereof.
The situation is this: conpty can decided to reinterpret and flush
large sections of its buffer as a continuous stream of unbroken
characters with no breaks when it repaints the full screen.
When we receive such an update, we see it as one long logical line,
and when we subsequently select multiple lines we can run into the
maximum logical line length and insert invalid synthetic line breaks
into the data that we send to the clipboard.
This commit adjusts the wrapping logic at the time that we receive
the text so that we don't tag the line as a logical line continuation
if:
* The alt screen is active. Full screen apps will re-render on resize
anyway, and we don't reflow long lines on resize either for the same
reasons
* If we are talking to ConPTY:
* If the last character in the line is not alphanumeric or
punctuation (in other words: it doesn't look plausibly like
text that should be a line continuation).
refs: #3278
refs: #3177
- Removes closures and function calls for types that implement default:
```rust
// Change
let _my_str = get_str().unwrap_or(String::new);
// To
let _my_str = get_str().unwrap_or_default();
```
- Uses the `.cloned()/.copied()` methods where possible
- Use function pointer instead of simple closure
May improve performace, as closures generate more code, and this might
unlock some inlining opportunities.
- Use `find` instead of `position(..).next()`
- Use `any` instead of `position(..).next().is_some()/.is_none()`
- Use `first/next` instead of `get(0)/nth(0)`
- Prefer `for` loops over `while let` loops on iterators
May improve performance.
Adopt the new blob lease layer to storing and referencing
image files.
This reduces the number of open files needed when
images are being displayed in the terminal.
refs: https://github.com/wez/wezterm/issues/3263
Input data:
\e_Ga=T,f=32,s=10,v=22,c=1,r=1,m=1\e\\e_Gm=1;/xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T//P=\e\\e_Gm=1;/xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T////E////xP///8T//P=\e\\e_Gm=0\e\
There were two issues in handling this:
* We expected there to be `;payload` in the first transmission packet,
but there wasn't one, so we ignored it as ill-formed.
* The standard base64 decoder in the rust ecosystem is super strict
and rejects the "sloppy" python base64 encoder output that isn't
strictly conformant with the RFC. We need to jump through some
hoops to get it to relax and accept the input.
refs: https://github.com/wez/wezterm/issues/2716
Continuing from the previous commit, this shifts:
* In-memory data -> temporary file
* Image decoding -> background thread
The background thread asynchronously decodes frames and
sends them to the render thread via a bounded channel.
While decoding frames, it writes them, uncompressed, to
a scratch file so that when the animation loops, it is
a very cheap operation to rewind and pull that data
from the file, without having to burn CPU to re-decode
the data from the start.
Memory usage is bounded to 4 uncompressed frames while
decoding, then 3 uncompressed frames (triple buffered)
while looping over the rest.
However, disk usage is N uncompressed frames.
refs: https://github.com/wez/wezterm/issues/3263
This makes decoding animation frames a lazy operation, but it
comes at the cost of needing to re-decode the image from scratch
when it loops, because the image crate doesn't provide a way
to rewind its frame iterator.
That initial decode can have a significant time cost; a small
webp file consistently takes 150ms to decode, which is too
much to do inline in the render thread.
Next steps will be to move that cost off the render thread.
I spent a few hours in heap profilers. What I found was:
* Inefficient use of heap when building up runs of
`Action::Print(char)`.
-> Solve by adding `Action::PrintString(String)`
and accumulating utf8 bytes rather than u32 codepoints.
* Inefficient use of heap when building Quad buffers: the default
exponential growth of `Vec` tended to waste 40%-75% of the allocated
capacity, and since we could keep ~1024 of these in cache, there's
a lot of potential for waste.
-> Solve by bounding the growth to 64 at a time. This has similar
characteristics to exponential growth at the default 80x24 terminal
size. May need to add a config option for this step size for users
with very large terminals.
* Lazy eviction from the LFU caches. The underlying cache advisor is
somewhat probabilistic and has a minimum cache size of 256, making
it difficult to maintain low heap utilization.
-> Solve by replacing it with a very simple LFU algorithm. It doesn't
seem to hurt much at the default terminal size with the default
cache sizes. If we make the cache sizes smaller, its overhead is
reduced.
Some further experimentation is needed to adjust defaults, but this
should help reduce heap usage.
refs: https://github.com/wez/wezterm/issues/2626
I've expanded the number of bits from 16->32 without impacting
the overall struct sizes and reserved 2 bits for super/subscript.
I refer to these as vertical alignment properties for conceptual
consistency with css.
SGR 73, 74, 75 are used to set super, sub and normal vertical alignment.
These are compatible with mintty.
However, mintty just added support for setting both attributes to render in
small caps in 06ac446049
(https://github.com/mintty/mintty/issues/1171)
According to its benchmarks, it's almost 2x faster than
unicode_segmentation. It doesn't appear to make a visible
difference to `time cat bigfile`, but I'll take anything
that gives more headroom for such little effort of switching.
Action is used to encode parsed terminal output and shuttle it between
the thread that does the parsing and the main gui thread that applies
it to the terminal model.
Take it down from 184 bytes to 40 bytes (on 64-bit systems). This seems
to boost `time cat bigfile` by reducing the runtime to ~40% of its prior
duration: down from 8s -> 4.5s on an M1 macbook air.
Size reductions achieved by Box'ing relatively less frequently
used enum variants. The kitty image data variant is particularly
large, and the Window variant is also pretty heavy.
Remove the faulty cache key stuff and hang references to the cached
data directly off the underlying Line. That makes the association
between the the Line and the data O(1) plus some basic cache
invalidation checks.
Adjust the shape cache portion of this to use the same ID for the
shape, so that things that invalidate just the quads (such as cursor
movement when not composing, and selection) only need to recompute
the quads without re-shaping.
Adds Pane::for_each_logical_line_in_stable_range_mut and
Pane::with_lines_mut which allow iterating mutably over lines.
The idea is that this will allow the renderer to directly cache
data in the Line via its appdata without having to build cumbersome
external caching logic and managing cache keys.
This commit just swaps the implementation around for localpane
and sanity checks that the renderer functions.
Various overlays and the mux client don't properly implement these
yet and current warn at compile time and panic at runtime.
To follow is the logic to cache the data and make sure that it
works the way that I think before converting the other Pane
implementations.