2

I'm new to GNU Readline, so I want to know if there exist a function that can cancel readline() request?

Ikbel
  • 7,721
  • 3
  • 34
  • 45
  • 2
    Well since the `readline` function is *blocking*, not really. You might be able to do it using multiple threads and sending an interrupt to the terminal. Also, can you please elaborate on *why* you want to "cancel" the function? – Some programmer dude Dec 26 '14 at 20:43

1 Answers1

5

To do this, you'll have to use the alternate (or "callback") interface to readline. There is actually no need to cancel anything, you just (temporarily) step out of the loop around rl_callback_read_char to do whatever needs to be done. This can even happen before the user has sent an ENTER, but only after a keypress.

#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>

void line_handler(char *line) { /* This function (callback) gets called by readline                    
                                   whenever rl_callback_read_char sees an ENTER */
  printf("%s? Hah!!\n", line);
}

int main() {
  rl_callback_handler_install("Ask a question: ", &line_handler);

  while (1) {
    rl_callback_read_char();
    if (strstr(rl_line_buffer, "you")) { /* They're asking about *me* =:-0 */
      printf("\nNo personal questions please! Goodbye!\n");
      break;
      /* or make a snarky remark and continue */
    }
  }
}

If you want to "cancel" without a keypress, you'll have to interrupt the read() syscall inside the rl_callback_read_char() using a signal (e.g. by setting an alarm()). Be aware, however, that readline installs its own signal handlers.

A slightly more sophisticated method would be to insert into the loop a select() on two file descriptors, stdin and e.g. a pipe (the self-pipe trick), to use this second descriptor (and/or a timeout) to "wake up" the select(), and then step out of the loop just like in the example below..

Hans Lub
  • 5,513
  • 1
  • 23
  • 43