Ncurses — это библиотека, предназначенная для управления вводом-выводом на терминал. Позволяет задавать экранные координаты и цвет выводимых символов. Это статья является переводом данного материала. Пишите в комментариях, если нашли ошибку или неточность в переводе.
Материал рассчитан в первую очередь, на пользователей Unix-подобных ОС. Тем не менее, для пользователей Windows есть клон библиотеки ncurses
— PDcurses.
История
В стародавние времена все немногочисленные возможности терминалов (телетайп-терминалов) поддерживались с помощью последовательностей байт. Эти управляющие последовательности, обычно называемые escape
-последовательностями, начинались со специального символа 0x1B
.
Отголоски того времени дошли и до нас. Сегодня мы можем сделать то же самое со своим терминалом (на самом деле с эмулятором терминала, но для краткости, здесь и далее, называемым терминалом), используя точно такую же технологию.
Рассмотрим пример. Допустим, вам захотелось написать строку «In color» красным цветом. Для этого напишем в терминале (работает только для UNIX-подобных систем!):
echo "^[[0;31;40mIn color"
Первый символ является escape
-символом («^[», догадайтесь сами какой HEX-код у этого символа). Чтобы набрать его в терминале нужно нажать CTRL+V
, а затем ESC
. Дальше набираете так, как есть.
Результат выполнения команды:
Тот же трюк можно провернуть и программно:
#include <iostream>
int main()
{
std::cout << "\x1B[0;31;40mIn color" << std::endl;
return 0;
}
В С\C++
escape
-символы задаются символом \
(к примеру, \n
— переход на новую строку, \r
— возврат каретки). Соответственно, чтобы загнать escape
-символ 0×1B в поток, нужно вписать \x1B.
Представим, что вам захотелось в своей программе использовать различные цвета, чтобы программа выглядела красивее чем обычно. Не правда ли будет сложно запоминать значения каждых управляющих символов?
И к тому же, эти символы, скорее всего, различны для каждого типа терминала. Именно для того, чтобы избежать заучивания значения каждого символа, а также для написания кода, не зависящего от типа терминала, была придумана библиотека ncurses
.
Что такое ncurses и с чем его едят?
Изначально была библиотека под названием curses
(название произошло от сокращения «cursor optimization»). Эта библиотека работала напрямую с терминалом, используя API системы, и при этом позволяла разработчикам не заботиться о различных типах терминалов. Библиотека давала возможность приложению перемещать курсор, создавать окна (не GUI), управлять цветом, управлять мышью и т.д. без использования зависящих от системы управляющих символов.
ncurses
— это клон оригинальной curses
из System V Release 4.0 (SVr4), которая в свою очередь была улучшением классического curses
из BSD
(название произошло от «new curses»)
Но ncurses
это не только обёртка над зависимыми от системы управляющими символами, это так же и хороший фреймворк для создания красивого пользовательского интерфейса в текстовом режиме. Библиотека содержит функции управления окнами и меню, а так же «библиотеку-сестру» panel
, управляющую панелями.
Вот пример приложения, основанного на ncurses
:
Разумеется, это не все возможности, предоставляемые этой библиотекой. По мере продвижения вперёд, мы увидим гораздо больше, не сомневайтесь :)
Установка ncurses
Установить ncurses
очень просто.
Для этого откроем терминал и напишем:
sudo apt-get install libncursesw5-dev
Всё. Библиотека установлена и теперь мы готовы писать код.
Привет, мир! (Hello world!)
Итак, добро пожаловать в мир ncurses
. Перед погружением в библиотеку, напишем простую программу, которая скажет «Hello!» всему миру.
Чуть не забыл, чтобы компилировать программы, использующие библиотеку ncurses
, нужно устанавливать флаг -lncurses
:
gcc <программа> -lncurses
Код программы:
#include <ncurses.h>
int main()
{
initscr(); // Переход в curses-режим
printw("Hello world!\n"); // Отображение приветствия в буфер
refresh(); // Вывод приветствия на настоящий экран
getch(); // Ожидание нажатия какой-либо клавиши пользователем
endwin(); // Выход из curses-режима. Обязательная команда.
return 0;
}
Описание кода
ncurses.h
ncurses.h
— заголовочный файл ncurses
. В нём объявлены все функции и константы библиотек. Обязателен к подключению.
initscr()
Функция initscr()
переводит терминал в curses
-режим. Она чистит экран, выделяет память под необходимые данные для работы библиотеки, и инициализирует окно stdscr
(об этом не сегодня, к сожалению). Вызов initscr()
обязателен перед любым использованием ncurses
. В некоторых случаях функция может завершиться неудачно, если не хватило памяти. Впрочем, такие ситуации маловероятны, учитывая ресурсы, предоставленные современным компьютерам и ресурсы, требуемые для нормальной работы библиотеки.
printw()
Функция printw()
выполняет ту же роль что и printf()
, и имеет точно такой же синтаксис. Почему используется именно printw()
? Потому что std::cout
и printf()
на работают в curses
-режиме. В остальном эта функция полностью аналогична printf()
. Для справки: ввод осуществляется при помощи функции scanw()
(аналогично scanf()
).
refresh()
Функция printw()
отправляет данные не напрямую на экран, а в так называемый буфер. Функция refresh()
проверяет буфер и, если он не пуст, отправляет информацию на экран (обновляет только изменившиеся зоны экрана), она чем то схожа с flush()
из stdio
. Зачастую, её вызов не обязателен, но иногда без вызова этой функции можно получить странные ошибки.
getch()
Функция getch()
, наверное, знакома всем по библиотеке conio.h
. Так вот, это её полный аналог (даже чуть лучше, как мы увидим далее). Функция ожидает нажатие любой клавиши на клавиатуре и возвращает код этой самой клавиши.
endwin()
В конце не забывайте выйти из curses
-режима, иначе, после завершения программы ваш терминал будет «странно» себя вести. Выходом из curses
-режима занимается функция endwin()
. Она очищает экран, освобождает память, которую выделяла initscr()
и переводит терминал в нормальный режим (в тот, в котором он был до выполнения программы).
Продолжение: Управление режимом работы терминала в Ncurses →.
Комментарии к статье: 12
Возможность комментировать эту статью отключена автором. Возможно, во всем виновата её провокационная тематика или большое обилие флейма от предыдущих комментаторов.
Если у вас есть вопросы по содержанию статьи, рекомендуем вам обратиться за помощью на наш форум.