Adds logic to resize handling that will consider the original logical
line length when the width of the terminal is changed.
The intent is that this will cause the text to be re-flowed as if it had
been printed into the terminal at the new width. Lines that were
wrapped due to hittin the margin will be un-wrapped and made into a
single logical line, and then split into chunks of the new width.
This can cause new lines to be generated in the scrollback when
making the terminal narrower. To avoid losing the top of the buffer
in that case, the rewrapping logic will prune blank lines off the
bottom.
This is a pretty simplistic brute force algorithm: each of the lines
will be visited and split, and for large scrollback buffers this could
be relatively costly with a busy live resize. We don't have much choice
in the current implementation.
refs: https://github.com/wez/wezterm/issues/14
`cargo run --example widgets_basic --features widgets` changes the
cursor style but wasn't changing it back when exiting.
In addition, setting the cursor to Default was only restoring visibility
and not restoring the style.
I was running `hg log --config pager.pager=sp` and pressing space without
releasing it. After about 10k lines sp appears to deadlock. It seems sp uses a
single thread for both reading terminal events and sending wake events and it
sends too many wake events without reading the events.
Failing to write to the wake pipe due to EWOULDBLOCK does not seem to be a
problem - there are enough events in the pipe to wake up the other side.
Therefore let's just make wake_pipe_write nonblocking and treat EWOULDBLOCK as
a success.
Context: The stuck thread looks like:
#0 0x00007f32671ee237 in write () from /usr/lib/libc.so.6
#1 0x000055c466022823 in std::sys::unix::fd::FileDesc::write () at src/libstd/sys/unix/fd.rs:96
#2 std::sys::unix::net::Socket::write () at src/libstd/sys/unix/net.rs:276
#3 <&std::sys::unix::ext::net::UnixStream as std::io::Write>::write ()
at src/libstd/sys/unix/ext/net.rs:597
#4 <std::sys::unix::ext::net::UnixStream as std::io::Write>::write ()
at src/libstd/sys/unix/ext/net.rs:582
#5 0x000055c465d010a6 in termwiz::terminal::unix::UnixTerminalWaker::wake (self=0x7ffe6bd32de0)
at /home/quark/.cargo/git/checkouts/wezterm-6425bab852909cc8/ef1b836/termwiz/src/terminal/unix.rs:278
#6 0x000055c465a6c64b in streampager::event::EventSender::send_unique (self=0x7ffe6bd32dd0, event=...,
unique=0x7ffe6bd32de8) at src/event.rs:66
#7 0x000055c465a7e65a in streampager::display::start (term=..., term_caps=..., events=..., files=...,
error_files=..., progress=..., mode=streampager::config::FullScreenMode::Auto) at src/display.rs:295
#8 0x000055c465a453a7 in streampager::Pager::run (self=...) at src/lib.rs:171
#9 0x000055c465a0aced in sp::open_files (args=...) at src/bin/sp/main.rs:170
#10 0x000055c465a08e4f in sp::main () at src/bin/sp/main.rs:25
This commit adds some plumbing for describing the cursor shape
(block, line, blinking etc) and visibility, and feeds that through
the mux and render layers.
The renderer now knows to omit the cursor when it is not visible.
This isn't complete but begins the process of extracting
the embedding application configuration into a trait provided
by the application rather than passing the values in at
construction.
This allows the application to change configuration at
runtime.
The first option to handle this is the scrollback size.
The defaults are pretty neutral. You can get a little more fancy
with something like this:
```
[colors.tab_bar]
background = "#0b0022"
[colors.tab_bar.active_tab]
bg_color = "#2b2042"
fg_color = "#c0c0c0"
[colors.tab_bar.inactive_tab]
bg_color = "#1b1032"
fg_color = "#808080"
[colors.tab_bar.inactive_tab_hover]
bg_color = "#3b3052"
fg_color = "#909090"
italic = true
```
This is a bit of a large commit because it needed some plumbing:
* Change mux creation to allow deferring associating any domains,
and to change the default domain later in the lifetime of the
program
* De-bounce the empty mux detection to allow for transient windows
during early startup
* Implement a bridge between the termwiz client Surface and the
frontend gui renderer so that we can render from termwiz to
the gui.
* Adjust the line editor logic so that the highlight_line method
can change the length of the output. This enables replacing
the input text with placeholders so that we can obscure password
input
I noticed while scrolling `emoji-test.txt` that some of the combined
emoji sequences rendered very poorly. This was due to the unicode
width being reported as up to 4 in some cases.
Digging into it, I discovered that the unicode width crate uses a
standard calculation that doesn't take emoji combination sequences
into account (see https://github.com/unicode-rs/unicode-width/issues/4).
This commit takes a dep on the xi-unicode crate as a lightweight way
to gain access to emoji tables and test whether a given grapheme is
part of a combining sequence of emoji.
I've noticed this off and on for a while, and thought it was something
fishy with my shell dotfiles.
Tracing through I found that the final byte in the "Face with head
bandage" emoji 🤕 U+1F915 was being interpreted as the MW control
code and causing the vt parser to jump out of the OSC state.
The solution for this is to hook up proper UTF-8 processing in the
same way that it is applied in the ground state.
Since we don't have enough bits to introduce new state values (we're
pretty tightly packed in the 16 bits available), I've introduced a
memory of the state to which the utf8 parser needs to return once
a complete sequence is detected.
I thought that I'd broken something with the DEL processing in vim with
the new frontend but it turned out that the other frontend was emitting
BS always and that I'd actuall unbroken passing DEL through and that
other layers were translating DEL into an application cursor mode output
for DEL that emits a totally different sequence.
This diff preserves DEL and disables that other sequence.
Will follow up with some explicit configuration to control this
behavior, but in the short term, the default behavior should be much
closer to what people actually want and expect!
refs: https://github.com/wez/wezterm/issues/52
This is still a bit rough because the terminal parser doesn't
understand the pixel sizes, so it relies on the hard coded
cell dimensions being accurate.
This enables using large OSC buffers in a form that we can publish
to crates.io without blocking on an external crate. Large OSC
buffers are important both for some tunnelling use cases and for
eg: iTerm2 image protocol handling.
Add a convenience function to the escape parser that, like `parse_first`,
matches only the first escape sequence, but instead collects all matching
actions.
It's taking a while for https://github.com/jwilm/vte/pull/20 to get
merged, so point to my branch directly while I build out some
tunneled mux protocol escape sequences.
I'll need to fork vte on crates.io if vte doesn't merge the PR
before the next termwiz crate bump.
The `flush_pending_attr` method does lots of unnecessary comparisons.
If the attributes have changed, then it works by resetting the
attributes and then setting new values. There's no need to emit the
codes for exiting modes.
It also doesn't support double underscore or rapid blink in the cases
where the terminfo capabilities are used, as these capabilities can't
express these attributes. Fall back to CSI sequences when these
attributes are requested.
Changing the terminal attributes (bold, underline, etc.) involves
emitting the `exit_attribute_mode` or SGR reset sequence. This also
resets the colors back to their defaults. If this happens when the
foreground or background colors haven't changed, set the colors again.
These codes are used to change the color palette, but if the `?`
string is used in place of a color spec, then we must respond with
the current color value string for that palette entry, so lets
implement that!
We need to set the terminal to blocking mode when we want poll_input
to block forever, otherwise we immediately receive WouldBlock error
response and quit the program.
This one has been bugging me for a while; we now know when we've
wrapped a line and can join it without a line break when double-clicking
to select a word.
This commit introduces a wrapped attribute to help record this
information, which could potentially help with when it comes
to looking at nicer resize behavior in refs: https://github.com/wez/wezterm/issues/14