TERMKEY_GETKEY(3)

🌸 TERMKEY_GETKEY 🌸

okay bestie, we're doing termkey_getkey and termkey_getkey_force today, and honestly? iconic. these two live in termkey(3) and their whole job is handing you the next key event. no cap. let's get into it πŸ’…


✨ SYNOPSIS ✨

#include <termkey.h>

TermKeyResult termkey_getkey(TermKey *tk, TermKeyKey *key);
TermKeyResult termkey_getkey_force(TermKey *tk, TermKeyKey *key);

Link with -ltermkey.


πŸ’– DESCRIPTION πŸ’–

so termkey_getkey() is the main character here 🫢 β€” it tries to pull one single keypress event out of the termkey(7) instance buffer and tuck it into the structure that key points at. cute, right?

and then it returns one of these lil guys, so listen up πŸŽ€:

  • TERMKEY_RES_KEY β€” yesss, a complete keypress got yeeted out of the buffer and is now sitting in the key structure. we ate. πŸ”₯
  • TERMKEY_RES_AGAIN β€” hmm, there's a partial keypress event in the buffer but it doesn't have all the bytes it needs yet 😭. and bestie, it also drops a lil preview of what termkey_getkey_force() would return right into the key structure. foreshadowing, honestly.
  • TERMKEY_RES_NONE β€” the buffer is empty. nothing. zero. nada. ghost town πŸ’€
  • TERMKEY_RES_EOF β€” no bytes are ready and the input stream is closed now. it's over. πŸ™ˆ
  • TERMKEY_RES_ERROR β€” you called this while terminal IO was stopped, because of termkey_stop(3). and in that case errno gets set to EINVAL. so check it, bestie 🫢

now termkey_getkey_force() is like termkey_getkey()'s chaotic older sister β€” it's similar, but it will NOT return TERMKEY_RES_AGAIN if it finds a partial match. instead it just forces an interpretation of the bytes πŸ’…. and yes, that means it might read the start of an Escape-prefixed multi-byte sequence as a literal Escape key followed by normal letters. that's the tradeoff. periodt.

🚨 neither of these functions will block or do any IO operations on the underlying filehandle. so don't come for them for that.

okay so what do you do instead, you ask? slay, glad you asked:

and before it returns, this function canonicalises the key structure according to the rules given for termkey_canonicalise(3). so it comes out all neat and pretty. the way that it just... tidies up. obsessed 🌸


πŸ‘‘ RETURN VALUE πŸ‘‘

termkey_getkey() returns an enumeration of one of TERMKEY_RES_KEY, TEMRKEY_RES_AGAIN, TERMKEY_RES_NONE, TERMKEY_RES_EOF or TERMKEY_RES_ERROR.

termkey_getkey_force() returns one of the above too, except for TERMKEY_RES_AGAIN. she simply refuses. πŸ’…


🌈 EXAMPLE 🌈

this lil program prints the deets of every keypress until you hit Ctrl-C. it's showing off how to use the termkey instance in a typical poll(2)-driven asynchronous program, which may also include mixed IO with other file handles. multi-tasking queen πŸ‘‘

// <poll.h> might need this for sigset_t
#define _XOPEN_SOURCE 600

#include <poll.h>
#include <stdio.h>

#include "termkey.h"

static void on_key(TermKey *tk, TermKeyKey *key)
{
  char buffer[50];
  termkey_strfkey(tk, buffer, sizeof buffer, key, TERMKEY_FORMAT_VIM);
  printf("%s\n", buffer);
}

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

  TermKey *tk = termkey_new(0, 0);

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

  struct pollfd fd;

  fd.fd = 0; /* the file descriptor we passed to termkey_new() */
  fd.events = POLLIN;

  TermKeyResult ret;
  TermKeyKey key;

  int running = 1;
  int nextwait = -1;

  while(running) {
    if(poll(&fd, 1, nextwait) == 0) {
      // Timed out
      if(termkey_getkey_force(tk, &key) == TERMKEY_RES_KEY)
        on_key(tk, &key);
    }

    if(fd.revents & (POLLIN|POLLHUP|POLLERR))
      termkey_advisereadable(tk);

    while((ret = termkey_getkey(tk, &key)) == TERMKEY_RES_KEY) {
      on_key(tk, &key);

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

    if(ret == TERMKEY_RES_AGAIN)
      nextwait = termkey_get_waittime(tk);
    else
      nextwait = -1;
  }

  termkey_destroy(tk);
}

πŸ¦‹ SEE ALSO πŸ¦‹

termkey_advisereadable(3), termkey_waitkey(3), termkey_get_waittime(3), termkey(7)


and that's the whole page bestie!! πŸ’œ this was TERMKEY_GETKEY(3), and yeah β€” that's literally the name stamped at the top and the bottom, she's consistent like that πŸ‘‘βœ¨ go forth and read them keys, iykyk πŸŽ€πŸ’–