Nitty-gritty questions on terminal nvim and keyboard events

I’m a user who has been trying to move from VimR to terminal nvim (via kitty). My main reason for this is to have access to dev builds of nvim, and also for kitty’s extraordinary performance.

However, I’ve found that the terminal’s “different” handling of keyboard events has caused many of my mappings to not work, specifically for:

  • D- mappings (i.e. command key on macOS)
  • function key mappings higher than F12
  • some modified function key mappings (e.g. <M-F1>, <C-F1>)

I understand that these are known issues and also occur in other terminal programs. The general issues around “exotic” key-chords and terminals are well-explained here. I have also been able to work around some of the issues by adding a translation layer that converts unsupported chords to specially-prefixed sequences, described in this SO answer. I’m not particularly satisfied with my solution, and am hoping for a day when all my mappings that work in VimR work identically in terminal nvim.

I went looking through nvim issues and found several that discuss various terminal keyboard issues and possible solutions. Here’s a sample:

However, my understanding of nvim specifics as well as terminal keyboard mechanics in general is very fuzzy. I find it hard to follow the discussions in these issues. I’m creating this thread in hopes that it can become a general reference for n00bs like me trying to plan for, understand, and/or work around these issues.

Here are some specific questions:

(1) In the post Fix Keyboard Input on Terminals - Please, author Leonerd suggests using his library libtickit to make things “just work”. AFAICT libtickit is the successor to libtermkey, also AFAICT nvim still uses the deprecated libtermkey.

Does nvim plan to switch to libtickit, and if it did would it make terminal keystrokes function straightforwardly?

(2) I can view the sequences generated by keystrokes in kitty using kitty +kitten show_key. This shows that kitty generates distinct escape sequences for, say, <F9> and <C-F9>. Also, I know that neovim can distinguish between <F9> and <C-F9> because I have separate mappings for these that work in VimR. But in terminal nvim, <C-F9> doesn’t work.

If kitty is sending a unique escape sequence for <C-F9>, and nvim recognizes <C-F9> in a GUI context, why doesn’t it recognize it in the terminal?

(3) Various “special” keys have distinct byte representations in neovim that you can see with, e.g. :echo "\<DEL>", which prints <80>kD. But the escape sequence sent by kitty when pressing delete (using kitty +kitten show_key) is \x1b[3~. And if I map another key in kitty to send the apparent byte representation of <DEL>, \x80kD, it does not trigger a delete. So there is some layer that translates the escape sequences generated by the terminal into Vim’s internal representation of special keys.

What is this layer, and how can I see the escape sequence that Vim will map to a particular special key? e.g. Is there any way to learn within Vim that it will interpret \x1b[3~ as <DEL>?

(4) I am hopelessly confused about the viable range of function keys:

  • The terminfo for Kitty generates has entries for function keys up through F63 (infocmp -a xterm-kitty).
  • My keyboard provides up to F24. The Karabiner event viewer confirms that keystrokes up to F24 are detected. But only up to F20 seem to be registered by kitty (print a unique code with kitty +kitten show_key).
  • In Neovim, up to F37 (:echo "\<F37>") is a specially recognized key. But in VimR, only my mappings up to F19 work. In terminal nvim, only my mappings up to F12 work.
  • I read somewhere that shift+F1-F12 is the same as F13-F24, but my mappings have no problem distinguishing these in VimR.

Why does the number of supported function keys vary so wildly by context? What is the maximum function key supported by Neovim-- F19, F37, something else?

(5) There is apparently a terminal feature called ModifyOtherKeys that is part of xterm. This enables modified chords that don’t map to any unique ASCII code to be distinguished from their unmodified forms, e.g. <C-.> to be distinguished from .. According to this issue, Neovim supports this but users have to enable it explicitly. Vim has a doc section that explains this, but there is no corresponding section in the Neovim docs.

Does NeoVim support ModifyOtherKeys? Is it off by default? If it is, how do I turn it on, and how would this affect the key chords that can be distinguished in the terminal?

Thank you!


If kitty is sending a unique escape sequence for <C-F9> , and nvim recognizes <C-F9> in a GUI context, why doesn’t it recognize it in the terminal?

This may be a terminfo problem. It is recognized as <F33> in Nvim. Related:

My 2 cents:

  • libtickit/libtermkey should not be supported. It is not a well-enough defined specification for two people to implement it similarly.
  • modifyOtherKeys (either mode 1 or 2) is useful and adds a bunch of missing functionality. neovim should support it, ideally enabling it automatically. Both vim and emacs have this behavior.