diff options
author | Gregory Anders <8965202+gpanders@users.noreply.github.com> | 2024-07-21 21:47:37 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-21 21:47:37 -0500 |
commit | f93ecd2760f5859fd5eeec28c7c2196ece98e9a1 (patch) | |
tree | d481d1220ebe4196ef754352272b25fd618dd77a /src/nvim | |
parent | 7381f0a1d517474dcf8d8d019cbda430ce4bff23 (diff) | |
download | rneovim-f93ecd2760f5859fd5eeec28c7c2196ece98e9a1.tar.gz rneovim-f93ecd2760f5859fd5eeec28c7c2196ece98e9a1.tar.bz2 rneovim-f93ecd2760f5859fd5eeec28c7c2196ece98e9a1.zip |
feat(tui): parse CSI subparams in termkey (#29805)
libtermkey does not know how to parse CSI subparameters (parameters
separated by ':', ASCII 0x3A) and currently just ignores them. However,
many important CSI sequences sent by the terminal make use of
subparameters, most notably key events when using the kitty keyboard
protocol [1]. Enabling subparameters is a prerequisite for expanding
kitty keyboard protocol support in Neovim.
Concretely, we do this by returning pointers into the internal termkey
buffer for each CSI parameter rather than parsing them into integers
directly. When a caller wants to actually use the parameter as an
integer, they must call termkey_interpret_csi_param, which parses the
full parameter string into an integer parameter and zero or more
subparameters.
The pointers into the internal buffer will become invalidated when new
input arrives from the terminal so it is important that the individual
params are used and parsed right away. All of our code (and libtermkey's
code) does this, so this is fine for now, but is something to keep in
mind moving forward.
[1]: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
Diffstat (limited to 'src/nvim')
-rw-r--r-- | src/nvim/tui/input.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 9f58607bf7..a6e27c9391 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -596,10 +596,10 @@ static void handle_unknown_csi(TermInput *input, const TermKeyKey *key) { // There is no specified limit on the number of parameters a CSI sequence can // contain, so just allocate enough space for a large upper bound - long args[16]; - size_t nargs = 16; + TermKeyCsiParam params[16]; + size_t nparams = 16; unsigned long cmd; - if (termkey_interpret_csi(input->tk, key, args, &nargs, &cmd) != TERMKEY_RES_KEY) { + if (termkey_interpret_csi(input->tk, key, params, &nparams, &cmd) != TERMKEY_RES_KEY) { return; } @@ -639,12 +639,22 @@ static void handle_unknown_csi(TermInput *input, const TermKeyKey *key) } break; case 't': - if (nargs == 5 && args[0] == 48) { - // In-band resize event (DEC private mode 2048) - int height_chars = (int)args[1]; - int width_chars = (int)args[2]; - tui_set_size(input->tui_data, width_chars, height_chars); - ui_client_set_size(width_chars, height_chars); + if (nparams == 5) { + // We only care about the first 3 parameters, and we ignore subparameters + long args[3]; + for (size_t i = 0; i < ARRAY_SIZE(args); i++) { + if (termkey_interpret_csi_param(params[i], &args[i], NULL, NULL) != TERMKEY_RES_KEY) { + return; + } + } + + if (args[0] == 48) { + // In-band resize event (DEC private mode 2048) + int height_chars = (int)args[1]; + int width_chars = (int)args[2]; + tui_set_size(input->tui_data, width_chars, height_chars); + ui_client_set_size(width_chars, height_chars); + } } break; default: |