Ensure we ignore SIGHUP once the TerminalUI is gone as it will be
sent again on fork, fix the parent process terminating due to trying
to write to stdout after it was closed.
Fixes#4960
Normally page-down is sent as \033[6~ but some terminals
send a CSI u encoding for the page-down on the numpad. See
https://codeberg.org/dnkl/foot#keypad for example.
Treat them as the underlying key; we could add a modifier if anyone
cares about the distinction.
When Kakoune's terminal is shown on my laptop monitor and I plug
in my external monitor, the terminal's workspace will move to that
external monitor. When this happens, Kakoune may segfault.
There are multiple resize events (SIGWINCH) in quick succession;
it crashes because we handle SIGWINCH during rendering.
The problem happens during execution of "TerminalUI::Screen::output"
(frame #18). When we receive SIGWINCH while writing to stdout, write(2)
fails with EAGAIN, prompting us to handle pending events (See ae001a1f9
(Run EventManager whenever writing to a file descriptor would block,
2022-05-10)). We update the screen size in check_resize() here:
#4 Kakoune::TerminalUI::check_resize (force=<optimized out>) at terminal_ui.cc:683
#5 Kakoune::TerminalUI::get_next_key () at terminal_ui.cc:719
#6 operator() (__closure=0x555555984198) at terminal_ui.cc:484
#7 std::__invoke_impl<void, Kakoune::TerminalUI::TerminalUI()::<lambda(Kakoune::FDWatcher&, Kakoune::FdEvents, Kakoune::EventMode)>&, Kakoune::FDWatcher&, Kakoune::FdEvents, Kakoune::EventMode> (__f=...) at /usr/include/c++/12.2.1/bits/invoke.h:61
#8 std::__invoke_r<void, Kakoune::TerminalUI::TerminalUI()::<lambda(Kakoune::FDWatcher&, Kakoune::FdEvents, Kakoune::EventMode)>&, Kakoune::FDWatcher&, Kakoune::FdEvents, Kakoune::EventMode> (__fn=...) at /usr/include/c++/12.2.1/bits/invoke.h:111
#9 std::_Function_handler<void(Kakoune::FDWatcher&, Kakoune::FdEvents, Kakoune::EventMode), Kakoune::TerminalUI::TerminalUI()::<lambda(Kakoune::FDWatcher&, Kakoune::FdEvents, Kakoune::EventMode)> >::_M_invoke(const std::_Any_data &, Kakoune::FDWatcher &, Kakoune::FdEvents &&, Kakoune::EventMode &&) (__functor=..., __args#0=..., __args#1=<optimized out>, __args#2=<optimized out>) at /usr/include/c++/12.2.1/bits/std_function.h:290
#10 std::function<void (Kakoune::FDWatcher&, Kakoune::FdEvents, Kakoune::EventMode)>::operator()(Kakoune::FDWatcher&, Kakoune::FdEvents, Kakoune::EventMode) const (__args#2=<optimized out>, __args#1=<optimized out>, __args#0=...) at /usr/include/c++/12.2.1/bits/std_function.h:591
#11 Kakoune::FDWatcher::run (mode=Kakoune::EventMode::Urgent, events=<optimized out>) at event_manager.cc:28
#12 Kakoune::EventManager::handle_next_events (mode=mode@entry=Kakoune::EventMode::Urgent, sigmask=sigmask@entry=0x0, block=<optimized out>, block@entry=false) at event_manager.cc:143
#13 Kakoune::write (fd=1, data=...) at file.cc:273
#14 Kakoune::BufferedWriter<4096>::flush () at string.hh:236
#15 Kakoune::BufferedWriter<4096>::write (data="t file.hh:145
#16 Kakoune::TerminalUI::Screen::set_face (face=..., writer=...) at terminal_ui.cc:255
#17 operator() (line=..., __closure=<synthetic pointer>) at terminal_ui.cc:326
#18 Kakoune::TerminalUI::Screen::output (force=force@entry=true, synchronized=<optimized out>, writer=...) at terminal_ui.cc:402
#19 Kakoune::TerminalUI::redraw (force=force@entry=true) at terminal_ui.cc:571
#20 Kakoune::TerminalUI::refresh (force=<optimized out>) at terminal_ui.cc:592
#21 Kakoune::Client::redraw_ifn () at client.cc:282
#22 Kakoune::ClientManager::redraw_clients () at client_manager.cc:232
#23 Kakoune::run_server (session=..., server_init=..., client_init=..., init_buffer="fish-rust/src/ast.rs", init_coord=..., flags=Kakoune::ServerFlags::None, ui_type=Kakoune::UIType::Terminal,
debug_flags=<optimized out>, files=ArrayView<Kakoune::StringView> = {...}) at main.cc:893
#24 main (argc=<optimized out>, argv=<optimized out>) at main.cc:1243
Thereafter, "TerminalUI::Screen::output" resumes and crashes due to
a buffer overflow in "lines" which has been resized.
Handle begin/end paste directly in paste csi, manage paste buffer
out of get_char, filter Key::Invalid earlier.
get_next_key returning Key::Invalid means there was some input but
it could not be represented as a Key. An empty optional means there
was no input at all.
Text pasted into Kakoune's normal mode is interpreted as command
sequence, which is probably never what the user wants. Text
pasted during insert mode will be inserted fine but may trigger
auto-indentation hooks which is likely not what users want.
Bracketed paste is pair of escape codes sent by terminals that allow
applications to distinguish between pasted text and typed text.
Let's use this feature to always insert pasted text verbatim, skipping
keymap lookup and the InsertChar hook. In future, we could add a
dedicated Paste hook.
We need to make a decision on whether to paste before or after the
selection. I chose "before" because that's what I'm used to.
TerminalUI::set_on_key has
EventManager::instance().force_signal(0);
I'm not sure if we want the same for TerminalUI::set_on_paste?
I assume it doesn't matter because they are always called in tandem.
Closes#2465
Some plugins (*cough* kak-lsp) and help texts tend to have immensely long content
in a single line. This generates info boxes that span the entire terminal width.
This is made especially worse on widescreen monitors or at small text size.
This grants user control over how wide these boxes are.
I deliberately avoid pushing this change to `kak-lsp` because it's not the only
plugin that this could help--see the `hook` help text for an example of this
problem in vanilla Kakoune. I would also suggest that since this is a rendering
concern, it be handled by the terminal rendering logic.
Enable it if supported by default, let the user override it with
the existing terminal_synchronized ui option.
This should finalize work discussed on #4317
Just validate if line changed or not. This should avoid flickering
on terminals such as the linux console that eagerly redraw on line
deletions. Unfortunately this means drawing will use more data and
might add a bit of latency on slow links.
Fixes#4317Fixes#4320
Add support for a third color in face definition that controls
the underline and a 'c' attribute for curly underline (that takes
precedence over 'u' if both are specified)
Allow empty colors to mean default, so that `,,red+u` means the
same as `default,default,red+u`
Fixes#4138
Display a whitespace in place of the uncovered half of the codepoint.
(I know this is incorrect and we should be considering grapheme clusters
instead of codepoints, but this is a far bigger refactoring and another
can of worms to handle with terminal emulators).
Fixes#4262
Synchronized output does not work well with various terminals
(including the linux console). It should also be unnecessary when
not going through a slow link.
This will eventually be removed if it is not proven to be useful
to some users.
TerminalUI::suspend() is responsible for undoing all Kakoune's modifications to
the terminal state, actually suspending the process, then re-applying all the
modifications after Kakoune wakes back up.
Previously, the "undo" and "reapply" steps for termios settings were both after
the suspend point, so on some platforms they were incorrect when the user
arrived back at the shell prompt.
Now, the termios "undo" step is back before the suspend point, and the undo and
reapply steps should be in exactly reversed order.
Fixes#3488.
In terminals that support it, this sequence causes the terminal to not redraw
*its* output until the application has finished, reducing redraw flickering.
The sequence is defined in:
https://gitlab.com/gnachman/iterm2/-/wikis/synchronized-updates-spec
...and is apparently also supported by kitty and libVTE.
Fixes#3482.
insert blank seems to behave differently between terminals and would
be less efficient because it still has to shift all following characters
(that we will overwrite anyway).
Fixes#3437