Использование GNU Readline; как я могу добавить ncurses в ту же программу?

Название немного более конкретное, чем моя настоящая цель:

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

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

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

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

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


person John Zwinck    schedule 27.03.2009    source источник
comment
Я сдался (и придерживался строки чтения).   -  person John Zwinck    schedule 11.06.2010


Ответы (6)


Я немного поискал, и, похоже, вам не повезло.

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

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

Альтернативой readline является libkinput, который, возможно, работает вместе с ncurses (он говорит, что может использовать terminfo ncurses. но я не уверен, означает ли это, что он может сосуществовать вместе с использованием ncurses)?

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

person hlovdal    schedule 28.03.2009
comment
сленг сам по себе оказывается языком. Также это лицензия GPL2 только на последнюю версию. Я ожидал, что это будет библиотека. - person matiu; 23.08.2016
comment
Обратите внимание, что Newt - это слой над SLang. Это может быть проще в использовании, но это совершенно другой вариант. - person Alexis Wilke; 17.01.2018

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

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

Снимок экрана ниже:

Скриншот программы, объединяющей ncurses и readline

person Ulfalizer    schedule 25.02.2015
comment
Фантастика! Какой код лицензии? Я бы хотел интегрировать его с некоторыми материалами, лицензированными MIT, если это возможно. Спасибо! - person cxw; 20.05.2015
comment
Рад, что это помогло! Я мог бы передать это в MIT, если бы это было меньше всего хлопот. В противном случае я бы пошел с ISC, и MIT выглядит похожим. У меня также есть версия, которая запускает цикл select () (или epoll () в данном случае), кстати, для github.com/ulfalizer/botniklas. Отвлекся и еще не продвинул его, но я мог бы сделать для него ветку, если вам будет интересно. - person Ulfalizer; 21.05.2015
comment
Эта версия устанавливает обработчик SIGWINCH (хотя и использует signalfd () вместо обычного обработчика) и позволяет readline читать прямо из stdin. Это также помогает решить проблему с поиском и многобайтовыми символами. - person Ulfalizer; 21.05.2015
comment
Это здорово, но на OS X El Capitan Terminal функция прокрутки не поддерживается. Вместо этого он прокручивает историю readline. Возможно, это как-то связано с этим: macissues.com/2014/06/10/ - person Adam; 24.01.2016
comment
@ Адам: Прокрутки нет. Верхнее окно было добавлено только для того, чтобы получить более интересный макет и действительно что-то сделать с вводом из строки чтения в примере. - person Ulfalizer; 01.10.2016

Из-за этого я несколько часов бился головой, просто чтобы спасти людей, которые гуглили немного от боли:

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

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

Обновление:

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

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

person Ulfalizer    schedule 17.02.2015
comment
Пожалуйста, подумайте о форматировании своего ответа. Команды / код трудно читать. - person ryanyuyu; 18.02.2015

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

person Guillaume    schedule 06.05.2013
comment
Вау, спасибо за это. И добро пожаловать в StackOverflow, Гийом. :) - person John Zwinck; 07.05.2013

Я добился того, что вы описали в своей программе:

http://dpc.ucore.info/lab:xmppconsole

Ниже приводится обработка файлов io:

http://github.com/dpc/xmppconsole/blob/master/src/io.c

person dpc.pw    schedule 09.06.2010

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

rl_getch_function
rl_redisplay_function
rl_completion_display_matches_hook

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

person mohan43u    schedule 14.09.2012
comment
Хорошо, я узнал. Нужно отобразить rl_display_prompt, затем rl_line_buffer и установить смещение курсора на rl_point + strlen(rl_display_prompt). - person nccc; 14.02.2013