2008-10-02 10 views
16

Meine Anwendung verfügt über eine Befehlszeilenschnittstelle, und ich denke über die GNU Readline library mit Geschichte zu liefern, um eine bearbeitbare Befehlszeile usw.Gibt es eine nette Möglichkeit, mehrzeilige Eingaben mit GNU readline zu verarbeiten?

Der Haken ist, dass meine Befehle ziemlich lang sein können und komplexe (man denke SQL) und ich möchte Benutzern erlauben, Befehle über mehrere Zeilen zu verteilen, um sie im Verlauf besser lesbar zu machen.

Ist es möglich, dies in readline (vielleicht durch Angabe eines Unterschieds zwischen einem Newline und einem Ende des Befehls) zu tun?

Oder wäre ich besser dran, meine eigene Befehlszeile zu implementieren (aber vielleicht mit der GNU History library)?

Antwort

16

Sie können sicher.

Sie können Optionen für die ‚\ r‘ und ‚\ n‘ Werte definieren mit

rl_bind_key('\r', return_func); 

Ihre return_func kann nun entscheiden, was mit diesen Schlüsseln zu tun.

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

Wenn Sie dies in einem UNIX-Terminal tun, müssen Sie über ANSI-Terminal-Codes lernen, wenn Sie um Ihren Cursor verschieben möchten. Es gibt eine starting reference auf Wikipedia.

Hier ist ein Beispielcode, der readline verwendet, um mehrzeilig zu lesen und die Bearbeitung stoppt, wenn Sie ein Semikolon eingeben (ich habe das als EOQ oder End-oder-Query festgelegt). Readline ist extrem mächtig, es gibt viel zu lernen.

#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); 
}