views:

515

answers:

2

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)?

+4  A: 

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 here on wikipedia

[http://en.wikipedia.org/wiki/ANSI_escape_code#Codes][1]

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);
}
Phil
A: 

Just want to leave a note about a non-GPL library that have similare functionality as GNU readline

Project tecla

epatel
On that note, libedit (http://www.thrysoee.dk/editline/) is a BSD-licensed library with similar functionality and APIs as libreadline.
DGentry