2009-03-27 12 views
21

Il titolo è un po 'più specifico del mio vero obiettivo:Utilizzo di GNU Readline; come posso aggiungere ncurses nello stesso programma?

Ho un programma a riga di comando che utilizza GNU Readline, principalmente per la cronologia dei comandi (cioè recuperare i comandi precedenti usando la freccia su) e alcune altre sottigliezze. In questo momento l'output del programma appare inframmezzato dall'input dell'utente, che a volte va bene, ma l'uscita è asincrona (arriva tramite una connessione di rete in risposta ai comandi di input), e talvolta diventa fastidioso (ad esempio se le righe vengono emesse quando l'utente sta scrivendo un nuovo input).

Vorrei aggiungere una funzionalità a questo programma: una "finestra" separata per l'output. Ho pensato di usare ncurses per questo. Ma appare dal ncurses FAQ che le due librerie non sono facili da usare insieme.

Potrei considerare l'utilizzo di Editline o tecla invece di Readline, ma non mi è chiaro se uno di questi risolverà il mio problema. Prenderò in considerazione l'utilizzo di qualcosa di diverso da ncurses, inclusa una libreria che fornisce entrambi i tipi di funzionalità (finestre in modalità testo e cronologia dei comandi), ma non so quale potrebbe essere la soluzione migliore.

Oh, e il supporto per il testo colorato potrebbe ottenere punti bonus. Sospetto che potrei riuscire a farlo con Readline, quindi forse è una questione separata, ma se una soluzione al mio problema rende anche più facile aggiungere un po 'di colore all'output, tanto meglio.

Sto usando Ubuntu Hardy (Linux 2.6).

+0

Avete trovato una soluzione? –

+0

Mi sono arreso (e bloccato con readline). Lo slang –

risposta

6

Ho fatto qualche ricerca, e sembra che tu non abbia fortuna.

Per le alternative ncurses ci sono SLang, Newt e Turbo Vision. Lo slang è molto più della semplice gestione dello schermo e quindi più complesso , ma forse può essere usato per il tuo scopo ?. Newt utilizza la gestione dello schermo ed è molto più semplice, ma è troppo semplice e single-threaded-mode per il tuo scopo.

Turbo vision è la libreria grafica in modalità testo di Borland, utilizzata da tutti i loro strumenti alla fine degli anni '80/primi anni '90. Borland ha rilasciato il codice sorgente quando il mercato per quel genere di cose è diminuito, e c'è ora una porta per linux (nota a margine, this project sembra aver scritto la propria implementazione di visione turbo). Quella porta non è morta (ci sono stati aggiornamenti quest'anno che hanno compilato bene (le vecchie versioni no)), ma nessuno degli esempi TV che ho trovato erano aggiornati e io ne ho solo alcuni compilare prima di rinunciare al resto. Questo è un peccato, perché la TV era un ambiente piacevole da usare. TV è btw C++ (e presumo tu stia usando C?).

di un'alternativa al readline, c'è libkinput, che forse funziona insieme a ncurses (si dice che può usare terminfo ncurses'. Ma sono non so se questo significa che può coesiste insieme con l'uso ncurses)?

Forse un'opzione è di eseguire readline "esternamente" al programma ncurses utilizzando rlwrap?

+0

si rivela essere un linguaggio in sé. Inoltre è licenza GPL2 solo per l'ultima versione. Mi aspettavo che fosse una biblioteca. – matiu

+0

Nota che Newt è un livello su SLang. Potrebbe essere più facile da usare, ma è esattamente un'altra opzione. –

2

non sono sicuro quale versione hai provato. Ad oggi (2012.09.14) è molto semplice, abbiamo solo bisogno di agganciare la nostra funzione personalizzata ai seguenti puntatori di funzione.

 
rl_getch_function 
rl_redisplay_function 
rl_completion_display_matches_hook 

Ho fatto qualcosa di ragionevole here.

+0

Qualche idea su come far funzionare la storia? – nccc

+1

OK, l'ho scoperto. Uno deve mostrare 'rl_display_prompt', quindi' rl_line_buffer' e impostare l'offset del cursore su 'rl_point + strlen (rl_display_prompt)'. – nccc

5

Questo mi ha fatto sbattere la testa per un paio d'ore, quindi basta per salvare la gente Googling po 'di dolore:

Se si' utilizzando il gestore integrato di ncurses SIGWINCH con KEY_RESIZE, tenere presente che readline imposta le variabili di ambiente LINES e COLUMNS per impostazione predefinita. Questi sostituiscono qualsiasi calcolo di dimensioni dinamiche (di solito con ioctl()TIOCGWINSZ) che altrimenti farebbero ncurses, il che significa che continuerai ad ottenere le dimensioni iniziali del terminale anche dopo il ridimensionamento del terminale.

Questo può essere evitato impostando rl_change_environment su 0 prima di inizializzare readline.

Aggiornamento:

Ecco alcune informazioni aggiuntive ho spigolato dalle fonti readline:

SIGWINCH codice di gestione di readline (che viene utilizzato se rl_catch_sigwinch è 1) non aggiornamento LINES e COLUMNS, che sembra come esso dovrebbe essere sufficiente per ncurses. Tuttavia, quando si utilizza l'interfaccia di lettura alternativa (che ha più senso quando si combina readline con ncurses), i gestori di segnale (incluso quello per SIGWINCH) verranno installati solo per la durata di ciascuna chiamata rl_callback_read_char(), vale a dire qualsiasi ridimensionamento del terminale tra due chiamate a rl_callback_read_char() non verrà visualizzato da readline.

+1

Per favore considera [formattazione] (http://stackoverflow.com/help/formatting) la tua risposta. I comandi/codice sono difficili da leggere. – ryanyuyu

+1

@dotctor Grazie per aver formattato per me! – Ulfalizer

9

Ora ho creato un semplice programma di esempio su GitHub: https://github.com/ulfalizer/readline-and-ncurses.

Supporta il ridimensionamento dei terminali senza soluzione di continuità ed efficiente e caratteri multibyte/combinanti/ampi. Il codice ha commenti utili.

screenshot qui sotto:

Screenshot of program combining ncurses and readline

+0

Fantastico! Qual è la licenza del codice? Mi piacerebbe integrarlo con alcuni materiali con licenza MIT se possibile. Grazie! – cxw

+0

Felice che sia utile! Potrei metterlo sotto MIT se sarebbe il minimo problema. Sarei andato con ISC altrimenti, e il MIT sembra simile. Ho anche una versione che esegue un ciclo select() (o epoll() in questo caso) per https://github.com/ulfalizer/botniklas. Sono stato sviato e non l'ho ancora spinto, ma potrei fare un ramo per questo se tu fossi interessato. – Ulfalizer

+0

Questa versione installa un gestore SIGWINCH (sebbene utilizzi signalfd() invece di un gestore ordinario) e consente di leggere la lettura direttamente da stdin. Ciò accade anche per risolvere il problema con i caratteri di ricerca e multibyte. – Ulfalizer

Problemi correlati