2009-03-27 4 views
21

Названия является немного более конкретным, чем моей фактической цель:Использование GNU Readline; как я могу добавить ncurses в ту же программу?

У меня есть программа командной строки, которая использует GNU Readline, в первую очередь для истории команд (то есть получение предыдущих команд, используя стрелок вверх) и некоторые другие тонкости. Прямо сейчас выход программы появляется в чередовании с входом пользователя, что иногда бывает в порядке, но выход асинхронен (он поступает через сетевое соединение в ответ на команды ввода), и иногда это раздражает (например, если строки выводятся, когда пользователь набирает новый ввод).

Я хотел бы добавить функцию в эту программу: отдельное «окно» для вывода. Я думал об использовании ncurses для этого. Но из ncurses FAQ видно, что две библиотеки не просто использовать вместе.

Я мог бы подумать об использовании Editline или tecla вместо Readline, но мне непонятно, сможет ли кто-нибудь из них решить мою проблему. Я бы также подумал об использовании чего-то другого, кроме ncurses, включая библиотеку, которая предоставляет обе функции (окна текстового режима и историю команд), но я не знаю, что может быть лучше.

О, и поддержка цветного текста может получить бонусные баллы. Я подозреваю, что смогу сделать это с помощью Readline, поэтому, возможно, это отдельная проблема, но если решение моей проблемы также упростит добавление немного цвета к выходу, тем лучше.

Я использую Ubuntu Hardy (Linux 2.6).

+0

Вы нашли решение? –

+0

Я сдался (и придерживался readline). –

ответ

6

Я сделал несколько поисков, и кажется, что вам не повезло.

Для альтернатив ncurses есть SLang, Newt и Turbo Vision. Сленг - это намного больше, чем просто обработка экрана и, следовательно, более сложный комплекс, но, возможно, он может быть использован для вашей цели ?. Ньют использует экран и намного проще, но слишком простой и однопоточный режим для вашей цели. Думаю.

Turbo vision - это графическая библиотека текстового режима от Borland, используемая всеми их инструментами в конце 80-х/начале 90-х годов. Borland выпустил исходный код , когда рынок для такого рода вещей уменьшился, и есть теперь порт для linux (примечание стороны, this project, похоже, написал свою собственную реализацию турбовидения). Этот порт не мертв (есть были некоторые обновления cvs в этом году, которые скомпилированы в порядке (более старые версии не сделали)), но ни один из примеров телевизоров, которые я нашел, не был обновлен, и я получил только некоторые из них скомпилировать, прежде чем отказаться от остальных. Это немного позор, потому что телевидение было прекрасной средой для использования. TV - это B ++ C++ (и я предполагаю, что вы используете C?).

Для альтернативы Readline есть libkinput, который, возможно, работает вместе с Ncurses (он говорит, что он может использовать Terminfo Ncurses. Но я не уверен, если это означает, что он может сосуществует вместе с использованием Ncurses)?

Возможно, одним из вариантов является запуск readline «извне» в вашу программу ncurses с использованием rlwrap?

+0

Сленг оказывается языком сам по себе. Также это лицензия GPL2 только для последней версии. Я ожидал, что это будет библиотека. – matiu

+0

Обратите внимание, что ньют - это слой над SLang. Это может быть проще в использовании, но это совсем другой вариант. –

2

Я не уверен, какую версию вы пробовали. На сегодняшний день (2012.09.14) Это очень просто. Нам просто нужно подключить нашу пользовательскую функцию к следующим указателям на функции.

 
rl_getch_function 
rl_redisplay_function 
rl_completion_display_matches_hook 

Я сделал что-то разумное here.

+0

Любые идеи о том, как сделать историю работы? – nccc

+1

ОК, я узнал. Нужно отобразить 'rl_display_prompt', затем' rl_line_buffer' и установить смещение курсора на 'rl_point + strlen (rl_display_prompt)'. – nccc

3

Итак, получается, что gdb использует как readline, так и ncurses. Если вы заинтересованы в этом, я рекомендую вам проверить их выполнение: http://sourceware.org/git/?p=gdb.git;a=blob;f=gdb/tui/tui-io.c

+0

Ничего себе, спасибо за это. И добро пожаловать в StackOverflow, Guillaume. :) –

5

Это был я стучал головой в течение нескольких часов, так что просто, чтобы спасти людей погуглить некоторую боль:

Если вы» re используя встроенный обработчик ncurses SIGWINCH обработчик с KEY_RESIZE, имейте в виду, что readline устанавливает значения переменных среды и COLUMNS. Они переопределяют любые вычисления динамического размера (обычно с TIOCGWINSZ), что в противном случае ncurses означало бы, что вы будете получать начальный размер терминала даже после изменения размера терминала.

Это можно предотвратить, установив rl_change_environment на 0 перед инициализацией readline.

Update:

Вот некоторая дополнительная информация, которую я почерпнутые из источников чтения строки:

SIGWINCH обработки кода ReadLine (который используется, если rl_catch_sigwinch является 1) не обновление LINES и COLUMNS, что кажется, что это должно быть достаточно для ncurses. Однако при использовании альтернативного интерфейса readline (что имеет смысл при объединении readline с ncurses), обработчики сигналов (включая один для SIGWINCH) будут установлены только на время каждого вызова rl_callback_read_char(), что означает, что любой терминал изменяет размер между двумя вызовами rl_callback_read_char() не будет видно по readline.

+1

Обратите внимание на [форматирование] (http://stackoverflow.com/help/formatting) вашего ответа. Команды/код трудно читать. – ryanyuyu

+1

@dotctor Спасибо за форматирование его для меня! – Ulfalizer

9

Теперь я собрал простую примерную программу на GitHub: https://github.com/ulfalizer/readline-and-ncurses.

Он поддерживает бесшовное и эффективное изменение размера и многобайтовых/комбинированных символов. Код содержит полезные комментарии.

Скриншот ниже:

Screenshot of program combining ncurses and readline

+0

Фантастический! Что такое лицензия на код? Я хотел бы интегрировать его с некоторыми материалами, лицензированными MIT, если это возможно. Благодаря! – cxw

+0

Рад, что это полезно! Я мог бы поставить его под MIT, если бы это было наименее хлопотно. В противном случае я бы пошел с ISC, и MIT выглядит похожим. У меня также есть версия, которая запускает цикл select() (или epoll() в этом случае), кстати, для https://github.com/ulfalizer/botniklas. Отвлекся и еще не подтолкнул его, но я мог бы сделать ветку, если тебе будет интересно. – Ulfalizer

+0

Эта версия устанавливает обработчик SIGWINCH (хотя вместо него используется обычный signalfd() вместо обычного обработчика) и позволяет readline читать непосредственно из stdin. Это также помогает устранить проблему с помощью поисковых и многобайтовых символов. – Ulfalizer