TERMKEY_WAITKEY(3)

✨ NAME ✨

termkey_waitkey β€” bestie just sits there, waits for the next key event, and hands it to you πŸ’…


✨ SYNOPSIS ✨

#include <termkey.h>

TermKeyResult termkey_waitkey(TermKey *tk, TermKeyKey *key);

Link with -ltermkey.


🌸 DESCRIPTION 🌸

okay so termkey_waitkey() is doing the most: it tries to grab a single keypress event out of the termkey(7) instance buffer and drop it into the structure that key points at. If it pulls that off, it returns TERMKEY_RES_KEY, which is the lil "yay, your struct has a brand new keypress event in it now" signal πŸ’–

If the buffer is giving absolutely nothing, it will block until something shows up. Like it will literally just stand there. Patient queen. πŸ‘‘

But if no events are ready and the input stream has closed, it returns TERMKEY_RES_EOF. And if there's no filehandle attached to this instance at all, you get TERMKEY_RES_ERROR back with errno set to EBADF. Rude, but fair.

Before it returns anything, this function canonicalises the key structure according to the rules laid out in termkey_canonicalise(3). Canonicalise before you hand it over, that's the rule ✨

So here's a thing: some keypresses make the terminal spit out multiple bytes. And because there can be network delays or whatever else between the terminal and your app, termkey_waitkey() will try to wait for the rest of the bytes to show up if it detects the start of a multibyte sequence. But β€” and this is the important part β€” if no more bytes arrive within a certain time, then the bytes get reported as they stand, even if that means interpreting a partially-complete Escape sequence as a literal Escape key followed by some normal letters or other symbols. 😭 The amount of time it's willing to wait can be set with termkey_set_waittime(3).


πŸ”₯ RETURN VALUE πŸ”₯

termkey_waitkey() returns one of these constants, no cap:

  • TERMKEY_RES_KEY β€” a key event has been provided. slay, you got one πŸ’–
  • TERMKEY_RES_EOF β€” no key events are ready and the terminal has been closed, so no more will arrive. that's it, that's the end 🫢
  • TERMKEY_RES_ERROR β€” an IO error occurred, and errno will be preserved. But listen: if the error is EINTR, this only gets returned when the TERMKEY_FLAG_EINTR flag is not set. If that flag is set, the IO operation gets retried instead. And if this is called while terminal IO is stopped β€” like, because of termkey_stop(3) β€” then errno will be set to EINVAL. noted. πŸ’€

πŸ¦‹ EXAMPLE πŸ¦‹

This lil example program prints the details of every single keypress until you hit Ctrl-C. iconic behaviour honestly:

// we want optarg
#define _XOPEN_SOURCE 600

#include <stdio.h>
#include <unistd.h>
#include <errno.h>

#include "termkey.h"

int main(int argc, char *argv[])
{
  TERMKEY_CHECK_VERSION;

  int mouse = 0;
  int mouse_proto = 0;
  TermKeyFormat format = TERMKEY_FORMAT_VIM;

  char buffer[50];
  TermKey *tk;

  int opt;
  while((opt = getopt(argc, argv, "m::p:")) != -1) {
    switch(opt) {
    case 'm':
      if(optarg)
        mouse = atoi(optarg);
      else
        mouse = 1000;

      break;

    case 'p':
      mouse_proto = atoi(optarg);
      break;

    default:
      fprintf(stderr, "Usage: %s [-m]\n", argv[0]);
      return 1;
    }
  }

  tk = termkey_new(0, TERMKEY_FLAG_SPACESYMBOL|TERMKEY_FLAG_CTRLC);

  if(!tk) {
    fprintf(stderr, "Cannot allocate termkey instance\n");
    exit(1);
  }

  if(termkey_get_flags(tk) & TERMKEY_FLAG_UTF8)
    printf("Termkey in UTF-8 mode\n");
  else if(termkey_get_flags(tk) & TERMKEY_FLAG_RAW)
    printf("Termkey in RAW mode\n");

  TermKeyResult ret;
  TermKeyKey key;

  if(mouse) {
    printf("\033[?%dhMouse mode active\n", mouse);
    if(mouse_proto)
      printf("\033[?%dh", mouse_proto);
  }

  while((ret = termkey_waitkey(tk, &key)) != TERMKEY_RES_EOF) {
    if(ret == TERMKEY_RES_KEY) {
      termkey_strfkey(tk, buffer, sizeof buffer, &key, format);
      if(key.type == TERMKEY_TYPE_MOUSE) {
        int line, col;
        termkey_interpret_mouse(tk, &key, NULL, NULL, &line, &col);
        printf("%s at line=%d, col=%d\n", buffer, line, col);
      }
      else if(key.type == TERMKEY_TYPE_POSITION) {
        int line, col;
        termkey_interpret_position(tk, &key, &line, &col);
        printf("Cursor position report at line=%d, col=%d\n", line, col);
      }
      else if(key.type == TERMKEY_TYPE_MODEREPORT) {
        int initial, mode, value;
        termkey_interpret_modereport(tk, &key, &initial, &mode, &value);
        printf("Mode report %s mode %d = %d\n", initial ? "DEC" : "ANSI", mode, value);
      }
      else if(key.type == TERMKEY_TYPE_UNKNOWN_CSI) {
        long args[16];
        size_t nargs = 16;
        unsigned long command;
        termkey_interpret_csi(tk, &key, args, &nargs, &command);
        printf("Unrecognised CSI %c %ld;%ld %c%c\n", (char)(command >> 8), args[0], args[1], (char)(command >> 16), (char)command);
      }
      else {
        printf("Key %s\n", buffer);
      }

      if(key.type == TERMKEY_TYPE_UNICODE &&
         key.modifiers & TERMKEY_KEYMOD_CTRL &&
         (key.code.codepoint == 'C' || key.code.codepoint == 'c'))
        break;

      if(key.type == TERMKEY_TYPE_UNICODE &&
         key.modifiers == 0 &&
         key.code.codepoint == '?') {
        // printf("\033[?6n"); // DECDSR 6 == request cursor position
        printf("\033[?1$p"); // DECRQM == request mode, DEC origin mode
        fflush(stdout);
      }
    }
    else if(ret == TERMKEY_RES_ERROR) {
      if(errno != EINTR) {
        perror("termkey_waitkey");
        break;
      }
      printf("Interrupted by signal\n");
    }
  }

  if(mouse)
    printf("\033[?%dlMouse mode deactivated\n", mouse);

  termkey_destroy(tk);
}

πŸ’€ COMPATIBILITY πŸ’€

This function is not available on Windows. sorry bestie, Windows girlies are on their own here πŸ™ˆ


🌈 SEE ALSO 🌈

termkey_getkey(3), termkey_set_waittime(3), termkey(7)


and that's the whole page, bestie πŸŽ€ this was TERMKEY_WAITKEY(3) from the Library Functions Manual β€” no version number or date was given on it, so we're keeping it mysterious 🧚 go forth and read those keys πŸ‘‘πŸ’–