ncurses trapping extended keys (Control-left, Shift-Function etc)
I am trying to trap Control-Left, Shift-F10 etc in my ruby programs. Normally, using just getch I get a list of ints such as 27,91,50,50,126 which works. However I fear these may be system or terminal dependent. After googling I found about use_extended_names, tigetstr etc. I found a C program using these which discovers the keycodes at run time (by Thomas Dickey). I run it and it seems to discover extended keys, but then the getch in the same program still gives me the usual list of ints such as [27,91,53,68] for C-left which I am getting anyway. I expect to get one return value, the one it mentions.
What am i missing ?
Here is the output when I press Control-left:
keypress=27
keypress=91
keypress=53
keypress=68
key=kLFT5, code=540
key=kEND5, code=525
key=kHOM5, code=530
key=kHOM3, code=528
key=kUP5, code=561
key=kDN5, code=520
Should I not get just 540 ?
Here is keytest.c : https://gist.github.com/1237091
Strangely, a开发者_高级运维ll the codes show 0 when running under TERM=screen. The above is TERM=xterm. (I am on OSX using Terminal)
ncurses by itself does not know about the control-, shift-, meta- and alt-modifiers because it only knows about characters. Modifiers are something that particular terminals know about. Some terminals can encode keyboard modifiers in the characters which they send to the host. xterm, for instance can do this.
terminfo (and termcap) have predefined lists of special keys (such as cursor-keys, function-keys), including a small number of modified special keys (such as shifted right arrow). The predefined keys have well-defined names in the terminal description as well as KEY_
xxx names in the curses.h
header. ncurses provides two ways to extend these lists of special keys
- the
-x
option of tic with the corresponding use_extended_names function (which defines a name for a given input string). - the define_key function (which assigns a code to be returned by getch for a given input string).
The ncurses terminal database provides the most useful definitions for modified special keys, focusing on the cursor-keys and editing-keypad. There are a few issues with this:
- the terminal database does not provide all definitions because portable terminfo definitions are limited to 4096 bytes. If there were no limit on size, then conceivably one could generate complete tables for each of the (literally) thousands of combinations of xterm's keyboard-related resource-settings.
- some terminals which set
TERM
toxterm
do not send the same strings as xterm. (In fact, most differ, though a few are subsets rather than simply differing). - for the example given, the string in terminfo would be
\E[5D
, which does not appear to be one of xterm's. (OP indicated that this is OSX Terminal, from a few years ago -- each release of OSX includes changes to Terminal, but no release of OSX Terminal yet matches xterm exactly). The reason why it does not appear to be xterm's is that the modifier (5) appears in the first position rather than in the second. xterm deprecated that in 2002 (patch #167). - function-keys are mentioned in the question without specifics. The convention used in ncurses is to assign the (almost standard) 12 PC-keyboard function keys with the 4 most useful combinations of shift- and control-modifiers to obtain 48 function keys. There are 60 predefined function keys in terminfo; when there are additional well-known strings for those, the remaining dozen are filled in up to the limit.
So much for making predefined tables using terminfo (with the problems of size and terminals which pretend to be something different). The define_key
function has no limit on size, and has long been available to applications which have specialized needs. For instance, one could use it to build a table by merging the most common variants of the most common terminals.
Curses was designed at a time before people were really doing modifiers in terminals. Its key handling model is effectively a flat enumeration of values, and doesn't easily handle arbitrary key + modifier combinations.
To solve this better, I wrote libtermkey, you may be more luck using this instead.
http://www.leonerd.org.uk/code/libtermkey/
It's a C library, though it has both Perl and Python bindings. I'd imagine someone ought to be able to build some Ruby bindings quite easily for it as well.
精彩评论