TTY

Модуль терминального UI для событий сырого ввода, стилизованного вывода и утилит компоновки.

Этот модуль работает только в контексте терминала. Его нельзя использовать из обычных функций — только из процессов, запущенных на Terminal Host.

Загрузка

local tty = require("tty")

Цикл ввода

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

local tty = require("tty")
local io = require("io")

local function handler()
    tty.start()
    local events = tty.events()

    while true do
        local ev = events:receive()
        if not ev then break end

        if ev.type == "key" then
            if ev.key == "q" or (ev.ctrl and ev.key == "c") then
                break
            end
            io.print("Key: " .. ev.key)

        elseif ev.type == "resize" then
            io.print("Size: " .. ev.width .. "x" .. ev.height)
        end
    end

    tty.stop()
end

Управление вводом

tty.start()

Включить режим сырого ввода терминала. Терминал переключается в raw-режим и начинает выдавать события.

local ok, err = tty.start()

Возвращает: boolean, error

tty.stop()

Отключить сырой ввод и вернуть терминал в нормальный режим.

local ok, err = tty.stop()

Возвращает: boolean, error

tty.events()

Подписаться на события терминала и вернуть канал. События доставляются в виде таблиц с полем type.

local events = tty.events()

Возвращает: EventChannel

tty.screen_size()

Запросить текущие размеры терминала.

local width, height, err = tty.screen_size()

Возвращает: number, number, error

tty.mouse(enable)

Включить или отключить отслеживание событий мыши.

local ok, err = tty.mouse(true)
Параметр Тип Описание
enable boolean true для включения, false для отключения

Возвращает: boolean, error

Типы событий

События — это таблицы с полем type, которое определяет, какие другие поля присутствуют.

Событие клавиши

{
    type = "key",
    key = "a",           -- печатный символ или имя клавиши
    key_type = "runes",  -- "runes" для печатных, или имя специальной клавиши
    action = "press",    -- "press" или "release"
    alt = false,
    ctrl = false,
    shift = false
}

Событие мыши

Требует tty.mouse(true).

{
    type = "mouse",
    action = "press",    -- "press", "release", "motion", "wheel"
    button = "left",     -- имя кнопки
    x = 10,
    y = 5,
    alt = false,
    ctrl = false,
    shift = false
}

Событие изменения размера

{type = "resize", width = 120, height = 40}

Событие старта

Выдаётся один раз после tty.start() с начальными размерами.

{type = "start", width = 120, height = 40}

Событие фокуса

{type = "focus", focused = true}

Событие вставки

{type = "paste", text = "pasted content"}

Привязки клавиш

Создавайте переиспользуемые привязки клавиш, которые сопоставляются с событиями клавиш:

local quit = tty.bind({
    keys = {"q", "ctrl+c"},
    help = {key = "q/ctrl+c", desc = "quit"}
})

-- В цикле событий
if quit:matches(ev) then
    break
end

tty.bind(config)

Поле Тип Описание
keys string[] Шаблоны клавиш для сопоставления (например, "a", "ctrl+c", "enter")
help table Опционально. {key = "...", desc = "..."} для текста справки

Возвращает: KeyBinding

Методы KeyBinding

Метод Возвращает Описание
matches(event) boolean Проверить, соответствует ли событие клавиши этой привязке
set_enabled(bool) self Включить или отключить привязку
is_enabled() boolean Проверить, включена ли привязка
help() table Возвращает справочную информацию {key, desc}

Стили

Создавайте стилизованный текстовый вывод с помощью стилизации на базе lipgloss. Все методы стиля возвращают новый стиль (immutable).

local tty = require("tty")
local io = require("io")

local title = tty.style()
    :bold()
    :foreground("#FF0000")
    :padding(0, 1)

local box = tty.style()
    :border(tty.borders.ROUNDED)
    :border_foreground("#00FF00")
    :width(40)
    :padding(1, 2)

io.print(box:render(title:render("Hello"), "World"))

tty.style()

Создать новый пустой стиль.

Возвращает: Style

Методы Style

Все методы возвращают новый Style и могут быть зацеплены.

Декорация текста

Метод Параметр Описание
foreground(color) string Цвет текста (hex "#FF0000", ANSI "9" или имя)
background(color) string Цвет фона
bold(enable?) boolean Жирный текст (по умолчанию: true)
italic(enable?) boolean Курсивный текст
underline(enable?) boolean Подчёркнутый текст
strikethrough(enable?) boolean Перечёркнутый текст
faint(enable?) boolean Приглушённый текст
blink(enable?) boolean Мигающий текст
reverse(enable?) boolean Поменять местами цвет текста и фона

Компоновка

Метод Параметр Описание
width(n) number Фиксированная ширина
height(n) number Фиксированная высота
max_width(n) number Максимальная ширина
max_height(n) number Максимальная высота
padding(...) numbers Внутренний отступ (CSS-стиль: top, right, bottom, left)
margin(...) numbers Внешний отступ (CSS-стиль)
align(pos) number Горизонтальное выравнивание
align_vertical(pos) number Вертикальное выравнивание
inline(enable?) boolean Inline-режим рендеринга

Границы

Метод Параметр Описание
border(name, ...) string, booleans Стиль границы, опциональные переключатели по сторонам
border_foreground(...) strings Цвет(а) границы
border_background(...) strings Цвет(а) фона границы

Прочее

Метод Описание
render(...) Отрендерить строки с применённым стилем
copy() Создать копию этого стиля

Константы границ

tty.borders.NORMAL
tty.borders.ROUNDED
tty.borders.THICK
tty.borders.DOUBLE
tty.borders.HIDDEN

Константы выравнивания

tty.align.LEFT    -- 0
tty.align.CENTER  -- 0.5
tty.align.RIGHT   -- 1

Утилиты текста

Функции компоновки и измерения для стилизованного текста. Доступны под tty.text.

Измерение

local w = tty.text.width("hello")         -- печатная ширина (с учётом ANSI)
local h = tty.text.height("a\nb\nc")      -- количество строк
local w, h = tty.text.size("hello\nworld") -- оба значения

Соединение

-- Соединить бок о бок, выровняв по верху
local row = tty.text.join_horizontal(tty.text.position.TOP, left, right)

-- Сложить вертикально, центрировано
local col = tty.text.join_vertical(tty.text.position.CENTER, top, bottom)

Максимальные размеры

local w = tty.text.max_width({"short", "a longer string"})   -- самое широкое
local h = tty.text.max_height({"one\ntwo", "single"})         -- самое высокое

Размещение

Поместить строку внутри области заданных размеров:

-- Центрировать в области 80x24
local out = tty.text.place(80, 24, tty.text.position.CENTER, tty.text.position.CENTER, content)

-- Только горизонтально
local out = tty.text.place_horizontal(80, tty.text.position.RIGHT, content)

-- Только вертикально
local out = tty.text.place_vertical(24, tty.text.position.BOTTOM, content)

Константы позиции

tty.text.position.TOP      -- 0
tty.text.position.LEFT     -- 0
tty.text.position.CENTER   -- 0.5
tty.text.position.BOTTOM   -- 1
tty.text.position.RIGHT    -- 1

См. также