Обновлен модуль сессии. Добавлено чтение нажатия клавиш. Безопасная инициализация сессии. Новые параметры: keypad и escDelay. Обновлены функции проверки вызовов ncurses-функций.
This commit is contained in:
parent
a5778d0de5
commit
057b62b58e
1 changed files with 93 additions and 16 deletions
|
|
@ -1,12 +1,33 @@
|
|||
module ncui.core.session;
|
||||
|
||||
import core.stdc.locale : setlocale, LC_ALL;
|
||||
import std.exception : enforce;
|
||||
|
||||
import deimos.ncurses;
|
||||
|
||||
import ncui.core.ncwin;
|
||||
import ncui.lib.common;
|
||||
import ncui.lib.checks;
|
||||
import ncui.core.event;
|
||||
|
||||
/**
|
||||
* Глобальный флаг инициализации ncurses для всего процесса.
|
||||
*
|
||||
* Хранит "истину" о том, выполнялась ли успешная инициализация (`initscr()`).
|
||||
* Используется для защиты от повторной инициализации и для быстрых проверок
|
||||
* перед вызовами функций, требующих активной ncurses-сессии.
|
||||
*/
|
||||
private __gshared bool gInitialized;
|
||||
|
||||
/**
|
||||
* Проверяет, была ли ncurses-сессия уже инициализирована в текущем процессе.
|
||||
*
|
||||
* Возвращает:
|
||||
* `true`, если ранее была выполнена успешная инициализация (и был поднят `gInitialized`),
|
||||
* иначе `false`.
|
||||
*/
|
||||
bool cursesInitialized() @nogc nothrow
|
||||
{
|
||||
return gInitialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Уровень видимости/типа курсора.
|
||||
|
|
@ -28,7 +49,7 @@ enum Cursor : int
|
|||
/**
|
||||
* Режим обработки ввода терминалом.
|
||||
*
|
||||
* - `common` — канонический (построчный) режим — ввод приходит после Enter.
|
||||
* - `cooked` — канонический (построчный) режим — ввод приходит после Enter.
|
||||
* - `cbreak` — посимвольный режим — символы доступны сразу, но часть спец-клавиш/
|
||||
* управляющих символов всё ещё может обрабатываться терминалом (сигналы).
|
||||
* - `raw` — "сырой" посимвольный режим — минимальная обработка терминалом,
|
||||
|
|
@ -41,7 +62,7 @@ enum InputMode
|
|||
/// Сырой посимвольный ввод с минимальной обработкой терминалом.
|
||||
raw,
|
||||
/// Канонический построчный ввод (поведение "как в обычной консоли").
|
||||
common
|
||||
cooked
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -59,6 +80,22 @@ enum Echo
|
|||
off
|
||||
}
|
||||
|
||||
/**
|
||||
* Режим обработки специальных клавиш в ncurses (`keypad`).
|
||||
*
|
||||
* Когда режим включён, ncurses преобразует специальные клавиши (стрелки, Home/End,
|
||||
* PgUp/PgDn, F1..F12 и т.п.) в коды `KEY_*`, которые удобно обрабатывать в программе.
|
||||
* Когда выключён — многие такие клавиши приходят как последовательности символов
|
||||
* (escape-последовательности), и их приходится разбирать вручную.
|
||||
*/
|
||||
enum Keypad : bool
|
||||
{
|
||||
/// Включить обработку специальных клавиш (`KEY_*`).
|
||||
on = true,
|
||||
/// Выключить обработку специальных клавиш.
|
||||
off = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Конфигурация терминальной сессии.
|
||||
*
|
||||
|
|
@ -66,6 +103,11 @@ enum Echo
|
|||
* - `mode` — режим ввода.
|
||||
* - `cursor` — видимость/тип курсора.
|
||||
* - `echo` — отображать ли вводимые символы.
|
||||
* - `keypad` — включение обработки специальных клавиш (стрелки, F-клавиши → `KEY_*`).
|
||||
* - `escDelay` — задержка (в миллисекундах) для различения одиночного `Esc` и
|
||||
* escape-последовательностей (стрелки и т.п.). Обычно 0..50 для
|
||||
* отзывчивого UI; слишком маленькое значение может повлиять на
|
||||
* корректность распознавания некоторых клавиш в отдельных терминалах.
|
||||
*/
|
||||
struct SessionConfig
|
||||
{
|
||||
|
|
@ -75,6 +117,10 @@ struct SessionConfig
|
|||
Cursor cursor = Cursor.normal;
|
||||
/// Эхо ввода. По умолчанию отображает вводимые символы (`on`).
|
||||
Echo echo = Echo.on;
|
||||
/// Обработка специальных клавиш (стрелки, Home/End, PgUp/PgDn, F1..F12 → `KEY_*`).
|
||||
Keypad keypad = Keypad.on;
|
||||
/// Задержка распознавания ESC/escape-последовательностей в миллисекундах.
|
||||
int escDelay = 50;
|
||||
}
|
||||
|
||||
final class Session
|
||||
|
|
@ -89,48 +135,79 @@ private:
|
|||
final switch (config.mode)
|
||||
{
|
||||
case InputMode.raw:
|
||||
ncuiCall!nocbreak(OK);
|
||||
ncuiCall!raw(OK);
|
||||
ncuiNotErr!nocbreak();
|
||||
ncuiNotErr!raw();
|
||||
break;
|
||||
|
||||
case InputMode.cbreak:
|
||||
ncuiCall!noraw(OK);
|
||||
ncuiCall!cbreak(OK);
|
||||
ncuiNotErr!noraw();
|
||||
ncuiNotErr!cbreak();
|
||||
break;
|
||||
|
||||
case InputMode.common:
|
||||
ncuiCall!noraw(OK);
|
||||
ncuiCall!nocbreak(OK);
|
||||
case InputMode.cooked:
|
||||
ncuiNotErr!noraw();
|
||||
ncuiNotErr!nocbreak();
|
||||
break;
|
||||
}
|
||||
// Настройка отображения вводимых символов.
|
||||
final switch (config.echo)
|
||||
{
|
||||
case Echo.on:
|
||||
ncuiCall!echo(OK);
|
||||
ncuiNotErr!echo();
|
||||
break;
|
||||
|
||||
case Echo.off:
|
||||
ncuiCall!noecho(OK);
|
||||
ncuiNotErr!noecho();
|
||||
break;
|
||||
}
|
||||
// Настройка видимости курсора.
|
||||
ncuiNotErr!curs_set(config.cursor);
|
||||
// Настройка задержки при нажатии на ESC
|
||||
ncuiNotErr!set_escdelay(config.escDelay);
|
||||
// Настройка обработки специальных клавиш
|
||||
ncuiNotErr!keypad(_root, config.keypad);
|
||||
}
|
||||
|
||||
public:
|
||||
this(const SessionConfig config)
|
||||
{
|
||||
// ncurses не должен быть инициализирован (false)
|
||||
ncuiExpectMsg!cursesInitialized("ncurses is already initialized", false);
|
||||
// Адекватное чтение юникода.
|
||||
setlocale(LC_ALL, "");
|
||||
_root = NCWin(ncuiNotNull!initscr());
|
||||
|
||||
// Если на этапе инициализации сработает проблема с конфигурированием сессии
|
||||
scope (failure)
|
||||
{
|
||||
endwin();
|
||||
gInitialized = false;
|
||||
}
|
||||
|
||||
// Установить флаг инициализации ncurses
|
||||
gInitialized = true;
|
||||
setup(config);
|
||||
}
|
||||
|
||||
NCWin root()
|
||||
{
|
||||
return _root;
|
||||
}
|
||||
|
||||
KeyEvent readKey(NCWin inputWindow)
|
||||
{
|
||||
dchar ch;
|
||||
int status = wget_wch(inputWindow, &ch);
|
||||
return KeyEvent(status, ch);
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if (_ended)
|
||||
return;
|
||||
endwin();
|
||||
_ended = true;
|
||||
gInitialized = false;
|
||||
}
|
||||
|
||||
~this()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue