Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a nice way of handling multi-line input with GNU readline?

My application has a command line interface, and I'm thinking about using the GNU Readline library to provide history, an editable command line, etc.

The hitch is that my commands can be quite long and complex (think SQL) and I'd like to allow users to spread commands over multiple lines to make them more readable in the history.

Is it possible to do this in readline (maybe by specifying a difference between a newline and an end of command)?

Or would I be better off implementing my own command line (but maybe using the GNU History library)?

like image 860
John Carter Avatar asked Oct 02 '08 09:10

John Carter


People also ask

How to read in multiple lines in java?

Another way to read multiple lines from the console can be done using the synchronized BufferedReader class in Java. The idea is to read each line using the readLine() method and use String. split() to split the line into individual tokens using whitespace as a delimiter. We can also use the StringTokenizer class.

How does GNU readline work?

It allows users to move the text cursor, search the command history, control a kill ring (a more flexible version of a copy/paste clipboard) and use tab completion on a text terminal. As a cross-platform library, readline allows applications on various systems to exhibit identical line-editing behavior.

How does readline work in C?

readline will read a line from the terminal and return it, using prompt as a prompt. If prompt is NULL or the empty string, no prompt is issued. The line returned is allocated with malloc(3); the caller must free it when finished. The line returned has the final newline removed, so only the text of the line remains.

What is readline support?

7.9 Readline Support This makes interactive use much more convenient, because of the command-line editing features of readline. Using (ice-9 readline) , you can navigate through the current input line with the cursor keys, retrieve older command lines from the input history and even search through the history entries.


1 Answers

You sure can.

You can define options for the '\r' and '\n' values with

rl_bind_key('\r', return_func);

Your return_func can now decide what to do with those keys.

int return_func(int cnt, int key) { ... }

If you're doing this inside a UNIX terminal, you will need to learn about ANSI terminal codes if you want to move your cursor around. There's a starting reference on wikipedia.

Here's some sample code that uses readline to read multi-line and will stop editing when you enter in a semi-colon (I've set that as the EOQ or end-or-query). Readline is extremely powerful, there's plenty of stuff to learn.

#include <stdio.h>
#include <unistd.h>
#include <readline/readline.h>
#include <readline/history.h>

int my_startup(void);
int my_bind_cr(int, int);
int my_bind_eoq(int, int);
char *my_readline(void);

int my_eoq; 

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

  if (isatty(STDIN_FILENO)) {
    rl_readline_name = "my";
    rl_startup_hook = my_startup;
    my_readline();
  }
}

int
my_startup(void) 
{
  my_eoq = 0;
  rl_bind_key('\n', my_bind_cr);
  rl_bind_key('\r', my_bind_cr);
  rl_bind_key(';', my_bind_eoq);
}

int
my_bind_cr(int count, int key) {
  if (my_eoq == 1) {
    rl_done = 1;
  }
  printf("\n");
}

int
my_bind_eoq(int count, int key) {
  my_eoq = 1;

  printf(";");
}

char * 
my_readline(void)
{
  char *line;

  if ((line = readline("")) == NULL) {
    return NULL;
  }

  printf("LINE : %s\n", line);
}
like image 179
Philip Reynolds Avatar answered Oct 24 '22 15:10

Philip Reynolds