TERMKEY(7)
π TERMKEY(7) π
Hiii bestie, welcome to TERMKEY(7) from the Miscellaneous Information Manual β it's the manual page for termkey, and no cap, this one is a whole journey. Grab a snack, we're doing this in two parts because there is so much tea to spill. ββ¨
π NAME π
termkey β terminal keypress reading library
π¦ DESCRIPTION π¦
Okay so, termkey</p> is a library that lets your program read and interpret keypress and other events from a terminal. The way that it understands the encoding schemes terminals use to encode keypresses, and UTF-8 too, so it can hand you back actual events that represent key events? Iconic. Obsessed. π
termkey operates in a pseudo object-oriented fashion. It gives you exactly one function, termkey_new(3), that returns a pointer to a newly-allocated structure. Every other function takes that pointer as its first argument β that's the whole bit, that pointer is your instance, she's the main character. π
A typical use of this library would be: call termkey_new() to construct a new instance representing the stdin stream, then use termkey_waitkey(3) to wait for and interpret key press events. And when your program is done with her, termkey_destroy(3) deallocates all the resources the instance was using. Clean exit, slay. β¨
π Reading Events π
Each instance of a termkey structure can be used by the program in one of three ways:
- Synchronously β blocking to wait for keypresses from a filehandle.
- Asynchronously β returning keypresses if they're available, while co-operating with a non-blocking program.
- Abstractly β interpreting key press bytes fed to it directly by the containing program.
To get the next key event synchronously, a program may call termkey_waitkey(3). She'll either return an event from the internal buffer, or block until a key is available, returning it the moment it's ready. It behaves similarly to getc(3), fgetc(3), or similar β except it understands and returns entire key press events rather than single bytes. Fr fr, glow-up of the century. π
To work with an asynchronous program, you use two other functions:
termkey_advisereadable(3)β tells atermkeyinstance that more bytes of input may be available from its file handle, so it should callread(2)to go get them.termkey_getkey(3)β the program can then call this to extract key press events out of the internal buffer, in a way similar totermkey_waitkey().
And finally, bytes of input can be fed directly into the termkey instance by calling termkey_push_bytes(3). This may be useful if the bytes have already been read from the terminal by the application, or even in situations that don't directly involve a terminal filehandle at all. Because of these situations, it's possible to construct a termkey instance not associated with a file handle, by passing -1 as the file descriptor. Yes, -1. She's unbothered, she's free. π¦
A termkey instance contains a buffer of pending bytes that have been read but not yet consumed by termkey_getkey(3). Here's the buffer squad:
termkey_get_buffer_remaining(3)β returns the number of bytes of buffer space currently free in the instance.termkey_set_buffer_size(3)andtermkey_get_buffer_size(3)β used to control and return the total size of this buffer.
π Key Events π
Key events are stored in structures. Each structure holds details of one key event. This structure is defined as follows:
typedef struct {
TermKeyType type;
union {
long codepoint; /* TERMKEY_TYPE_UNICODE */
int number; /* TERMKEY_TYPE_FUNCTION */
TermKeySym sym; /* TERMKEY_TYPE_KEYSYM */
} code;
int modifiers;
char utf8[7];
} TermKeyKey;
The type field indicates the type of event, and it's the one that decides which member of the code union is valid. It'll be one of these constants, and every single one of them matters, so here's the full roster:
TERMKEY_TYPE_UNICODEβ a Unicode codepoint. This value indicates thatcode.codepointis valid, and will contain the codepoint number of the keypress. In Unicode mode (if theTERMKEY_FLAG_UTF8bit is set) this will be its Unicode character number. In raw byte mode, this will contain a single 8-bit byte.TERMKEY_TYPE_FUNCTIONβ a numbered function key. This value indicates thatcode.numberis valid, and contains the number of the numbered function key.TERMKEY_TYPE_KEYSYMβ a symbolic key. This value indicates thatcode.symis valid, and contains the symbolic key value.TERMKEY_TYPE_MOUSEβ a mouse button press, release, or movement. Thecodestructure should be considered opaque;termkey_interpret_mouse(3)may be used to interpret it.TERMKEY_TYPE_POSITIONβ a cursor position report. Thecodestructure should be considered opaque;termkey_interpret_position(3)may be used to interpret it.TERMKEY_TYPE_MODEREPORTβ an ANSI or DEC mode value report. Thecodestructure should be considered opaque;termkey_interpret_modereport(3)may be used to interpret it.TERMKEY_TYPE_DCSβ a DCS sequence including its terminator. Thecodestructure should be considered opaque;termkey_interpret_string(3)may be used to interpret it.TERMKEY_TYPE_OSCβ a OSC sequence including its terminator. Thecodestructure should be considered opaque;termkey_interpret_string(3)may be used to interpret it.TERMKEY_TYPE_UNKNOWN_CSIβ an unrecognised CSI sequence. Thecodestructure should be considered opaque;termkey_interpret_csi(3)may be used to interpret it.
The modifiers bitmask is composed of a bitwise-or of the constants TERMKEY_KEYMOD_SHIFT, TERMKEY_KEYMOD_CTRL and TERMKEY_KEYMOD_ALT. π«Ά
The utf8 field is only set on events whose type is TERMKEY_TYPE_UNICODE. Do not read it for other events, bestie, I'm begging. π
Key events that represent special keys (type is TERMKEY_TYPE_KEYSYM) have with them a symbolic value that identifies the special key, in code.sym. Two helpers for that:
termkey_get_keyname(3)β turn this symbolic value into a string.termkey_lookup_keyname(3)β turn string names into symbolic values.
A pair of functions is also provided to convert between key events and strings:
termkey_strfkey(3)β converts a key event into a string.termkey_strpkey(3)β parses a string, turning it into a key event.
And key events may be compared for equality or ordering by using termkey_keycmp(3). πΈ
ποΈ Control Flags ποΈ
Details of the behaviour of a termkey instance are controlled by two bitmasks of flags. Here's who does what:
termkey_set_flags(3)andtermkey_get_flags(3)β set or return the flags used to control the general behaviour.termkey_set_canonflags(3)andtermkey_get_canonflags(3)β set or return the flags that control the key value canonicalisation behaviour performed bytermkey_canonicalise(3).
The following control flags are recognised. All of them. Every single one. π
TERMKEY_FLAG_NOINTERPRETβ Do not attempt to interpret C0 codes into keysyms. Instead report them as plain Ctrl-letter events.TERMKEY_FLAG_CONVERTKPβ Convert xterm's alternative keypad symbols into the plain ASCII codes they would represent.TERMKEY_FLAG_RAWβ Ignore locale settings; do not attempt to recombine UTF-8 sequences. Instead report only raw values.TERMKEY_FLAG_UTF8β Ignore locale settings; force UTF-8 recombining on. This flag overridesTERMKEY_FLAG_RAW.TERMKEY_FLAG_NOTERMIOSβ Even if the terminal file descriptorfdrepresents a TTY device, do not call thetcsetattr(3)termios function on it to set it to canonical input mode.TERMKEY_FLAG_SPACESYMBOLβ Report space as being a symbolic key rather than a Unicode codepoint. Setting or clearing this flag in fact sets or clears theTERMKEY_CANON_SPACESYMBOLcanonicalisation flag.TERMKEY_FLAG_CTRLCβ Disable theSIGINTbehaviour of Ctrl-C. If this flag is provided, then Ctrl-C will be available as a normal keypress, rather than sending the process group aSIGINT. This flag only takes effect withoutTERMKEY_FLAG_NOTERMIOS; with it, none of the signal keys are disabled anyway.TERMKEY_FLAG_EINTRβ Without this flag, IO operations are retried when interrupted by a signal (EINTR). With this flag theTERMKEY_RES_ERRORresult is returned instead.TERMKEY_FLAG_NOSTARTβ This flag is only meaningful to the constructor functionstermkey_new(3)andtermkey_new_abstract(3). If set, the constructor will not calltermkey_start(3)as part of the construction process. The user must call that at some future time before the instance will be usable.
The following canonicalisation flags are recognised:
TERMKEY_CANON_SPACESYMBOLβ If this flag is set then a Unicode space character is represented using theTERMKEY_SYM_SPACEsymbol. If this flag is not set, it is represented by theU+0020Unicode codepoint.TERMKEY_CANON_DELBSβ If this flag is set then an ASCII DEL character is represented by theTERMKEY_SYM_BACKSPACEsymbol. If not, it is represented byTERMKEY_SYM_DEL. An ASCII BS character is always represented byTERMKEY_SYM_BACKSPACE, regardless of this flag. No cap. π«Ά
π§ Multi-byte Events π§
Special keys, mouse events, and UTF-8 encoded Unicode text are all represented by more than one byte. So if the start of a multi-byte sequence is seen by termkey_waitkey(), it will wait a short time to see if the remainder of the sequence arrives. And if the sequence remains unfinished after this timeout, it will be returned in its incomplete state. Here's how the leftovers show up:
- Partial escape sequences are returned as an Escape key (
TERMKEY_SYM_ESCAPE) followed by the text contained in the sequence. - Partial UTF-8 sequences are returned as the Unicode replacement character,
U+FFFD.
The amount of time the termkey instance will wait is set by termkey_set_waittime(3), and is returned by termkey_get_waittime(3). Initially it will be set to 50 miliseconds. (Yes, that's exactly how the page spells it, and I'm keeping it character for character because that's the rule π)
π Mouse Events π
The TERMKEY_TYPE_MOUSE event type indicates a mouse event. The code field of the event structure should be considered opaque, though modifiers will be valid. In order to obtain the details of the mouse event, call termkey_interpret_mouse(3) passing the event structure and pointers to integers to store the result in. π«Ά
termkey recognises three mouse protocols:
- the original X10 protocol (
CSI Mfollowed by three bytes), - SGR encoding (
CSI < ... M, as requested byCSI ? 1006 h), - and rxvt encoding (
CSI ... M, as requested byCSI ? 1015 h).
Which encoding is in use is inferred automatically by termkey, and does not need to be specified explicitly. She just knows. π
β¨
okay bestie that's part 1 β part 2 is coming, don't go anywhere π
π Position Events π
okay so when you get a TERMKEY_TYPE_POSITION event, that's your terminal telling you where the cursor is at. slay β¨ it's basically the terminal answering back β usually because you asked it with the Report Cursor Position command, which is CSI ? 6 n.
the event bytes themselves are opaque (mysterious, iconic, we don't peek π), but you can get the actual goods by calling termkey_interpret_position(3) β just hand it the event structure plus pointers to integers where you want the result stashed. easy π
real talk though bestie: only a DEC CPR sequence (CSI ? R) gets recognised here. the non-DEC prefixedCSI Rdoes not count, and that's on purpose β because that one could literally be read as the F3 function key instead. so like, careful π«Ά
πΈ Mode Reports πΈ
TERMKEY_TYPE_MODEREPORT is the vibe when your terminal sends back an ANSI or DEC mode report. it's typically what you get in response to the Request Mode command β either CSI $p or CSI ? $p, depending on which flavour we're talking.
same deal as before: the event bytes are opaque, no cap π«₯, but you can pull the info out by calling termkey_interpret_modereport(3) and passing the event structure along with pointers to integers to store the result in. yes bestie, pointers to integers, you got this πͺ
π¦ Control Strings π¦
now TERMKEY_TYPE_DCS and TERMKEY_TYPE_OSC are the two event types for a DCS or an OSC control string. these usually show up when your terminal is responding to similar kinds of strings that the application sent out as queries β like, you asked, it answered, we love a two-way conversation π¬
the event bytes are opaque again (as per usual, the drama π), but the body of the string itself? that you can grab by calling termkey_interpret_string(3) immediately after this event lands.
β οΈ and this part is so important: the underlying termkey instance can only hold one pending string at a time. so you gotta call that function in a timely manner β soon after the event arrives. at the very least, before you call any other functions that will insert bytes into or remove key events from the instance. don't let it get overwritten, queen ππ
π Unrecognised CSIs π
TERMKEY_TYPE_UNKNOWN_CSI means the termkey ran into a CSI sequence it just... does not recognise. rude of it, honestly. π€ it has been extracted from the stream though, so it's still available for you to inspect by calling termkey_interpret_csi(3).
but listen: if you wanna look at that sequence, you do it immediately β before any other IO operations on the termkey instance. and yes, specifically before calling termkey_waitkey() or termkey_getkey() again. otherwise the buffer space that sequence is chilling in gets overwritten and it's gone forever, no cap π
the good news? other types of key event don't have this problem at all π because the TermKeyKey structure is enough to hold all the information required. so it's just this one diva of an event type that needs the special treatment β¨
β SEE ALSO β
and that's the whole page bestie!! π«Ά this was the TERMKEY(7) manual page, section 7, and that little footer down at the bottom is just its name sitting pretty β TERMKEY(7). go forth and handle your key events, main character πππ§
π¦ where this page comes from
- alpine 3.24: libtermkey-doc 0.22-r4 Β· MIT
- debian trixie: libtermkey-dev 0.22-2+b1 Β· MIT
- epel 10: libtermkey-devel 0.22-2.el10_0 Β· MIT
- epel 9: libtermkey-devel 0.22-2.el9 Β· MIT
- fedora 43: libtermkey-devel 0.22-11.fc43 Β· MIT
- fedora 43: libtermkey-devel 0.22-11.fc43 Β· MIT
- fedora 44: libtermkey-devel 0.22-12.fc44 Β· MIT
- fedora 44: libtermkey-devel 0.22-12.fc44 Β· MIT
- nixos 26.05: libtermkey 0.22
- nixpkgs unstable: libtermkey 0.22
- opensuse-leap 16.0: libtermkey-devel 0.22-bp160.1.11 Β· MIT
- opensuse-leap 16.0: libtermkey-devel 0.22-bp160.1.11 Β· MIT
- opensuse-leap 16.0: libtermkey-devel 0.22-bp160.1.11 Β· MIT
- opensuse-leap 16.0: libtermkey-devel 0.22-bp160.1.11 Β· MIT
- ubuntu questing: libtermkey-dev 0.22-2
- ubuntu resolute: libtermkey-dev 0.22-2build1 Β· MIT
- ubuntu stonking: libtermkey-dev 0.22-3 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms