Использование GNU Readline; Как я могу добавить ncurses в той же программе?
Название немного более конкретное, чем моя настоящая цель:
У меня есть программа командной строки, которая использует GNU Readline, в основном для истории команд (т.е. извлечения предыдущих команд с помощью стрелки вверх) и некоторых других тонкостей. Прямо сейчас выходные данные программы перемежаются с пользовательским вводом, который иногда в порядке, но вывод асинхронный (он приходит через сетевое соединение в ответ на команды ввода), и это иногда раздражает (например, если строки выводятся, когда пользователь набирает новый ввод).
Я хотел бы добавить функцию к этой программе: отдельное "окно" для вывода. Я думал об использовании ncurses для этого. Но из часто задаваемых вопросов по ncurses видно, что две библиотеки не так просто использовать вместе.
Я мог бы рассмотреть возможность использования Editline или Tecla вместо Readline, но мне не ясно, решит ли кто-нибудь из них мою проблему. Я также хотел бы рассмотреть возможность использования чего-то другого, кроме ncurses, включая библиотеку, которая предоставляет оба вида функциональных возможностей (окна в текстовом режиме и историю команд), но я не знаю, что может быть лучше.
Да, и поддержка цветного текста может получить бонусные баллы. Я подозреваю, что смогу сделать это с помощью Readline, так что, возможно, это отдельная задача, но если решение моей проблемы также облегчает добавление цвета в вывод, тем лучше.
Я использую Ubuntu Hardy (Linux 2.6).
6 ответов
Я провел некоторые поиски, и кажется, что вам не повезло.
Для альтернатив ncurses есть SLang, Newt и Turbo Vision. Сленг - это гораздо больше, чем просто обработка экрана, и поэтому он более сложный, но, может быть, его можно использовать для ваших целей? Newt использует обработку экрана и является намного более простым, но я думаю, что он слишком простой и однопотоковый.
Turbo vision - это графическая библиотека текстового режима Borland, используемая всеми их инструментами в конце 80-х - начале 90-х годов. Borland выпустил исходный код, когда рынок для подобных вещей уменьшился, и теперь есть порт для Linux (примечание: этот проект, похоже, написал свою собственную реализацию Turbo Vision). Этот порт не умер (в этом году было несколько обновлений cvs, которые скомпилировались нормально (более старые выпуски этого не сделали)), но ни один из телевизионных примеров, которые я обнаружил, не был обновлен, и у меня было только несколько из них для компиляции до отказываться от отдыха. Это немного стыдно, потому что телевидение было прекрасной средой для использования. Телевизор между прочим C++ (и я предполагаю, что вы используете C?).
Для альтернативы readline есть libkinput, который может работать вместе с ncurses (он говорит, что может использовать terminfo ncurses. Но я не уверен, означает ли это, что он может сосуществовать вместе с использованием ncurses)?
Может быть, один из вариантов - запустить readline "внешне" для вашей программы ncurses, используя rlwrap?
Сейчас я собрал простой пример программы на GitHub: https://github.com/ulfalizer/readline-and-ncurses.
Он поддерживает плавное и эффективное изменение размера терминала и многобайтовые / комбинирующие / широкие символы. Код имеет полезные комментарии.
Снимок экрана ниже:
Это заставило меня удариться головой в течение нескольких часов, чтобы спасти людей.
Если вы используете встроенные ncurses SIGWINCH
обработчик с KEY_RESIZE
Имейте в виду, что readline устанавливает LINES
а также COLUMNS
переменные окружения по умолчанию. Они переопределяют любые динамические вычисления размера (обычно с ioctl()
TIOCGWINSZ
) что ncurses в противном случае сделает, то есть вы будете получать первоначальный размер терминала даже после изменения размера терминала.
Это можно предотвратить, установив rl_change_environment
в 0
перед инициализацией readline.
Обновить:
Вот некоторая дополнительная информация, которую я почерпнул из источников readline:
Readline-х SIGWINCH
код обработки (который используется, если rl_catch_sigwinch
1) обновляет LINES
а также COLUMNS
Кажется, что это должно быть достаточно для ncurses. Однако при использовании альтернативного интерфейса readline (что наиболее целесообразно при сочетании readline с ncurses), обрабатываются сигналы (в том числе для SIGWINCH
) будет установлен только на время каждого rl_callback_read_char()
вызов, означающий изменение размера любого терминала между двумя вызовами rl_callback_read_char()
не будет видно по readline.
Получается, что GDB использует readline и ncurses. Если вы заинтересованы в этом, я рекомендую вам проверить их реализацию: http://sourceware.org/git/?p=gdb.git;a=blob;f=gdb/tui/tui-io.c
Я достиг того, что вы описали в моей программе:
http://dpc.ucore.info/lab:xmppconsole
Ниже приведена обработка файла io:
Я не уверен, какую версию вы пробовали. На сегодняшний день (2012.09.14) Это очень просто, нам просто нужно привязать нашу пользовательскую функцию к указателям на следующие функции.
rl_getch_function rl_redisplay_function rl_completion_display_matches_hook
Я сделал что-то разумное здесь.