5

Vim by default maps <F1> to bring up help. I'd like to map <S-F1> (shift + F1) to close the help using the :helpclose command.

I'm having trouble with this simple task, running inside a Gnome terminal (v 3.30.2 according to Help/About).

First, I start vim with vim -u NONE. I use ^V to show the sequences generated from <F1> and <S-F1>:

Press F1:  ^[OP
Press S-F1: ^[[1;2P
~
~
~

I then ask Vim about <F1> using:

:set <F1>?

it replies:

t_k1 <F1>        ^[OP

So apparently we are on the same page for <F1>. And it works! If I press <F1> I get a help split.

Then I ask vim about <S-F1> in the same way, and it says,

E846: Key code not set: <S-F1>?

Then I ask about all the keys with :set termcap and I get a bunch of info, including all the unshifted F-keys, but no shifted keys.

Determined to continue anyway, I choose to tell vim about what my terminal does (square brackets are keys I press, spaces added here for clarity):

:set <S-F1>= [Ctrl-V] [Shift-F1]
:set <S-F1>=^[[1;2P [Enter]

Then when I ask again, I get the expected answer?

:set <S-F1>?
     <S-F1>      ^[[1;2P

Finally, I try something super basic:

:map <S-F1> :echomsg "Shift Eff One!"<CR>

When I press <S-F1> in my empty window in normal mode, I get:

E353: Nothing in register "

I suspect that this is because I haven't deleted or yanked anything, and my escape sequence "...P" is trying to paste. Which means that my keystroke mapping didn't work.

What am I doing wrong?

2
  • 2
    Interesting. It looks like there's something different about F1 through F4 versus F5 and up in VT100 terminal emulation... Some terminals prefer to encode Home, End and the F1 to F4 function keys using shorter CSI letter encodings (Try <S-F5> ... it should work for you if your system is like mine.) Hopefully, someone can shed some better light on this.
    – B Layer
    Commented Dec 11, 2021 at 22:08
  • 1
    I tried this on Fedora 34 (Gnome Terminal 3.40, a recent vim 8.2) and had no trouble creating the mapping for <S-F1> after setting the escape sequence for it. One thing to watch out is that ^[ is actually the Esc character. Your post describes the right sequence to get this right, so I'm guessing that's not why it didn't work for you... Still, you could use an alternative approach such as :execute "set <S-F1>=\e[1;2P" which doesn't depend on the special character and might work better in a vimrc file, for instance...
    – filbranden
    Commented Dec 12, 2021 at 4:22

2 Answers 2

1

Unless vim is configured, e.g., in your .vimrc, it will not have a setting for the shifted function keys. That is because vim uses

  • the termcap capabilities (which do not define any shifted function-keys), or
  • vim's built-in termcap-like settings.

For the latter, that starts with the builtin_xterm table in term.c, which does not have any of the shifted-keys, e.g., K_S_F1. But vim has other tables, such as modifier_keys_table, in misc2.c, which it uses for managing its information on shifted keys. When you define S-F1, it is using that table.

The termcap (very likely using terminfo) for xterm has definitions for the shifted function-keys as F13-F24. Vim does not associate F13-F24 as shifted versions of F1-F12. The modifier_keys_table keeps those two ranges of function-keys separate.

Further reading:

1

I can reproduce that (bug?). A non-recursive map works though.

:noremap <S-F1> :echomsg "Shift Eff One!"<CR>
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.