mirror of
https://github.com/neovim/neovim.git
synced 2025-10-01 07:28:34 +00:00
tui: check stty/termios for kbs
Requires libtermkey 0.19+ Closes #2048 Closes #5693 Seea9b61424aa
%5E...c0eb4e4a05f49ad8fee0195c77f2c29d09cc36af See https://bugzilla.redhat.com/show_bug.cgi?id=142659 Seefe4e9470bb/tty-keys.c (L625-L632)
This commit is contained in:
@@ -39,8 +39,6 @@ static int events_enabled = 0;
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "os/input.c.generated.h"
|
||||
#endif
|
||||
// Helper function used to push bytes from the 'event' key sequence partially
|
||||
// between calls to os_inchar when maxlen < 3
|
||||
|
||||
void input_init(void)
|
||||
{
|
||||
@@ -389,6 +387,8 @@ static void process_interrupts(void)
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function used to push bytes from the 'event' key sequence partially
|
||||
// between calls to os_inchar when maxlen < 3
|
||||
static int push_event_key(uint8_t *buf, int maxlen)
|
||||
{
|
||||
static const uint8_t key[3] = { K_SPECIAL, KS_EXTRA, KE_EVENT };
|
||||
|
@@ -32,7 +32,14 @@ void term_input_init(TermInput *input, Loop *loop)
|
||||
term = ""; // termkey_new_abstract assumes non-null (#2745)
|
||||
}
|
||||
|
||||
#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
|
||||
input->tk = termkey_new_abstract(term,
|
||||
TERMKEY_FLAG_UTF8 | TERMKEY_FLAG_NOSTART);
|
||||
termkey_hook_terminfo_getstr(input->tk, input->tk_ti_hook_fn, NULL);
|
||||
termkey_start(input->tk);
|
||||
#else
|
||||
input->tk = termkey_new_abstract(term, TERMKEY_FLAG_UTF8);
|
||||
#endif
|
||||
|
||||
int curflags = termkey_get_canonflags(input->tk);
|
||||
termkey_set_canonflags(input->tk, curflags | TERMKEY_CANON_DELBS);
|
||||
|
@@ -12,6 +12,7 @@ typedef struct term_input {
|
||||
bool paste_enabled;
|
||||
bool waiting;
|
||||
TermKey *tk;
|
||||
TermKey_Terminfo_Getstr_Hook *tk_ti_hook_fn; ///< libtermkey terminfo hook
|
||||
TimeWatcher timer_handle;
|
||||
Loop *loop;
|
||||
Stream read_stream;
|
||||
|
@@ -7,9 +7,13 @@
|
||||
|
||||
#include <uv.h>
|
||||
#include <unibilium.h>
|
||||
#if defined(HAVE_TERMIOS_H)
|
||||
# include <termios.h>
|
||||
#endif
|
||||
|
||||
#include "nvim/lib/kvec.h"
|
||||
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/ui.h"
|
||||
@@ -195,6 +199,9 @@ static void tui_terminal_start(UI *ui)
|
||||
terminfo_start(ui);
|
||||
update_size(ui);
|
||||
signal_watcher_start(&data->winch_handle, sigwinch_cb, SIGWINCH);
|
||||
|
||||
data->input.tk_ti_hook_fn = tui_tk_ti_getstr;
|
||||
term_input_init(&data->input, data->loop);
|
||||
term_input_start(&data->input);
|
||||
}
|
||||
|
||||
@@ -227,8 +234,6 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
|
||||
signal_watcher_init(data->loop, &data->winch_handle, ui);
|
||||
signal_watcher_init(data->loop, &data->cont_handle, data);
|
||||
signal_watcher_start(&data->cont_handle, sigcont_cb, SIGCONT);
|
||||
// initialize input reading structures
|
||||
term_input_init(&data->input, &tui_loop);
|
||||
tui_terminal_start(ui);
|
||||
data->stop = false;
|
||||
// allow the main thread to continue, we are ready to start handling UI
|
||||
@@ -957,3 +962,50 @@ static void flush_buf(UI *ui, bool toggle_cursor)
|
||||
unibi_out(ui, unibi_cursor_invisible);
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to get "kbs" code from stty because "the terminfo kbs entry is extremely
|
||||
/// unreliable." (Vim, Bash, and tmux also do this.)
|
||||
///
|
||||
/// @see tmux/tty-keys.c fe4e9470bb504357d073320f5d305b22663ee3fd
|
||||
/// @see https://bugzilla.redhat.com/show_bug.cgi?id=142659
|
||||
static const char *tui_get_stty_erase(void)
|
||||
{
|
||||
static char stty_erase[2] = { 0 };
|
||||
#if defined(ECHOE) && defined(ICANON) \
|
||||
&& (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H))
|
||||
struct termios t;
|
||||
if (tcgetattr(input_global_fd(), &t) != -1) {
|
||||
stty_erase[0] = (char)t.c_cc[VERASE];
|
||||
stty_erase[1] = '\0';
|
||||
ILOG("stty/termios:erase=%s", stty_erase);
|
||||
}
|
||||
#endif
|
||||
return stty_erase;
|
||||
}
|
||||
|
||||
/// libtermkey hook to override terminfo entries.
|
||||
/// @see TermInput.tk_ti_hook_fn
|
||||
static const char *tui_tk_ti_getstr(const char *name, const char *value,
|
||||
void *data)
|
||||
{
|
||||
static const char *stty_erase = NULL;
|
||||
if (stty_erase == NULL) {
|
||||
stty_erase = tui_get_stty_erase();
|
||||
}
|
||||
|
||||
if (strcmp(name, "key_backspace") == 0) {
|
||||
ILOG("libtermkey:kbs=%s", value);
|
||||
if (stty_erase != NULL && stty_erase[0] != 0) {
|
||||
return stty_erase;
|
||||
}
|
||||
} else if (strcmp(name, "key_dc") == 0) {
|
||||
ILOG("libtermkey:kdch1=%s", value);
|
||||
// Vim: "If <BS> and <DEL> are now the same, redefine <DEL>."
|
||||
if (stty_erase != NULL && strcmp(stty_erase, value) == 0) {
|
||||
return stty_erase[0] == DEL ? (char *)CTRL_H_STR : (char *)DEL_STR;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user