2009-03-27 16 views
21

Tytuł jest nieco bardziej konkretny niż mój faktyczny cel:Korzystanie z GNU Readline; jak mogę dodać ncurses w tym samym programie?

Mam program wiersza poleceń, który korzysta z Linuksa w Reado, głównie dla historii poleceń (tj. Pobieranie poprzednich poleceń za pomocą strzałki w górę) i kilka innych nicet. W tej chwili dane wyjściowe programu pojawiają się na przemian z danymi wejściowymi użytkownika, co czasami jest w porządku, ale dane wyjściowe są asynchroniczne (przychodzi przez połączenie sieciowe w odpowiedzi na polecenia wejściowe), co czasami staje się denerwujące (np. Jeśli linie są wyprowadzane, gdy użytkownik pisze nowe wejście).

Chciałbym dodać funkcję do tego programu: osobne "okno" dla wyjścia. Myślałem o tym, żeby użyć ncurses. Ale z pliku ncurses FAQ wynika, że ​​te dwie biblioteki nie są łatwe w użyciu.

Mogę rozważyć użycie Editline lub tecla zamiast Readline, ale nie jest dla mnie jasne, czy któreś z nich rozwiąże mój problem. Rozważę też użycie czegoś innego niż ncurses, w tym biblioteki, która zapewnia oba rodzaje funkcjonalności (okna tekstowe i historię poleceń), ale nie wiem, co może być najlepsze.

Aha, a obsługa kolorowego tekstu może uzyskać dodatkowe punkty. Podejrzewam, że mogę to zrobić z Readline, więc może to osobny problem, ale jeśli rozwiązanie mojego problemu również ułatwia dodanie nieco koloru do wyjścia, tym lepiej.

Używam Ubuntu Hardy (Linux 2.6).

+0

Znalazłeś rozwiązanie? –

+0

Poddałem się (i utknąłem z readline). –

Odpowiedz

6

Zrobiłem kilka wyszukiwania i wydaje się, że masz pecha.

Dla alternatywnych ncurses są SLang, Newt i Turbo Vision. Slang jest czymś więcej niż tylko obsługą ekranu, a więc bardziej złożonym, ale może może być użyty do twojego celu ?. Newt używa obsługi ekranu i jest znacznie prostszy, ale za prosty i jednotomowy.

Turbo vision to biblioteka graficzna w trybie tekstowym firmy Borland, używana przez wszystkie jej narzędzia w późnych latach 80. i wczesnych latach 90. XX wieku. Borland zwolnił kod źródłowy , gdy rynek tego typu rzeczy zmalał, a teraz jest teraz port dla Linuxa (uwaga boczna, this project, jak się wydaje, napisała swoją własną implementację turbo wizji). Ten port nie jest martwy (w tym roku zostały zaktualizowane niektóre aktualizacje cvs, które zostały skompilowane w porządku (wcześniejsze wersje: )), ale żaden z przykładów programów telewizyjnych, które znalazłem, nie był aktualny, a I zrobił tylko kilka z nich skompilować przed poddaniem się reszcie. To trochę szkoda, ponieważ telewizor był pięknym środowiskiem, z którego można korzystać. TV jest btw C++ (i zakładam, że używasz C?).

alternatywy dla readline, istnieje libkinput, który może działa wraz z ncurses (mówi to może użyć terminfo ncurses. Ale jestem nie wiem, czy to oznacza, że ​​może on współistnieje razem z wykorzystaniem ncurses)?

Być może jedną z opcji jest uruchomienie readline "zewnętrznie" do programu ncurses przy użyciu rlwrap?

+0

slang okazuje się być językiem samym w sobie. Również jest licencją GPL2 tylko dla najnowszej wersji. Spodziewałem się, że będzie to biblioteka. – matiu

+0

Należy zauważyć, że Newt jest warstwą nad SLangiem. Może być łatwiejszy w użyciu, ale jest to kolejna opcja. –

2

nie jestem pewien którą wersję wypróbowałeś. Na dzień dzisiejszy (2012.09.14) Jest to bardzo proste, wystarczy podpiąć naszą funkcję niestandardową do następujących wskaźników funkcji.

 
rl_getch_function 
rl_redisplay_function 
rl_completion_display_matches_hook 

Zrobiłem coś rozsądnego here.

+0

Jakieś pomysły na to, jak sprawić, żeby historia działała? – nccc

+1

OK, dowiedziałem się. Należy wyświetlić 'rl_display_prompt', następnie' rl_line_buffer' i ustawić offset kursora na 'rl_point + strlen (rl_display_prompt)'. – nccc

5

Miało mi walić głową przez kilka godzin, więc po prostu zapisać ludzie Googling trochę bólu:

Jeśli” Ponownie wykorzystaj wbudowaną obsługę ncurses SIGWINCH z KEY_RESIZE, należy pamiętać, że readline domyślnie ustawia zmienne środowiskowe LINES i COLUMNS. Zastępują one wszelkie obliczenia wielkości dynamicznej (zwykle z ioctl()TIOCGWINSZ), które w przeciwnym razie robiłby ncurures, co oznacza, że ​​otrzymasz początkowy rozmiar terminala nawet po zmianie rozmiaru terminalu.

Można temu zapobiec, ustawiając rl_change_environment na 0 przed inicjalizacją readline.

Aktualizacja:

Oto kilka dodatkowych informacji I zbierana ze źródeł readline:

readline za SIGWINCH obsługi kodu (który jest używany jeśli rl_catch_sigwinch jest 1) czy zmiana LINES i COLUMNS, co wydaje się podoba powinno wystarczyć dla ncurses. Jednak w przypadku używania alternatywnego interfejsu readline (co jest najbardziej sensowne przy łączeniu readline z ncurses), procedury obsługi sygnału (w tym jedna dla SIGWINCH) będą instalowane tylko na czas każdego połączenia rl_callback_read_char(), co oznacza, że ​​każda zmiana rozmiaru terminala między dwoma wywołaniami rl_callback_read_char() nie będzie widoczny przez readline.

+1

Proszę rozważyć [formatowanie] (http://stackoverflow.com/help/formatting) swoją odpowiedź. Polecenia/kod są trudne do odczytania. – ryanyuyu

+1

@dotctor Dzięki za sformatowanie go dla mnie! – Ulfalizer

9

Połączyłem prosty przykładowy program na GitHub: https://github.com/ulfalizer/readline-and-ncurses.

Obsługuje płynne i wydajne skalowanie terminali oraz wielobajtowe/kombinowane/szerokie znaki. Kod zawiera pomocne komentarze.

Zrzut ekranu poniżej:

Screenshot of program combining ncurses and readline

+0

Fantastyczne! Co to jest licencja na kod? Chciałbym w miarę możliwości zintegrować go z jakimś materiałem licencjonowanym na MIT. Dzięki! – cxw

+0

Cieszę się, że to pomocne! Mogłabym go umieścić w MIT, gdyby to było najmniej kłopotów. W innym przypadku byłbym z ISC, a MIT wygląda podobnie. Mam również wersję, która uruchamia pętlę select() (lub epoll() w tym przypadku) nawiasem mówiąc, dla https://github.com/ulfalizer/botniklas. Zjechałem na boczny tor i nie pchnąłem go jeszcze, ale mógłbym zrobić dla niego gałąź, gdybyś był zainteresowany. – Ulfalizer

+0

Ta wersja instaluje program obsługi SIGWINCH (chociaż używa on metody signalfd() zamiast zwykłego programu obsługi) i pozwala readline czytać bezpośrednio ze standardowego wejścia. To także rozwiązuje problem z wyszukiwaniem i znakami wielobajtowymi. – Ulfalizer