2009-03-27 15 views
21

Der Titel ist ein bisschen genauer als mein eigentliches Ziel:Verwenden von GNU Readline; Wie kann ich Ncurses im selben Programm hinzufügen?

Ich habe ein Befehlszeilenprogramm, das GNU Readline, in erster Linie für Befehlsverlauf (d. H. Abruf früherer Befehle mit Pfeil nach oben) und einige andere Nettigkeiten. Zurzeit erscheint die Ausgabe des Programms durchsetzt mit der Benutzereingabe, die manchmal in Ordnung ist, aber die Ausgabe asynchron ist (sie kommt über eine Netzwerkverbindung als Antwort auf die Eingabebefehle), und das wird manchmal ärgerlich (zB wenn Zeilen beim Benutzer ausgegeben werden) tippt neue Eingabe).

Ich möchte eine Funktion zu diesem Programm hinzufügen: ein separates "Fenster" für die Ausgabe. Ich habe darüber nachgedacht, ncurses zu verwenden. Aber es scheint aus dem ncurses FAQ, dass die beiden Bibliotheken nicht einfach zusammen zu verwenden sind.

Ich könnte in Betracht ziehen, Editline oder tecla statt Readline zu verwenden, aber es ist mir nicht klar, wenn einer von denen mein Problem lösen wird. Ich würde auch in Erwägung ziehen, etwas anderes als ncurses zu verwenden, einschließlich einer Bibliothek, die beide Arten von Funktionen bietet (Textmodusfenster und Befehlsverlauf), aber ich weiß nicht, was am besten ist.

Oh, und Unterstützung für farbigen Text könnte Bonuspunkte erhalten. Ich vermute, dass ich das vielleicht mit Readline machen kann, also vielleicht ist es ein separates Problem, aber wenn eine Lösung für mein Problem es auch leicht macht, der Ausgabe etwas Farbe hinzuzufügen, umso besser.

Ich benutze Ubuntu Hardy (Linux 2.6).

+0

Haben Sie eine Lösung gefunden? –

+0

Ich gab auf (und blieb bei readline). –

Antwort

6

Ich habe etwas gesucht, und es scheint, als ob Sie kein Glück haben.

Für ncurses Alternativen gibt es SLang, und Turbo Vision. Slang ist viel mehr als nur Bildschirm Handhabung und somit mehr komplex, aber vielleicht kann es für Ihren Zweck verwendet werden. Newt verwendet den Bildschirm Handhabung und ist viel einfacher, aber zu einfach und Single-Thread-Modus für Ihren Zweck, denke ich.

Turbo Vision ist die Text-Modus-Grafik-Bibliothek von Borland, verwendet von alle ihre Werkzeuge in den späten 80er/frühen 90er Jahren. Borland veröffentlichte die Quelle Code, wenn der Markt für diese Art von Sache verringert, und es gibt jetzt einen Port für Linux (Randnotiz, this project scheint seine eigene Turbo-Vision-Implementierung geschrieben zu haben). Dieser Port ist nicht tot (es gab einige cvs Updates in diesem Jahr, die gut zusammengestellt (die älteren Releases nicht)), aber keine der TV-Beispiele, die ich fand, waren auf dem neuesten Stand und ich habe nur ein paar von ihnen vor dem Aufgeben auf den Rest kompilieren. Das ist ein bisschen eine Schande, denn TV war eine schöne Umgebung zu benutzen. TV ist übrigens C++ (und ich nehme an, Sie verwenden C?).

Für eine Alternative zu readline gibt libkinput ist, die mit ncurses zusammen vielleicht funktioniert (es sagt, es term ncurses verwenden können. Aber ich bin nicht sicher, ob das bedeutet, dass es existiert zusammen mit ncurses Nutzung zusammen können)

Vielleicht ist eine Option, Readline "extern" zu Ihrem ncurses Programm mit rlwrap zu führen?

+0

Slang erweist sich als eine Sprache an sich. Auch ist es GPL2-Lizenz nur für die neueste Version. Ich habe erwartet, dass es eine Bibliothek ist. – matiu

+0

Beachten Sie, dass Newt eine Ebene über SLang ist. Es kann einfacher zu verwenden sein, aber es ist genau eine andere Option. –

2

Ich bin nicht sicher welche Version du ausprobiert hast. Ab heute (2012.09.14) Es ist sehr einfach, wir müssen nur unsere benutzerdefinierte Funktion an folgende Funktionszeiger hängen.

 
rl_getch_function 
rl_redisplay_function 
rl_completion_display_matches_hook 

Ich tat etwas Vernünftiges here.

+0

Irgendwelche Ideen, wie man auch Geschichte arbeiten lässt? – nccc

+1

OK, ich habe es herausgefunden. Man muss 'rl_display_prompt', dann' rl_line_buffer' anzeigen und den Cursor-Offset auf 'rl_point + strlen (rl_display_prompt)' setzen. – nccc

5

Das hatte mich für ein paar Stunden den Kopf hämmern, so dass nur einige Schmerzen, Menschen zu retten Googeln:

Wenn Sie‘ Verwenden Sie den integrierten SIGWINCH Handler von ncurses mit KEY_RESIZE, beachten Sie, dass readline standardmäßig die Umgebungsvariablen LINES und COLUMNS einstellt. Diese überschreiben jede dynamische Größenberechnung (normalerweise mit ioctl()TIOCGWINSZ), die ncurses sonst tun würde, was bedeutet, dass Sie auch nach der Größenänderung des Terminals die anfängliche Terminalgröße erhalten.

Dies kann verhindert werden, indem vor der Initialisierung von readline rl_change_environment auf gesetzt wird.

Update:

Hier einige zusätzliche Informationen, die ich aus den Readline- Quellen entnommen:

Readline- des SIGWINCH Behandlungs-Code (die, wenn rl_catch_sigwinch verwendet wird, 1) nicht aktualisiert LINES und COLUMNS, die wie es scheint sollte für ncurses ausreichen. Bei Verwendung der alternativen readline-Schnittstelle (was am sinnvollsten ist, wenn readline mit ncurses kombiniert wird), werden die Signalhandler (einschließlich der für SIGWINCH) nur für die Dauer jedes rl_callback_read_char()-Aufrufs installiert, was bedeutet, dass die Terminalgröße zwischen zwei Aufrufen geändert wird rl_callback_read_char() wird von readline nicht gesehen.

+1

Bitte beachten Sie [Formatierung] (http://stackoverflow.com/help/formatting) Ihre Antwort. Die Befehle/Code sind schwer zu lesen. – ryanyuyu

+1

@dotctor Danke für die Formatierung für mich! – Ulfalizer

9

Ich habe jetzt ein einfaches Beispielprogramm auf GitHub zusammengestellt: https://github.com/ulfalizer/readline-and-ncurses.

Es unterstützt nahtlose und effiziente Terminal-Größenanpassung und Multibyte/Kombination/Wide Zeichen. Der Code enthält hilfreiche Kommentare.

Screenshot unten:

Screenshot of program combining ncurses and readline

+0

Fantastisch! Was ist die Code-Lizenz? Ich würde es gerne mit etwas MIT-lizenziertem Material integrieren, wenn möglich. Vielen Dank! – cxw

+0

Froh, dass es hilfreich ist! Ich könnte es MIT unterstellen, wenn das der geringste Aufwand wäre. Ich wäre sonst mit ISC gegangen, und MIT sieht ähnlich aus. Ich habe auch eine Version, die neben einer select() Schleife (oder in diesem Fall epoll() in diesem Fall) für https://github.com/ululfizer/botniklas läuft. Habe abgelenkt und habe es noch nicht gedrängt, aber ich könnte einen Zweig dafür machen, wenn es dich interessiert. – Ulfalizer

+0

Diese Version installiert einen SIGWINCH-Handler (obwohl signalfd() anstelle eines gewöhnlichen Handlers verwendet wird) und ermöglicht es Readline, direkt von stdin zu lesen. Das behebt das Problem auch mit Such- und Multibyte-Zeichen. – Ulfalizer