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.